基于STM32的LED实战 -- 流水灯、呼吸灯、流水呼吸灯
🌈个人主页:羽晨同学
💫个人格言:“成为自己未来的主人~”
驱动LED
// LED1: PE9
// LED2: PB1
// LED3: PB0
这个是我们板子上的三个LED灯分别对应的引脚名称。
首先,我们需要对这三个引脚进行初始化
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_StructInit(&GPIO_InitStructure);GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;GPIO_InitStructure.GPIO_Speed = GPIO_High_Speed;GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;GPIO_InitStructure.GPIO_Pin = LED1_PIN;GPIO_Init(LED1_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = LED2_PIN;GPIO_Init(LED2_PORT, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = LED3_PIN;GPIO_Init(LED3_PORT, &GPIO_InitStructure);
以上的这些为引脚初始化的代码。
接下来,我们对引脚赋高低电平,就可以使得对应LED灯进行亮灭闪烁。
while (1){GPIO_SetBits(LED1_PORT, LED1_PIN);cpu_delay();GPIO_ResetBits(LED1_PORT, LED1_PIN);cpu_delay();}
如果这个时候要是没有 cpu_delay();的话,我们会看到LED灯是保持常亮的,这个是因为stm32f407本身的主频就比较大(有168MHz),CPU执行的速度很快,所以我们需要加上一个对应的延时函数。
void cpu_delay(void)
{uint32_t delay = 168 * 1000 * 10;for (uint32_t t = 0; t < delay; t++) { ; }
}
这样,我们就实现了对应的LED灯的闪烁。
三个LED灯同时闪烁的原理也是如此
while (1){GPIO_SetBits(LED1_PORT, LED1_PIN);GPIO_SetBits(LED2_PORT, LED2_PIN);GPIO_SetBits(LED3_PORT, LED3_PIN);cpu_delay();GPIO_ResetBits(LED1_PORT, LED1_PIN);GPIO_ResetBits(LED2_PORT, LED2_PIN);GPIO_ResetBits(LED3_PORT, LED3_PIN);cpu_delay();}
流水灯
为了方便查看,我们修改一下我们的呈现方式
static void led_set(uint8_t led, uint8_t state)
{if (led == 1){GPIO_WriteBit(GPIOE, GPIO_Pin_9, state ? Bit_RESET : Bit_SET);}else if (led == 2){GPIO_WriteBit(GPIOB, GPIO_Pin_1, state ? Bit_RESET : Bit_SET);}else if (led == 3){GPIO_WriteBit(GPIOB, GPIO_Pin_0, state ? Bit_RESET : Bit_SET);}
}
有了这个函数之后,我们就可以通过以下方式来实现流水灯的效果。
首先,我们先让三个灯全部熄灭
led_set(1, 0);led_set(2, 0);led_set(3, 0);
然后,我们实现流水灯的效果
uint32_t ledidx = 1;while (1){led_set(ledidx, 1);cpu_delay();led_set(ledidx, 0);if (++ledidx > 3){ledidx = 1;}}
这样子,我们就可以实现流水灯的效果了。
呼吸灯
呼吸灯就是LED的渐灭和渐亮的过程,我们要利用的便是周期和占空比。
这个灯的亮度是由亮的时间和灭的时间来进行确定的,如果亮的时间长一些,灭的时间短一些,总体看上来就会更亮一些。
所以,我们可以采用除了PWM的方法的另外一个方式来实现这个效果:
while (1){int period = 2000;for(int d = 0;d<period;d++){led_set(1,1);for(int i = 0;i<d;i++);led_set(1,0);for(int i = d;i<period;i++);}}
浪潮灯
要实现浪潮灯,我们先来使得三个LED灯的亮度不一样,那应该怎么做呢?
当LED1低于20的时候,让LED1亮,当LED2低于40,LED3低于60的时候,让这三个亮,我们就能大概实现出来三个LED亮度不一样的效果
代码如下:
led_set(1, i < led1_duty ? 1 : 0);led_set(2, i < led2_duty ? 1 : 0);led_set(3, i < led3_duty ? 1 : 0);
所以,最终代码如下:
//软件模拟PWM//设置频率int period = 250;//设置led的占空比int led1_duty = 0, led2_duty = period * 25 / 100, led3_duty = period * 50 / 100;int led1_inc = 1, led2_inc = 1, led3_inc = 1;while (1){//输出比较,向上计数,i < 占空比时置低电平,灯亮for (int i = 0; i < period; i++){led_set(1, i < led1_duty ? 1 : 0);led_set(2, i < led2_duty ? 1 : 0);led_set(3, i < led3_duty ? 1 : 0);}//占空比在0-100%period中自增或自减led1_duty += led1_inc;led2_duty += led2_inc;led3_duty += led3_inc;if (led1_duty >= period || led1_duty < 0) led1_inc = -led1_inc;if (led2_duty >= period || led2_duty < 0) led2_inc = -led2_inc;if (led3_duty >= period || led3_duty < 0) led3_inc = -led3_inc;}