1.前言
不管是玩什么芯片,点灯都是一个绕不开的话题。在蓝桥杯的嵌入式比赛中,几乎每一年的省赛都涉及到与LED有关的设计。点灯说白了也很简单,无非就是分为点亮一个灯、点亮多个灯以及流水灯和灯闪烁等等情况。
接下来本文将会分别讲解如何实现上述功能。
2.硬件配置
点灯之前肯定要知道LED是怎么和STM32连接的,可以参考蓝桥杯嵌入式开发手册
从图中可以看出,开发板的8个LED连接在STM32的PC8~PC15,并且LED是共阳极连接,这表明GPIO引脚为低电平时,从才能点亮LED。图中的SN74HC573ADWR是一个锁存器,其控制位LE和STM32的PD2引脚连接。
那锁存器是干什么的呢?简单来说,它能够将输入到锁存器中的数据保存并输出,当打开锁存器的时候,LED才能接收到来自STM32的电平信号,当锁存器关闭时,LED无法被STM32的引脚高低电平影响。关于这个锁存器的详细信息可以通过查找其数据手册,此处我们只要知道,PD2引脚高电平可以打开该锁存器,低电平则是关闭。
知道了这些,就可以在STM32CubeMX中控制配置相关的引脚,当然你可以选择和我一样,通过代码配置这些引脚。上述提到的GPIO引脚均可以配置为推挽输出模式,引脚速度为低速或者高速都可以。如果想要开发板的所有LED在上电时均保持熄灭,可以将PC8~PC15的初始电平全部设置为高电平。
void Led_GPIO_Init(void)
{
__HAL_RCC_GPIOC_CLK_ENABLE();
GPIO_InitTypeDef gpio_led_init;
gpio_led_init.Pin = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 |GPIO_PIN_11 |GPIO_PIN_12 |GPIO_PIN_13 |GPIO_PIN_14 |GPIO_PIN_15;
gpio_led_init.Mode = GPIO_MODE_OUTPUT_PP;
gpio_led_init.Speed = GPIO_SPEED_LOW;
HAL_GPIO_Init(GPIOC, &gpio_led_init);
__HAL_RCC_GPIOD_CLK_ENABLE();
GPIO_InitTypeDef gpio_74HC573_init;
gpio_74HC573_init.Pin = GPIO_PIN_2;
gpio_74HC573_init.Mode = GPIO_MODE_OUTPUT_PP;
gpio_74HC573_init.Speed = GPIO_SPEED_HIGH;
HAL_GPIO_Init(GPIOD,&gpio_74HC573_init);
HAL_GPIO_WritePin(GPIOC, gpio_led_init.Pin, GPIO_PIN_SET);
}
3.代码实现
3.1点亮一个LED
点亮一个LED非常简单,只需要将LED对应的GPIO电平拉低即可。以下给出HAL库代码,当然你也可以选择通过修改寄存器的值实现。
void Led_Disp(void)
{
//点亮LED1
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);//打开锁存器
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);//关闭锁存器
}
3.2点亮多个LED
这部分的代码和上述代码并没有什么区别,只需要将所需点亮的LED对应的引脚通过“|”相连接即可。
void Led_Disp(void)
{
//点亮LED1和LED8
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8|GPIO_PIN_15, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
}
3.3LED闪烁
LED闪烁有两种办法可以实现,一种是先打开LED,延时一定时间(这段时间通常为ms级别)后关闭LED,再延时一定时间后再打开LED。
void Led_Disp(void)
{
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);//打开锁存器
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8, GPIO_PIN_RESET);
HAL_Delay(500);//延时500ms
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8, GPIO_PIN_SET);
HAL_Delay(500);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);//关闭锁存器
}
当然也可以使用HAL库自带的电平翻转函数实现。
void Led_Disp(void)
{
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_8);
HAL_Delay(500);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
}
3.4流水灯
STM32并没有专门实现流水灯的HAL库函数,这里提供一种通过写寄存器的方式实现的方法。
首先,该函数有比较大的局限性,只能放在main.c文件中,因为其涉及到了对全局变量led的修改。led是一个无符号整型变量,初始化的值代表流水灯上电时的LED状态。在下面的函数中,会对led的值进行修改,将其左移8为是因为所使用的GPIO引脚是PC8~PC15,对应的ODR寄存器的值是从第8位到第15位。将led值取反是因为在本开发板中LED是低电平点亮。每次运行该函数,都会使led的值向左移一位,当led的值全部溢出时,也就是全为0时,则重新设置led的值,使其从led1开始依次点亮。
void Led_Disp(void)
{
GPIOC->ODR = ~led << 8;
HAL_Delay(50);
if(led == 0) led = 1;
else led = led << 1;
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
}
以上就是本文的全部内容了,如有错误还请海涵指正。