蓝桥杯嵌入式——LED操作总结

本文是我在复习阶段的总结,算是写复习笔记了,也很乐意把分享出来。小白也是可以看的,可以更快入门。

LED初始化

初始化部分是比较简单的,不是重点,直接贴代码:

void  LED_Init(void)
{
    
    
  GPIO_InitTypeDef GPIO_InitStructure;
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD,ENABLE);
  // RCC_AHBPeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD,ENABLE);//时钟使能
 
 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
 GPIO_InitStructure.GPIO_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_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
 GPIO_Init(GPIOC,&GPIO_InitStructure);
 
 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2;
 GPIO_Init(GPIOD,&GPIO_InitStructure);
}

两种不同的LED驱动代码

第一种是写驱动函数的方法。

void LED_Control(u16 cont,int status)
{
    
    
 if(status==1)
 {
    
    
   GPIO_ResetBits(GPIOC,cont<<8);
   GPIO_SetBits(GPIOD,GPIO_Pin_2);
   GPIO_ResetBits(GPIOD,GPIO_Pin_2);
 }
  if(status!=1)
 {
    
    
   GPIO_SetBits(GPIOC,cont<<8);
   GPIO_SetBits(GPIOD,GPIO_Pin_2);
   GPIO_ResetBits(GPIOD,GPIO_Pin_2);
 }
 
}

这种写法比较方便,直接用就可以。具体怎么写参考这位大佬添加链接描述
这里需要提一下GPIO_ResetBits()和GPIO_SetBits()是对GPIOx_BRR和GPIOx_BSRR进行的操作。这两个寄存器的介绍我贴在下面了。**具体可以看STM32参考手册中文版。**可以看到BSRR寄存器可以单独对一位进行操作,不会影响其它位,简单解释就是可以只控制一个LED灯。
在这里插入图片描述
在这里插入图片描述

第二种方法是直接操作寄存器

  GPIOC-> ODR = 0XFFFF;
  GPIOD-> ODR |= (1<<2);
  GPIOD-> ODR &=~(1<<2);

这是初始化代码,具体功能是让所有LED灯熄灭。
这里使用的是ODR寄存器,和BSRR寄存器功能是不一样的。可以看到ODR寄存器是对所有的位进行操作的。因此0XFFFF便可以实现让所有的LED灯都熄灭的效果。
在这里插入图片描述

两种方法的比较

起初我学的时候使用第一种函数的方法,因为方便。第二种方法就让人很难受,毕竟操作库函数比操作寄存器更加直观和方便,还要记住那么多的位运算。但是深入学习的话会发现第二种方法有它的优势。

具体看第八届的省赛模拟题。
在这里插入图片描述
可以看到温度和湿度两个标准是可以同时超过其上限的,也就是在L1闪烁的时候,L2也是可以闪烁的,还有L3也是。三个灯的状态是可以独立切换,互不影响的,这是难点。如果用第一种方法写函数的话,实现灯的闪烁就很啰嗦,需要配置许多函数,还有就是要想从一个灯闪烁的状态转换为两个灯一起闪烁是比较困难的,因为我上面说了BSRR寄存器可以单独对一位进行操作,要想转变成两位的话会不流畅,简言之就是函数很难实现3个灯独立切换。大家可以试一试。
但是操作寄存器就会非常容易。

	u16 LED_MODE = 0XFFFF;
   if(LED_Flag)
   {
    
    
     if(Temperature > TH_compare)//当达到温度上限
     {
    
    
       LED_MODE ^= (1<<8);//实现灯的状态反转
     }else			//没有达到温度上限
     {
    
    
       LED_MODE |= (1<<8);//熄灭
     }
     if(RH > RH_cpmpare)
     {
    
    
       LED_MODE ^= (1<<9);
     }else
     {
    
    
       LED_MODE |= (1<<9);
     }
     GPIOC-> ODR = LED_MODE;
     GPIOD-> ODR |= (1<<2);
     GPIOD-> ODR &=~(1<<2);
     LED_Flag = 0;
   }

这里涉及到位运算。

int led_mode =0xffff
led_mode &=~(1<<2);//第三位置零,计算结果为led_mode=0xfffB
led_mode |=(1<<2);//第三位置1,计算结果为led_mode=0xffff
led_mode ^=(1<<2);//第三位取反,计算结果为led_mode=0xfffB
led_mode ^=(1<<2);//第三位再次取反,计算结果为led_mode=0xffff

可以看到灯的状态反转只需要一个函数就可以实现。而且最重要的是每个灯的状态不会相互影响。大家可以自己运算一下,加深理解。

总结

我建议大家两种方法都尝试一下,这样可以更好的理解。在入门的时候先用函数的方法,之后要学会对寄存器的操作。

猜你喜欢

转载自blog.csdn.net/qq_43690936/article/details/105100317