媽蛋,先插了代碼文字要打在里面了,管不了了。昨天開始准備在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更新。
也希望新人們通過看我這個筆記,能夠更加清楚地了解單片機的工作原理。
:)