第一次写,有不对的地方还望大家多多指正。
任务要求:
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(); // 重新初始化中断
}
}
}
本代码在完成原题基本要求外添加了可以反复执行的功能(基本要求执行完毕后短按一下按键复位)。
按键按下时的处理
- 首先,函数检查按键SW1是否被按下,即其输入电平是否为低电平(SW1==0)。同时,它还检查计数器
count
是否为0,count
在这里用作一个状态标志,用于区分这是初次按下还是持续的按下状态。 - 如果按键被按下且
count
为0,函数会调用delay
函数进行一个较长的延时(延时时间由delay
函数的参数决定,这里为200000个单位),这个延时是为了检测长按是否为真。 - 延时之后,再次检查按键SW1是否仍然被按下,即再次检测长按的有效。如果确实如此,将LED1设置为高电平(即点亮LED1),并将
count
设置为1,表示已经检测到了一次稳定的按键按下事件。
按键释放时的处理
- 接下来,函数检查按键SW1是否被释放,即其输入电平是否为高电平(SW1==1)。同时,它还检查
count
是否为1,确保之前检测到了按键按下事件。 - 如果按键被释放且
count
为1,函数会调用delay
函数进行一个短暂的延时(延时时间为50个单位),这个延时是为了确保按键已经完全释放,避免由于按键释放时的弹跳导致的误判。 - 延时之后,将LED1和LED2都设置为高电平(即点亮LED1和LED2),这通常表示按键事件已经被处理。同时,将标志位
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,表示已经处理了中断的触发状态。