# STM32F429 Discovery kit ## 1. GPIO (General Purpose Input / Output) [TOC] ### (1) 參考 [成大資工wiki-GPIO介紹](http://wiki.csie.ncku.edu.tw/embedded/GPIO#stm32f4xx-gpio%E7%89%B9%E6%80%A7) 1. GPIO : 四種功能`input` `output` `alternate functions` `analog` 2. `alternate functions` : 週邊硬體功能 (e.g.`UART`,`I2C`) 3. STM32F4xx 每個 GPIO Port 有 **10** 個 **32-bit 暫存器 (Register)** 4. GPIOx : 共有**9個Ports** (從A到I) <!-- 放截圖 --> ![](https://i.imgur.com/I2YgtLt.png) :::danger **Push-Up / Push-Down** 是為了避免**電壓floating**導致**信號不明確**的問題。 * Push-Up : default 為 High * Push-Down : default 為 Low ::: > TLL Schmitt Trigger : > 一種整流電路,目的為使**輸入的類比訊號**轉換為**數位方波** >* 原理 : >高於一個閾值的信號:設為 High >小於: 設為 Low ### (2) Hardware Block Diagram (including Clock-tree) * 使用週邊功能步驟: 1. 設定週邊 (UART,SPI,USB...etc.) 2. 設定GPIO 正確電路型態(AF mode) 3. 根據週邊、GPIO : 管理**時鐘** (正確設定) ![](https://i.imgur.com/JtRl7XH.png) * Bus : 大致分AHB和APB兩種 `AHB`:高速 (H : High speed高速的) `APB`:較慢 (P : peripharal週邊的) :::warning 若往後要用特殊功能(如**SPI**),先了解該功能工作**Clock頻率**,再確認對應system clock的頻率,決定要**除頻多少**。否則不能正常工作。 ::: #### 簡易電路區塊說明: ![](https://i.imgur.com/QyUYNcn.png) * 左上角JTAG & SW : 外部debug電路 * ARM Cortex-M4 : CPU * DMA : Direct Memory Access * 中間Flash, SRAM等記憶體 * RNG : Random Number Generator. --- ![](https://i.imgur.com/03edFgH.png) * GPIO PORT A~K --- ![](https://i.imgur.com/rAWZyTC.png) * SPI: MOSI (Master-out, Slave-in) MISO (Master-in, Slave-out) * Voltage regulator: 穩壓功能 * XTAL OSC : 外部石英震盪器 XTAL 32kHz : **GPIO PC14, PC15** XTAL 4-16kHz : **GPIO PH0, PH1 * RTC : Real-Time Clock #### Clock Tree ![](https://i.imgur.com/92AUT2u.jpg) :::info **鎖相迴路(PLL: Phase-locked loops)** 是一種利用反饋(Feedback)控制原理實現的頻率及相位的同步技術,其作用是將電路輸出的時鐘與其外部的參考時鐘保持同步。 >引用自**維基百科** ::: #### MMIO (Memory Mapped I/O) * 在撰寫程式碼時,針對某個Register對應的Pin腳的設定,其實是**先對Memory寫入**,MCU內建的**Controller**再對Register寫入。 ![](https://i.imgur.com/y2jsC1n.png) ### (3) 範例程式碼 #### 1. 檔案格式說明 ![](https://i.imgur.com/SvpH46e.png) :::success `.c` : C files. `.h` : Header files. `.s` : Assembly codes. `.ld`: Linker Script. `.o` : Object files. Compiler 生成`目標檔`,再Link其他libraries. `.elf` : UNIX OS下的執行黨 `.bin` : 燒錄到stm之檔案 ::: #### 2. 如何從eclipse編譯project,再使用ST-LINK Utility燒錄到開發版? 1. 從eclipse(luna)版,按下`Build` 2. 若`Build`成功,確認路徑:`Project/Debug/`是否生成一個`.hex`檔案 3. 將STM32開發版**插入電腦**,開啟**ST-LINK Utility** 4. 先點選`open/file`,放入剛剛的`.hex`檔案 5. 點選`connect`連接到開發版 6. 點選`Program & Verify` ::: danger 如果都沒有error訊息則大功告成 ::: ![](https://i.imgur.com/ELPeX5v.png =300x) ![](https://i.imgur.com/r82zvRL.png) #### 3. Import Exam1_LED 此範例程式為練習用GPIO控制LED的閃爍 :::success 如何知道LED對應到哪些**Port**和**Pin**? ::: 本開發版的LED對應之GPIO Port 為 GPIO**G**的 `PG13` `PG14`兩個腳位,可從Schematics找到 ![](https://i.imgur.com/2lYDrhK.png) 因此 `Blink_led.h`檔中的`Blink_Port_Number`和`Blink_Pin_Number`應該設為 6和13(6=G, 13) ![](https://i.imgur.com/wE6T4jF.png) #### In `BlinkLed.c` ``` C= #include "BlinkLed.h" // ---------------------------------------------------------------------------- // RCC : Reset and clock controL register. void blink_led_init() { // Enable GPIO Peripheral clock RCC->AHB1ENR |= BLINK_RCC_MASKx(BLINK_PORT_NUMBER); // Use struct type definition. GPIO_InitTypeDef GPIO_InitStructure; // Configure pin in output push/pull mode GPIO_InitStructure.Pin = BLINK_PIN_MASK(BLINK_PIN_NUMBER); GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; GPIO_InitStructure.Pull = GPIO_NOPULL; HAL_GPIO_Init(BLINK_GPIOx(BLINK_PORT_NUMBER), &GPIO_InitStructure); // Start with led turned off blink_led_off(); } ``` **Note:** 把Pin設好後,要先把該Port對應的**Clock** 設定好(打開)才會正常運作 此範例中的GPIO**G**對應之clock可從上**Clock tree**圖找出為 `AHB1` 所以才會有這行程式碼: ``` C= RCC->AHB1ENR |= BLINK_RCC_MASKx(BLINK_PORT_NUMBER); ``` 可以從`BlinkLed.h`檔案找出`BLINK_RCC_MASKx() `的定義: ```= #define BLINK_RCC_MASKx(_N) (RCC_AHB1ENR_GPIOAEN << (_N)) ``` 可知function `BLINK_RCC_MASKx(_N)`會接收參數`PORT_NUMBER`並將Register `RCC_AHB1ENR_GPIOAEN` 的第 **_N** 個bit設為 1 表示將`AHB1`這條Bus連到的Port `GPIOG`的Enable打開。 #### In `BlinkLed.h` ``` C= // ----- LED definitions ------------------------------------------------------ // Adjust these definitions for your own board. #if defined(BOARD_OLIMEX_STM32_E407) // STM32-E407 definitions (the GREEN led, C13, active low) // Port numbers: 0=A, 1=B, 2=C, 3=D, 4=E, 5=F, 6=G, ... #define BLINK_PORT_NUMBER (2) #define BLINK_PIN_NUMBER (13) #define BLINK_ACTIVE_LOW (1) #else // STM32F4DISCOVERY definitions (the GREEN led, D12, active high) // (SEGGER J-Link device name: STM32F407VG). #define BLINK_PORT_NUMBER (5) #define BLINK_PIN_NUMBER (6) #define BLINK_ACTIVE_LOW (1) #endif #define BLINK_GPIOx(_N) ((GPIO_TypeDef *)(GPIOA_BASE + (GPIOB_BASE-GPIOA_BASE)*(_N))) #define BLINK_PIN_MASK(_N) (1 << (_N)) #define BLINK_RCC_MASKx(_N) (RCC_AHB1ENR_GPIOAEN << (_N)) ``` #### 另一個範例: 下面為網路上參考一個範例程式 因為他們不是用我們的型號 `stm32f429` 所以他LED Port跟pin的設定不太依樣 他是 `GPIOD`的第`12 13 14 15`四個Pin 即 `PG12` `PG13` `PG14` `PG15` 四個針腳 ``` C= #include <stm32f4xx.h> #include <stm32f4xx_gpio.h> void delay(uint32_t count) { while(count--); } void init_GPIO() { GPIO_InitTypeDef GPIO_InitStruct = { .GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15, .GPIO_Mode = GPIO_Mode_OUT, .GPIO_Speed = GPIO_Speed_50MHz, .GPIO_OType =GPIO_OType_PP, .GPIO_PuPd = GPIO_PuPd_DOWN }; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); GPIO_Init(GPIOD, &GPIO_InitStruct); } int main() { init_GPIO(); int digitStatus = 1; while(1) { GPIO_WriteBit(GPIOD, GPIO_Pin_12, digitStatus); delay(1000000L); GPIO_WriteBit(GPIOD, GPIO_Pin_13, digitStatus); delay(1000000L); GPIO_WriteBit(GPIOD, GPIO_Pin_14, digitStatus); delay(1000000L); GPIO_WriteBit(GPIOD, GPIO_Pin_15, digitStatus); delay(1000000L); digitStatus = (digitStatus + 1) % 2; } return 0; } ``` ### (4) 補充資料 **STM32_cube** [STM32Cube](https://www.st.com/content/st_com/en/stm32cube-ecosystem.html)官方網站 ###### tags: `STM32f429 Discovery kit`