小蜜蜂笔记
嵌入式开发与物联网应用教育践行者

【赛题详解】2019年物联网江苏省赛任务三题1-按键多连击控制风扇(附完整源码)

任务要求

新建IAR工程文件,完成按键控制Zigbee黑色板子上的灯及外接风扇,实现以下任务要求:
【1】程序开始运行时,板上的D4、D3、D6、D5灯亮3秒后全灭,外接的风扇停止。
【2】按键SW1单击,切换D5灯的开关状态。
【3】按键SW1双击,切换D6灯的开关状态。
【4】按键SW1三连击,切换D3灯的开关状态。
【5】按键SW1四连击,切换D4灯的开关状态。
【6】当LED灯的状态为1101时,即D5灯亮,D6灯亮,D3灯灭,D4灯亮,打开外接的风扇,否则停止风扇。
【7】按下SW2按键后,数据及风扇重置到初始上电状态
【8】能重复实现以上步骤。
【9】需在代码中使用定时器实现以上LED灯及外接风扇的功能。

参考源码

#include "ioCC2530.h"
 
#define D4  P1_1
#define D3  P1_0
#define D5  P1_3
#define D6  P1_4
#define SW1 P1_2
#define SW2 P0_1
#define FS  P2_0

unsigned char count_t = 0;    //0.1秒间隔定时累计
unsigned char K_Num = 0;      //按键连击状态记录
unsigned char LED_dat = 0;    //灯光工作状态标志
unsigned char F_Start = 0;    //系统工作状态标志
/*=======================简单的延时函数========================*/
void Delay(unsigned int t)
{
  while(t--);
}
/*======================端口初始化函数========================*/
void Init_Port()
{
  P1SEL &= ~0x1b;     //P1_0、P1_1、P1_3和P1_4作为通用I/O端口
  P1DIR |= 0x1b;      //P1_0、P1_1、P1_3和P1_4端口输出
  P1 &= ~0x1b;        //关闭所有的LED灯
  
  P1SEL &= ~0x04;     //P1_2作为通用I/O端口
  P1DIR &= ~0x04;     //P1_2端口输入
  P1INP &= ~0x04;     //P1_2设置为上拉/下拉模式
  P2INP &= ~0x40;     //P1_2设置为上拉
  
  P0SEL &= ~0x02;     //P0_1作为通用I/O端口
  P0DIR &= ~0x02;     //P0_1端口输入
  P0INP &= ~0x02;     //P0_1设置为上拉/下拉模式
  P2INP &= ~0x20;     //P0_1设置为上拉
  
  P2SEL &= ~0x01;     //P2_0作为通用I/O端口
  P2DIR |= 0x01;      //P2_0端口输出
  FS = 0;
}
/*=======================定时器1初始化========================*/
void Init_Timer1()
{
  T1CC0L = 0xd4;      
  T1CC0H = 0x30;        //16MHz时钟,128分频,定时0.1秒
  T1CCTL0 |= 0x04;      //开启通道0的输出比较模式
  T1IE = 1;             //开启定时器中断
  EA = 1;               //开启总中断
  T1CTL = 0x0e;         //分频系数是128,模模式
}
/*====================定时器1服务函数========================*/
#pragma vector = T1_VECTOR
__interrupt void Timer1_int()
{
  
  T1STAT &= ~0x20;      //清除定时器1的溢出中断标志位
  if(F_Start == 1)      
  {
    if(K_Num != 0 && SW1 != 0)      
    {
      count_t++;        //计算按键的生命周期  
    }
  }
  else
  {
    count_t++;          //间隔定时3秒钟
    if(count_t == 30)
    {
      count_t = 0;
      F_Start = 1;      
    }
  }
}
/*====================按键扫描处理函数========================*/
void Scan_Keys()
{
  if(SW1 == 0)
  {
    Delay(100);             //去抖动处理
    if(SW1 == 0)            //确认按键SW1按下
    {
      while(SW1 == 0);      //等待按键松开
      count_t = 0;          //重新计算按键生命周期
      K_Num++;              //按键按下次数记录
    }
  }
  if(SW2 == 0)
  {
    Delay(100);             //去抖动处理
    if(SW2 == 0)            //确认按键SW2按下
    {
      while(SW2 == 0);
      count_t = 0;
      K_Num = 0;
      LED_dat = 0;
      D5 = 0;
      D6 = 0;
      D4 = 0;
      D3 = 0;
    }
  }
  if(count_t > 5)           //按键生命周期结束
  {
    switch(K_Num)
    {
      case 1:               //按键单击
        if((LED_dat & 0x01) == 0x01)
        {
          D4 = 0;
          LED_dat &= ~0x01;
        }
        else
        {
          D4 = 1;
          LED_dat |= 0x01;
        }
      break;
      case 2:               //按键双击
        if((LED_dat & 0x02) == 0x02)
        {
          D3 = 0;
          LED_dat &= ~0x02;
        }
        else
        {
          D3 = 1;
          LED_dat |= 0x02;
        }
      break;
      case 3:               //按键三连击
        if((LED_dat & 0x04) == 0x04)
        {
          D6 = 0;
          LED_dat &= ~0x04;
        }
        else
        {
          D6 = 1;
          LED_dat |= 0x04;
        }
      break;
      case 4:               //按键四连击
        if((LED_dat & 0x08) == 0x08)
        {
          D5 = 0;
          LED_dat &= ~0x08;
        }
        else
        {
          D5 = 1;
          LED_dat |= 0x08;
        }
      break;
    }
    K_Num = 0;            //清除按键按下记录
    count_t = 0;          //按键生命周期清零
  }
}
/*==========================主函数============================*/
void main()
{
  Init_Port();              //初始化端口
  Init_Timer1();            //初始化定时器1
  D5 = 1;
  D6 = 1;
  D4 = 1;
  D3 = 1;
  while(F_Start == 0);      //等待间隔定时3秒
  D5 = 0;
  D6 = 0;
  D4 = 0;
  D3 = 0;
  while(1)
  {
    Scan_Keys();            //扫描按键
    if(LED_dat == 0x0d)     //0000 1101
    {
      FS = 1;               //打开风扇
    }
    else
    {
      FS = 0;               //停止风扇
    }
  }
}
赞(26)
未经允许不得转载:小蜜蜂笔记 » 【赛题详解】2019年物联网江苏省赛任务三题1-按键多连击控制风扇(附完整源码)

评论 1

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
  1. #1

    该程序存在一定问题,即第一次满足上述的二进制要求时,若第二次触发该二进制涉及的LED时也会触发继电器模块。
    举个例子:第一次触发0000 1101后,第二次双击按键(改变第1位后)板子上的LED灯的状态为0000 0011,继电器还会被触发。
    建议:通过判断P1口输出状态可以有效防止该问题的发生!

    殘風5年前 (2019-10-12)回复

小蜜蜂笔记 更专业 更方便 更高效

联系我们精品小店