GPIO学习和了解——初步掌握HAL库编程思路以及Cubemx配置方法
本次文章没有探究hal库和fw库的差别,目前没有细读hal库的文档例程;
1.cubemx生成工程框架
主要是将配置RCC的外部晶振时钟,把时钟树参数填好(后续对时钟配置有更高的要求时再讨论如何配置)
目前直接配置成80MHz
2.建立两个文件夹,一个用来存放cubemx直接生成的文件,主要是一些初始化代码,但是由于代码风格不佳,所以不直接使用;
另一个文件为正式工程文件,将cubemx初始化代码按自己风格移植,并且编写bsp层代码,使用main函数调用实现功能。
3.GPIO点灯实验
生成框架之后,文件复制到另一个文件夹里面,之后根据实现目的,继续进行外设初始化,下面进行GPIO初始化。
根据LED电路原理图,了解output mode以及level,并且因为有锁存器的存在,需要额外注意多一个PD2需要控制。
锁存器使用三态门控制存储,
LE为high时,Q更新为D;OE为low时,Qn更新为Q;所以在OE接gnd的情况下,LE为高电平则锁存器打开,pin值送给led,否则关闭。(LED低电平点亮)
PC8-PC15属于既连接了led,又连接了LCD,所以需要锁存器保证led和lcd互不干扰。
4.程序改写
生成框架产生的gpio.c文件只有一句简单代码:
__HAL_RCC_GPIOF_CLK_ENABLE();
而led相关的gpio初始化之后,cubemx生成的代码包含了上述代码,因此,可以直接改写。
(ps:这个地方看起来好像很傻,因为框架生成的代码被更进一步的gpio生成代码所包含,这是肯定的但是在后续更多外设的使用中,不可避免出现代码混乱,所以每一步都依次改写,不嫌麻烦,是有必要的,至少对我这个新手来说。)
改写方式如下:新建bsp层,建立bsp_led.c,设置好头文件路径等之后,在bsp_led.c中做gpio的初始化,以及调用GPIOWRITEPIN更改寄存器值,实现开关锁存器并输出高低电平。
#include "led\bsp_led.h" void Led_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOF_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8 |GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12, GPIO_PIN_SET); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET); /*Configure GPIO pins : PC13 PC14 PC15 PC8 PC9 PC10 PC11 PC12 */ GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8 |GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); /*Configure GPIO pin : PD2 */ GPIO_InitStruct.Pin = GPIO_PIN_2; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); } //函数名:Led_Disp //函数入口:ucLed //函数出口:void //函数功能ucLed的数值传递给GPIOC的pin8-pin15,实现点亮对应Led的功能 void Led_Disp(unsigned char ucLed) { //switch off all the leds. HAL_GPIO_WritePin(GPIOC, GPIO_PIN_All, GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET); //switch on the specific leds. HAL_GPIO_WritePin(GPIOC, ucLed<<8, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET); }
之后在main.c中调用Led_Disp写入需要点亮的led就可以了。
(右移八位——因为PC8-15为led对应pin,所以一个unsigned char为8位,右移八位才能变成高8为数值,变成鱼Pin8-Pin15一样的数字。)
end