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