STM32F411RE簡單的GPIO控制與調試


媽蛋,先插了代碼文字要打在里面了,管不了了。昨天開始准備在STM32F411RE上對TLC59401進行軟件驗證,雲上不能調試,於是在本地搭建環境,搭了半天,深感公司對於信息安全的重視程度到了令人發指的地步。
以下為吐槽,閑雜人等可以跳過。
首先因為本地只能上內網,所以把IAR相關的軟件和Licence破解之類的工具通過greenetrans傳到本地,本地安裝了半天。。。
調試要代碼吧要庫吧,於是把代碼打包,准備通過綠傳傳到本地,突然發現,被檢測到是代碼就給我rejected了。。。我日。。
怎么辦?
SVN?不行,那是管理版本的怎么能用來給我傳代碼。。
不過機制的我機智地把代碼壓縮分卷成了好幾份,Espace傳給同事小伙伴,然后下線,在本地登陸Espace,讓小伙伴再傳過來。。
真累啊。。。
。。。
終於環境搭好了,二話不說,進主題。

先看main函數如下:


1 /** 2 * @brief Main program 3 * @param None 4 * @retval None 5 */ 6 int main(void) 7 { 8 /* STM32F4xx HAL library initialization: 9 - Configure the Flash prefetch, instruction and Data caches 10 - Configure the Systick to generate an interrupt each 1 msec 11 - Set NVIC Group Priority to 4 12 - Global MSP (MCU Support Package) initialization 13 */ 14 HAL_Init(); 15 16 /* Configure the system clock to 100 MHz */ 17 SystemClock_Config(); 18 19 /*##-1- Enable GPIOA Clock (to be able to program the configuration registers) */ 20 __HAL_RCC_GPIOA_CLK_ENABLE(); 21 22 /*##-2- Configure PA05 IO in output push-pull mode to drive external LED ###*/ 23 GPIO_InitStruct.Pin = GPIO_PIN_5; 24 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; //推挽輸出 25 GPIO_InitStruct.Pull = GPIO_NOPULL ; //默認懸空 26 GPIO_InitStruct.Speed = GPIO_SPEED_FAST; //管腳響應速度配置 27 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); 28 29 /*##-3- Toggle PA05 IO in an infinite loop #################################*/ 30 unsigned int i=0; 31 while (1) 32 { 33 ((++i)%2==0)?(HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET)):(HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_RESET)); 34 //HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); 35 //HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,1); 36 /* Insert a 100ms delay */ 37 HAL_Delay(100); 38 } 39 }
 1 typedef struct
 2 {
 3   uint32_t Pin;       /*!< Specifies the GPIO pins to be configured.
 4                            This parameter can be any value of @ref GPIO_pins_define */
 5 
 6   uint32_t Mode;      /*!< Specifies the operating mode for the selected pins.
 7                            This parameter can be a value of @ref GPIO_mode_define */
 8 
 9   uint32_t Pull;      /*!< Specifies the Pull-up or Pull-Down activation for the selected pins.
10                            This parameter can be a value of @ref GPIO_pull_define */
11 
12   uint32_t Speed;     /*!< Specifies the speed for the selected pins.
13                            This parameter can be a value of @ref GPIO_speed_define */
14 
15   uint32_t Alternate;  /*!< Peripheral to be connected to the selected pins. 
16                             This parameter can be a value of @ref GPIO_Alternate_function_selection */
17 }GPIO_InitTypeDef;

來看GPIO_Initstruct的定義,

里面有Pin—管腳號;

Mode-輸入模式或者輸出模式,其中輸出又分為推挽輸出和開漏輸出,不了解的同學可以去查閱相關資料,簡單地說如果你想要電平轉換速度快的話,那么就選push-pull,但是缺點是功耗相對會大些。
如果你想要功耗低,且同時具有“線與”的功能,那么就用open-drain的模式;

Pull—默認時的狀態,上拉下拉還是浮空,即初始電平;

Speed—設置IO口響應速度;

Alternate—這個不清楚,沒用過,似乎也沒啥用。

 

main函數的init配置里有GPIO_InitStruct.Pin = GPIO_PIN_5;

我們來看GOIO_PIN_5等於什么?

 1 #define GPIO_PIN_0                 ((uint16_t)0x0001U)  /* Pin 0 selected    */
 2 #define GPIO_PIN_1                 ((uint16_t)0x0002U)  /* Pin 1 selected    */
 3 #define GPIO_PIN_2                 ((uint16_t)0x0004U)  /* Pin 2 selected    */
 4 #define GPIO_PIN_3                 ((uint16_t)0x0008U)  /* Pin 3 selected    */
 5 #define GPIO_PIN_4                 ((uint16_t)0x0010U)  /* Pin 4 selected    */
 6 #define GPIO_PIN_5                 ((uint16_t)0x0020U)  /* Pin 5 selected    */
 7 #define GPIO_PIN_6                 ((uint16_t)0x0040U)  /* Pin 6 selected    */
 8 #define GPIO_PIN_7                 ((uint16_t)0x0080U)  /* Pin 7 selected    */
 9 #define GPIO_PIN_8                 ((uint16_t)0x0100U)  /* Pin 8 selected    */
10 #define GPIO_PIN_9                 ((uint16_t)0x0200U)  /* Pin 9 selected    */
11 #define GPIO_PIN_10                ((uint16_t)0x0400U)  /* Pin 10 selected   */
12 #define GPIO_PIN_11                ((uint16_t)0x0800U)  /* Pin 11 selected   */
13 #define GPIO_PIN_12                ((uint16_t)0x1000U)  /* Pin 12 selected   */
14 #define GPIO_PIN_13                ((uint16_t)0x2000U)  /* Pin 13 selected   */
15 #define GPIO_PIN_14                ((uint16_t)0x4000U)  /* Pin 14 selected   */
16 #define GPIO_PIN_15                ((uint16_t)0x8000U)  /* Pin 15 selected   */
17 #define GPIO_PIN_All               ((uint16_t)0xFFFFU)  /* All pins selected */

可以看到GPIO_PIN_5十六進制表示就是0x0020U,轉換為二進制即0000 0000 0010 0000 對應的就是第六個管腳PIN5。

同樣地,結構體里別的變量的值的設置其實就是按datasheet里寄存器的配置把十六位二進制轉成四位十六進制,然后通過define定義為各種名稱,應該很容易理解。

 

 1 ((++i)%2==0)?(HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET)):(HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_RESET)); 

while里的這句是要實現什么呢?

是的,就是根據i的奇偶來交替拉高拉低IO口電平。

 1 void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
 2 {
 3   /* Check the parameters */
 4   assert_param(IS_GPIO_PIN(GPIO_Pin));
 5   assert_param(IS_GPIO_PIN_ACTION(PinState));
 6 
 7   if(PinState != GPIO_PIN_RESET)
 8   {
 9     GPIOx->BSRR = GPIO_Pin;
10   }
11   else
12   {
13     GPIOx->BSRR = (uint32_t)GPIO_Pin << 16U;
14   }
15 }

看HAL_GPIO_WritePin,GPIOx和GPIO_Pin就不提了,主要是PinState,當它非零時(=。=GPIO_PIN_RESET肯定是0啦我用膝蓋想一下就知道)給GPIOx->BSRR寫入GPIO_Pin,即把相對應的管腳為1的電平拉高;

如果它為零時,就GPIOx->BSRR=0000 0000 0000 0000啦,所有管腳拉低,即復位。

 

很簡單的內容,要實現的也能簡單,我這里GPIOA_Pin5連着LED二極管,所以燒寫后效果就是100ms亮、100ms滅交替進行下去。

一年多沒用過MCU了,算是新的開始吧。以后解決了什么問題也會在blog更新。

也希望新人們通過看我這個筆記,能夠更加清楚地了解單片機的工作原理。

:) 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM