🌈个人主页:羽晨同学

💫个人格言:“成为自己未来的主人~” 

驱动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;
    }

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐