2023年上海市“星光计划”中职物联网技术应用与维护样题 CC2530辅助开发,单片机按键控制

第一次写,有不对的地方还望大家多多指正。

任务要求:
1. 程序通电,节点盒的 LED1 、 LED2 灯都不亮。
2. 长按 SW1 键不松开, LED1 灯亮, LED2 灯熄灭。
3. 松开 SW1 键, LED1 、 LED2 亮灯都常亮。
4. 将编写好的程序发布到蓝色 ZigBee 节点盒中。

代码部分:

#include <iocc2530.h>

// 定义LED和开关对应的端口位
#define LED1 P1_0
#define LED2 P1_1
#define SW1 P1_2
#define OUT1 P1_5 
#define OUT0 P1_6

// 定义无符号字符类型别名
#define unsigned char uchar

// 全局标志变量和计数器
int flag=0;
int count=0;

/**
 * @brief 初始化GPIO端口
 * 配置P1.2~P1.3为普通I/O,设置P1.0和P1.1为输出,P1.2为输入并上拉。
 */
void init_gpio()
{
  P1SEL &= ~0x0C; 
  P1DIR |= 0x03;  
  P1INP |= 0x04; 
}

/**
 * @brief 延迟函数
 * 通过循环计数实现延迟,时间取决于参数t。
 * @param t 延迟时间,单位为循环次数。
 */
void delay(long t)
{
  while(t--);
}

/**
 * @brief 初始化中断
 * 配置P1口中断,使能P1.2口的外部中断功能,并设置为上升沿触发。
 */
void initial_interrupt()
{
  IEN2|=0x10;  // 打开P1口中断的使能位
  P1IEN|=0x04; // 使能P1.2口的外部中断功能
  PICTL|=0x02; // 配置P1.3-P1.0的中断为上升沿触发
  EA=1;        // 打开全局中断使能
}

// P1口中断服务程序
#pragma vector=P1INT_VECTOR
__interrupt void  P1_ISR()
{
  // 如果按键SW1被按下且LED2为亮态,则关闭两个LED并重置相关变量
  if (SW1==0&&LED2==1) 
  {
    LED1=LED2=0;
    flag=count=0;
  }
  flag=0; // 重置标志位
  P1IF=0x00; // 清除P1口的中断标志
  P1IFG=0x00; // 清除P1口的中断标志待触发状态
}

/**
 * @brief 定期扫描按键状态并处理按键事件
 * 检测按键SW1的状态,当按键被持续按下时,触发一系列动作。
 */
void keyscan()
{
  // 检测按键是否按下且之前没有按下记录
  if(SW1==0&&count==0)
  {
    delay(200000);  // 确保按键是持续按下
    if(SW1==0)  // 再次确认按键状态
    {
      LED1=1;  // 打开LED1,表示按键按下
      count=1;  // 记录按键按下状态
    }
  }
  // 检测按键是否释放
  if(SW1==1&&count==1)
  {
    delay(50);  // 确认按键释放
    LED1=LED2=1;  // 打开两个LED,表示按键已释放
    flag=1;  // 标记按键处理完成
  }
}

/**
 * @brief 主函数,初始化并持续检测按键状态。
 * 初始化GPIO、LED和标志位,然后进入无限循环,等待按键事件并处理。
 */
int main(void)
{
  init_gpio();  // 初始化GPIO端口
  LED1=LED2=0;  // 关闭LED
  flag=0;  // 初始化标志位
  P1IF=0x00;  // 清除中断标志
  P1IFG=0x00;  // 清除中断标志待触发状态
  while(1)  // 进入无限循环
  {
    // 当无按键事件时,循环扫描按键
    while(flag==0)
    {
      keyscan();    
    }
    // 当有按键事件时,处理按键事件
    while(flag==1)
    {
      initial_interrupt();  // 重新初始化中断
    }
  }
}


本代码在完成原题基本要求外添加了可以反复执行的功能(基本要求执行完毕后短按一下按键复位)。

按键按下时的处理

  1. 首先,函数检查按键SW1是否被按下,即其输入电平是否为低电平(SW1==0)。同时,它还检查计数器count是否为0count在这里用作一个状态标志,用于区分这是初次按下还是持续的按下状态。
  2. 如果按键被按下且count0,函数会调用delay函数进行一个较长的延时(延时时间由delay函数的参数决定,这里为200000个单位),这个延时是为了检测长按是否为真。
  3. 延时之后,再次检查按键SW1是否仍然被按下,即再次检测长按的有效。如果确实如此,将LED1设置为高电平(即点亮LED1),并将count设置为1,表示已经检测到了一次稳定的按键按下事件。

按键释放时的处理

  1. 接下来,函数检查按键SW1是否被释放,即其输入电平是否为高电平(SW1==1)。同时,它还检查count是否为1,确保之前检测到了按键按下事件。
  2. 如果按键被释放且count1,函数会调用delay函数进行一个短暂的延时(延时时间为50个单位),这个延时是为了确保按键已经完全释放,避免由于按键释放时的弹跳导致的误判。
  3. 延时之后,将LED1LED2都设置为高电平(即点亮LED1LED2),这通常表示按键事件已经被处理。同时,将标志位flag设置为1,表示已经检测到了一次完整的按键按下和释放事件。

中断服务程序

P1_ISR中断服务程序中,处理了中断事件,用于反复执行:

  • if (SW1==0&&LED2==1):这一条件判断检查了按键SW1是否被按下,并且LED2是否处于点亮状态。如果是这种情况,说明在LED2已经亮起的情况下按键被再次按下,这表明已经完成了任务要求中的前三个操作。
  • LED1=LED2=0;:这一行代码关闭了LED1和LED2,表示对用户操作的响应。
  • flag=count=0;:这一行代码将标志位flag和计数器count清零,重置了按键检测状态。
  • P1IF=0x00;:这一行代码清除了P1端口的Interrupt Flag,表示已经处理了中断。
  • P1IFG=0x00;:这一行代码清除了P1端口的Interrupt Flag Ground,表示已经处理了中断的触发状态。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值