CC2530单片机呼吸灯与按键控制详解【23物联网国赛样题第二套】

任务要求:

  • ZigBee节点盒通电或重置,节点盒的LED1、LED2灯都不亮。
  • 长按SW1键不松开,LED1灯亮,LED2灯熄灭。
  • 松开SW1键,LED1、LED2亮灯都常亮。
  • 双击SW1可以控制LED1灯实现呼吸灯效果,LED2灯保持熄灭状态。
  • 再次双击SW1可以控制LED1维持当前亮度不再发生变化,LED2继续保持熄灭状态。
  • 将编写好的程序发布到蓝色ZigBee节点盒中。
  • 任务分析:

    这道题其实并不难,主要考的是思维逻辑,这边我们只写平常常用的按键与呼吸灯,通过变量控制来达到想要的效果,不用定时器,只在循环中完成任务。我们按照任务步骤一步一步开发,先写初始化,然后编写按键触发代码,最后在相应位置加入灯的效果。

    代码实现:

     ※本次代码使用library版竞赛工程

    在工程app目录下新建Breath.c与.h文件,该呼吸灯代码是从别的工程移植过来的,有明显bug,建议动手修改,改不来留言

    以下为Breath.c文件,

    #include "iocc2530.h"
    #include "Breath.h"
    
    #define false 0
    #define true 1
    unsigned char levelCount = 8;
    unsigned char led_levet_timer = 2;
    unsigned char devideCount = 16;
    unsigned char level = 1;
    unsigned char timeTic = 0;
    unsigned char isUprise = 1;
    
    
    void _pwmLevelUp() {
        static unsigned long led_level_tick = 0;
        led_level_tick++;
        if (led_level_tick > led_levet_timer) {
            led_level_tick = 0;
            if (isUprise)
                level++;
            else
                level--;
            if (level > levelCount) {
                level = levelCount;
                isUprise = false;
            } else if (level == 0) {
                isUprise = true;
            }
        }
    }
    
    void _pwm() {
        timeTic++;
        if (timeTic > level) {
             P1_0  = 1;
        }
        if (timeTic > levelCount) {
            timeTic = 0;
            P1_0  = 0;
        }
    }
    
    unsigned char timeDevice = 0;
    void _breathLed() {
        timeDevice++;
        if (timeDevice >= devideCount) {
            timeDevice = 0;
            _pwmLevelUp();
        }
        _pwm();
    }
    
    
    
    

    以下为Breath.h文件

    #ifndef _BREATH_H_
    #define _BREATH_H_
    #endif
    
    
    void _pwm(void);
    void _breathLed(void);
    
    
    

    以下为Main.c内容

    引入头文件,定义所需变量

    #include "Breath.h"
    
    #define Sw1 P1_2
    #define Led1 P1_0
    #define Led2 P1_1
    
    unsigned int keyTime=0, keyCnt=0, bFlag=0;
    //keyTime长按时间,keyCnt按键次数,bFlag是否呼吸1呼吸0暂停

    初始化函数,基本io最简化版

    void Init()
    {
      P1DIR = 0X1B;
      P1=0X00;
    }

    以下为按键功能,比较简单,不理解就自己断点跑一跑

    void key()
    {
      if(Sw1==0)
      {
        keyTime = 0;
        while(Sw1==0)
        {
          halMcuWaitMs(1);
          //按下时间大于300ms视为长按,
          if(++keyTime>300)
          {
            Led1 = 1;
            Led2 = 0;
          }
        }
        if(Sw1==1)
        {
          //长按后灯全部亮起,短按则计算按键次数
          if(keyTime>300)
            Led1 = Led2 = 1;
          else
            keyCnt+=1;
        }
      }
      //0.3s内没有第二次点击按钮则失效当前次数
      //短时间内连续触发即为连击
      if(keyCnt>1)
      {
         halMcuWaitMs(1);
        if(++keyTime>300)
        {
          if(bFlag==0)
            bFlag=1;
          else if(bFlag==1)
            bFlag=2;
          else if(bFlag==2)
            bFlag=1;
          keyCnt=0;
        }
      }
    }

    以下为呼吸灯控制代码

    void BreathLed()
    {
      //几连击就填几
      if(keyCnt==2)
      {
        Led2=0;
        bFlag=!bFlag;
        keyCnt=0;
      }
      if(bFlag==1)
        _breathLed();
      else if(bFlag==2)
        _pwm();
    }

    以下为main函数

    void main(void)
    {
      Init();
      while(1)
      {
        halMcuWaitMs(1);
        key();
        BreathLed();
      }
    }
    

    main.c源代码

    /**
      ******************************************************************************
      * File Name          : main.c
      * Description        : Main program body
      * By                 :Azhuo
      ******************************************************************************
      */
    #include <string.h>
    #include <stdio.h>
    #include "basic_rf.h"
    #include "hal_defs.h"
    #include "hal_cc8051.h"
    #include "hal_int.h"
    #include "hal_mcu.h"
    #include "hal_board.h"
    #include "hal_led.h"
    #include "hal_rf.h"
    #include "hal_uart.h" 
    #include "Breath.h"
    
    #define Sw1 P1_2
    #define Led1 P1_0
    #define Led2 P1_1
    
    unsigned int keyTime=0, keyCnt=0, bFlag=0;
    //keyTime长按时间,keyCnt按键次数,bFlag是否呼吸1呼吸0暂停
    void Init()
    {
      P1DIR = 0X1B;
      P1=0X00;
    }
    void key()
    {
      if(Sw1==0)
      {
        keyTime = 0;
        while(Sw1==0)
        {
          halMcuWaitMs(1);
          //按下时间大于300ms视为长按,
          if(++keyTime>300)
          {
            Led1 = 1;
            Led2 = 0;
          }
        }
        if(Sw1==1)
        {
          //长按后灯全部亮起,短按则计算按键次数
          if(keyTime>300)
            Led1 = Led2 = 1;
          else
            keyCnt+=1;
        }
      }
      //0.3s内没有第二次点击按钮则失效当前次数
      //短时间内连续触发即为连击
      if(keyCnt>1)
      {
         halMcuWaitMs(1);
        if(++keyTime>300)
        {
          if(bFlag==0)
            bFlag=1;
          else if(bFlag==1)
            bFlag=2;
          else if(bFlag==2)
            bFlag=1;
          keyCnt=0;
        }
      }
    }
    void BreathLed()
    {
      //几连击就填几
      if(keyCnt==2)
      {
        Led2=0;
        bFlag=!bFlag;
        keyCnt=0;
      }
      if(bFlag==1)
        _breathLed();
      else if(bFlag==2)
        _pwm();
    }
    
    /**
     * Main application entry point.
     */
    void main(void)
    {
      Init();
      while(1)
      {
        halMcuWaitMs(1);
        key();
        BreathLed();
      }
    }
    

    今天的训练就到这,下了鬼泣5所以比较急,代码是有些bug的,不过如果这点bug都解决不了就别比了,加油各位,奥利给。

    物联沃分享整理
    物联沃-IOTWORD物联网 » CC2530单片机呼吸灯与按键控制详解【23物联网国赛样题第二套】

    发表评论