上次做的STM32项目中要求实现4种灯的闪烁效果,并能控制闪烁模式的切换。实现4种灯的闪烁效果并不难,用很精确的延时函数配合高低电平控制就能实现了。控制端使用引脚输入控制,类似3-8译码器,三个输入即可控制8种闪烁效果。

4种灯质闪烁闪烁的规则如下图:

简单说就是要设定灯关闭、常亮、快闪、慢闪、亮灭时间不同闪和混合效果闪。难点在于控制。如果在一个函数中设定一个周期的灯闪烁循环,那么如果周期长的话,切换模式后也得等到周期执行完了才能进入下一种闪烁模式,于是自己写了一个以闪烁中最小周期为循环节的循环显示效果,这样发出控制命令后,能及时切换到其它模式。虽然也会延时最小变化周期,但是应该够用了,更精确的写法可以试试中断。本代码的优点就在于在于简洁易懂,无需其它配置。

代码中设定的输入控制信号为:PC1、PC2、PC3,输出的灯接PE5。定义的几种闪烁效果为:

丹顿光:亮3秒,灭1秒
等明暗光:亮、灭各2秒
连续快闪光:亮、灭各0.5秒
联甚块闪光:亮0.5秒,灭0.5秒,循环6次;亮2秒,灭2秒

PC1、PC2、PC3设定与对应模式:000灭、010常亮、100丹顿光Oc、101等明暗光Iso、110连续快闪光QFlash、111联甚快闪光VQLFI

代码如下:

#include "stm32f10x.h"
#define Delay_ms(msec) Delay_us(msec*1000)  //延时毫秒级
#define PC1 GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_1)   //读PC1
#define PC2 GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_2)   //读PC2
#define PC3 GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_3)   //读PC3

void LED_GPIO_Config(void) //配置LED用到的I/O口
{       
    GPIO_InitTypeDef GPIO_InitStructure; 
    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOE, ENABLE);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOE, &GPIO_InitStructure);
    GPIO_ResetBits(GPIOE, GPIO_Pin_5);
}

   void Input_GPIO_Config(void)//输入I/O口配置
{
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);//
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3; //
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //IPU;上拉、IPD下拉
    GPIO_Init(GPIOC, &GPIO_InitStructure);
}
 
void Delay_us(u32 ntimes)
{
    u32 flag;
    SysTick->LOAD=9*ntimes; 
    SysTick->VAL=0;
    SysTick->CTRL=0x00000001;
    do
    {
        flag=SysTick->CTRL;
    }
    while(flag&0x01&&!(flag&(1<<16)));
    SysTick->CTRL=0;
}

//丹顿光:亮3秒,灭1秒                                
//等明暗光:亮、灭各2秒                               
//连续快闪光:亮、灭各0.5秒                           
//联甚块闪光:亮0.5秒,灭0.5秒,循环6次;亮2秒,灭2秒 
//PC1 PC2 PC3
// 0   0   0  灭
// 0   1   0  常亮
// 1   0   0  丹顿光Oc
// 1   0   1  等明暗光Iso
// 1   1   0  连续快闪光QFlash
// 1   1   1  联甚快闪光VQLFI
//灯接的是PE5
void LED_FLASH_Simple(u8 l,u8 m,u8 s) //灯闪烁,l为亮的时间,m为灭的时间。s为亮灭模式切换
{
    u8 i;
    if(s==1) 
    {
        GPIO_SetBits(GPIOE , GPIO_Pin_5);
        for(i=0;i<l;i++) Delay_ms(500);
    }
    if(s==0)
    { 
        GPIO_ResetBits(GPIOE,GPIO_Pin_5);
        for(i=0;i<m;i++) Delay_ms(500);
    }
}

u8 s=1,j=0;
int main(void)
{
    LED_GPIO_Config();
    Input_GPIO_Config();
    while(1)
    {
      if(PC3==0 && PC1==0 )
      {
      GPIO_ResetBits(GPIOE,GPIO_Pin_5);
      j=0;
      }

      if(PC3==0 && PC1==1 )
      {
      GPIO_SetBits(GPIOE , GPIO_Pin_5);
      j=0;
      }

      if(PC3==1)
      {
      if(PC1==0 && PC2==0)  
      {
          j=0;
          LED_FLASH_Simple(6,2,s);
          if(s==1) s=0;
          else s=1;
      }
      if(PC1==0 && PC2==1)  
      {
          j=0;
          LED_FLASH_Simple(4,4,s);
          if(s==1) s=0;
          else s=1;
      }
      if(PC1==1 && PC2==0)  
      {
          j=0;
          LED_FLASH_Simple(1,1,s);
          if(s==1) s=0;
          else s=1;
      }
      if(PC1==1 && PC2==1)  
      {
          if(j<12)
          {
              LED_FLASH_Simple(1,1,s);
               if(s==1) s=0;
               else s=1;
              j++;
          }
          if(j==12) 
          {
              LED_FLASH_Simple(4,4,s);
              if(s==1) s=0;
              else s=1;
              j++;
          }
          if(j==13) 
          {
              LED_FLASH_Simple(4,4,s);
              if(s==1) s=0;
              else s=1;
              j=0;
          }
      }
      } 
      
    }
}