1.LED 控制引脚相关的宏
//引脚定义
//R 红色灯
#define LED1_PIN GPIO_PIN_10
#define LED1_GPIO_PORT GPIOH
#define LED1_GPIO_CLK_ENABLE() __GPIOH_CLK_ENABLE()
//G 绿色灯
#define LED2_PIN GPIO_PIN_11
#define LED2_GPIO_PORT GPIOH
#define LED2_GPIO_CLK_ENABLE() __GPIOH_CLK_ENABLE()
//B 蓝色灯
#define LED3_PIN GPIO_PIN_12
#define LED3_GPIO_PORT GPIOH
#define LED3_GPIO_CLK_ENABLE() __GPIOH_CLK_ENABLE()
以上代码分别把控制 LED
灯的
GPIO
端口、
GPIO
引脚号以及
GPIO
端口时钟封装起来了。在实际控制的时候我们就直接用这些宏,以达到应用代码跟硬件无关的效果。
2 .控制 LED 灯亮灭状态的宏定义
这部分宏控制 LED 亮灭的操作是直接向
BSRR
寄存器写入控制指令来实现的,对
BSRR
低
16
位 写 1
输出高电平,对
BSRR
高
16
位写
1
输出低电平,对
ODR
寄存器某位进行异或操作可反转位 的状态。
RGB 彩灯可以实现混色,如最后一段代码我们控制红灯和绿灯亮而蓝灯灭,可混出黄色效果。
/** 控制 LED 灯亮灭的宏,
* LED 低电平亮,设置 ON=0,OFF=1
* 若 LED 高电平亮,把宏设置成 ON=1 ,OFF=0 即可
*/
#define ON GPIO_PIN_RESET
#define OFF GPIO_PIN_SET
/* 带参宏,可以像内联函数一样使用 */
#define LED1(a) HAL_GPIO_WritePin(LED1_GPIO_PORT,LED1_PIN,a)
#define LED2(a) HAL_GPIO_WritePin(LED2_GPIO_PORT,LED2_PIN,a)
#define LED3(a) HAL_GPIO_WritePin(LED2_GPIO_PORT,LED3_PIN,a)
/* 直接操作寄存器的方法控制 IO */
#define digitalHi(p,i) {p->BSRR=i;} //设置为高电平
#define digitalLo(p,i) {p->BSRR=(uint32_t)i << 16;} //输出低电平
#define digitalToggle(p,i) {p->ODR ^=i;} //输出反转状态
/* 定义控制 IO 的宏 */
#define LED1_TOGGLE digitalToggle(LED1_GPIO_PORT,LED1_PIN)
#define LED1_OFF digitalHi(LED1_GPIO_PORT,LED1_PIN)
#define LED1_ON digitalLo(LED1_GPIO_PORT,LED1_PIN)
#define LED2_TOGGLE digitalToggle(LED2_GPIO_PORT,LED2_PIN)
#define LED2_OFF digitalHi(LED2_GPIO_PORT,LED2_PIN)
#define LED2_ON digitalLo(LED2_GPIO_PORT,LED2_PIN)
#define LED3_TOGGLE digitalToggle(LED3_GPIO_PORT,LED3_PIN)
#define LED3_OFF digitalHi(LED3_GPIO_PORT,LED3_PIN)
#define LED3_ON digitalLo(LED3_GPIO_PORT,LED3_PIN)
/* 基本混色,后面高级用法使用 PWM 可混出全彩颜色, 且效果更好 */
//红
#define LED_RED \
LED1_ON;\
LED2_OFF\
LED3_OFF
//绿
#define LED_GREEN \
LED1_OFF;\
LED2_ON\
LED3_OFF
//蓝
#define LED_BLUE \
LED1_OFF;\
LED2_OFF\
LED3_ON
//黄 (红 + 绿)
#define LED_YELLOW \
LED1_ON;\
LED2_ON\
LED3_OFF
//紫 (红 + 蓝)
#define LED_PURPLE \
LED1_ON;\
LED2_OFF\
LED3_ON
//青 (绿 + 蓝)
#define LED_CYAN \
LED1_OFF;\
LED2_ON\
LED3_ON
//白 (红 + 绿 + 蓝)
#define LED_WHITE \
LED1_ON;\
LED2_ON\
LED3_ON
//黑 (全部关闭)
#define LED_RGBOFF \
LED1_OFF;\
LED2_OFF\
LED3_OFF
3.LED GPIO 初始化函数
整个函数与“构建库函数雏形”章节中的类似,主要区别是硬件相关的部分使用宏来代替,初始
化
GPIO
端口时钟时也采用了
STM32
库函数,函数执行流程如下:
(1)
使用
GPIO_InitTypeDef
定义
GPIO
初始化结构体变量,以便下面用于存储
GPIO
配置。
(2)
调用宏定义函数
LED1_GPIO_CLK_ENABLE()
来使能
LED
灯的
GPIO
端口时钟,在前面的章
节中我们是直接向
RCC
寄存器赋值来使能时钟的,不如这样直观。该函数在
HAL
库里边将操作
寄存器部分封装起来,直接调用宏即可。
(3)
向
GPIO
初始化结构体赋值,把引脚初始化成推挽输出模式,其中的
GPIO_PIN 使用宏“
LEDx_PIN
”来赋值,使函数的实现方便移植。
(4)
使用以上初始化结构体的配置,调用
HAL_GPIO_Init
函数向寄存器写入参数,完成
GPIO
的
初始化,这里的
GPIO
端口使用“
LEDx_GPIO_PORT
”宏来赋值,也是为了程序移植方便。
(5)
使用同样的初始化结构体,只修改控制的引脚和端口,初始化其它
LED
灯使用的
GPIO
引
脚。
(6)
使用宏控制
RGB
灯默认关闭。
void LED_GPIO_Config(void)
{
/* 定义一个 GPIO_InitTypeDef 类型的结构体 */
GPIO_InitTypeDef GPIO_InitStruct;
/* 开启 LED 相关的 GPIO 外设时钟 */
LED1_GPIO_CLK_ENABLE();
LED2_GPIO_CLK_ENABLE();
LED3_GPIO_CLK_ENABLE();
/* 选择要控制的 GPIO 引脚 */
GPIO_InitStruct.Pin = LED1_PIN;
/* 设置引脚的输出类型为推挽输出 */
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
/* 设置引脚为上拉模式 */
GPIO_InitStruct.Pull = GPIO_PULLUP;
/* 设置引脚速率为高速 */
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
/* 调用库函数,使用上面配置的 GPIO_InitStructure 初始化 GPIO*/
HAL_GPIO_Init (LED1_GPIO_PORT, &GPIO_InitStruct);
/* 选择要控制的 GPIO 引脚 */
GPIO_InitStruct.Pin = LED2_PIN;
HAL_GPIO_Init(LED2_GPIO_PORT, &GPIO_InitStruct);
/* 选择要控制的 GPIO 引脚 */
GPIO_InitStruct.Pin = LED3_PIN;
HAL_GPIO_Init(LED3_GPIO_PORT, &GPIO_InitStruct);
/* 关闭 RGB 灯 */
LED_RGBOFF;
}
4.主函数
编写完 LED 灯的控制函数后,就可以在 main 函数中测试了。在 main 函数中,调用 SystemClock_Confifig 函数初始化系统的时钟。F429-挑战者的为 180MHz,所有程序都必须设置好系统的时钟再进行其他操作。接着调用我们前面定义的 LED_GPIO_Confifig 初始化好 LED 的控制引脚,然后直接调用各种控制 LED 灯亮灭的宏来实现 LED 灯的控制,延时采用库自带基于滴答时钟延时 HAL_Delay 单位为 ms,直接调用即可,这里 HAL_Delay(1000) 表示延时 1s。
以上,就是一个使用 STM32 HAL 软件库开发应用的流程。
int main(void)
{
/* 系统时钟初始化成 216 MHz */
SystemClock_Config();
/* LED 端口初始化 */
LED_GPIO_Config();
/* 控制 LED 灯 */
while (1)
{
LED1( ON ); // 亮
HAL_Delay(1000);
LED1( OFF ); // 灭
HAL_Delay(1000);
LED2( ON ); // 亮
HAL_Delay(1000);
LED2( OFF ); // 灭
LED3( ON ); // 亮
HAL_Delay(1000);
LED3( OFF ); // 灭
/* 轮流显示 红绿蓝黄紫青白 颜色 */
LED_RED;
HAL_Delay(1000);
LED_GREEN;
HAL_Delay(1000);
LED_BLUE;
HAL_Delay(1000);
LED_YELLOW;
HAL_Delay(1000);
LED_PURPLE;
HAL_Delay(1000);
LED_CYAN;
HAL_Delay(1000);
LED_WHITE;
HAL_Delay(1000);
LED_RGBOFF;
HAL_Delay(1000);
}
}