一、实验目的:
- 阅读 ZigBee 模块硬件熟悉 ZigBee 模块相关硬件接口。使用 IAR开发环境设计程序,学习CC2530的外部中断的使用,实现用按键(霍尔效应传感器模拟)查询控制 LED 亮灭。
- 学习 CC2530 的外部中断的使用,实现用按键(霍尔效应传感器模拟)中断控制 LED 亮灭。
二、实验原理:
LED及按键原理图,如下图所示:
CC2530 的外部中断需要配置三个寄存器 P0IEN、PICTL、P0IFG、IEN1。
LED 初始化配置:
P2DIR |= 0x01; //P2_0 定义为输出
按键初始化配置:
P0SEL &= ~0X20; //设置 P0_5 为普通 IO 口
P0DIR &= ~0X20; //按键在 P0_5 口,设置为输入模式
P0SEL(0XF3) P0[7:0]功能设置寄存器,默认设置为普通 I/O 口
P0INP(0X8F) P0[7:0]作为输入口时的电路模式寄存器
P0(0X80) P0[7:0]可为寻址的 I/O 寄存器
P0DIR(0XFD) P0 口输入输出设置寄存器,0:输入,1:输出
P0INP &= ~0x20; //打开 P0_5 上拉电阻,不影响
实验设备与芯片选择
全代码如下:
#include <ioCC2530.h>
#define uint unsigned int
#define uchar unsigned char
//定义控制 LED 灯的端口
#define LED1 P2_0 //LED1 为 P2_0 口控制
#define KEY1 P0_5 //KEY1 为 P0_5 口控制
//函数声明
void Delayms(uint); //延时函数
void InitLed(void); //初始化 LED1
void KeyInit(); //按键初始化
uchar KeyScan(); //按键扫描程序
/****************************
延时函数
*****************************/
void Delayms(uint xms) //i=xms 即延时 i 毫秒
{
uint i,j;
for(i=xms;i>0;i--)
for(j=587;j>0;j--);
}
/****************************
LED 初始化函数
*****************************/
void InitLed(void)
{
P2DIR |= 0x01; //P2_0 定义为输出
LED1 = 1; //LED1 灯熄灭
}
/****************************
按键初始化函数
*****************************/
void InitKey()
{
P0SEL &= ~0X20; //设置 P0_5 为普通 IO 口
P0DIR &= ~0X20; //按键在 P0_5 口,设置为输入模式
P0INP &= ~0x20; //打开 P0_5 上拉电阻,不影响
}
/****************************
按键检测函数
*****************************/
uchar KeyScan(void)
{
if(KEY1==0)
{Delayms(10);
if(KEY1==0)
{
while(!KEY1); //松手检测
return 1; //有按键按下
}
}
return 0; //无按键按下
}
/***************************
主函数
***************************/
void main(void)
{
InitLed(); //调用初始化函数
InitKey();
while(1)
{
if(KeyScan()) //按键改变 LED 状态
LED1=~LED1;
}
}
LED 初始化配置:
P0IEN(0XAB) P0[7:0]中断掩码寄存器,0:关中断, 1:开中断
PICTL(0X8C) P0 口的中断触发控制寄存器
Bit0 为 P0[0:7]的中断触法配置:
0:上升沿触发 1:下降沿触发
P0IFG(0X89) P0[7:0]中断标志位,在中断发生时,相应位置 1 IEN1(0XB8) Bit5 为 P0[0:7]中断使能位,0:关中断 1:开中断
P2DIR |= 0x01; //P2_0 定义为输出
外部中断初始化配置:
P0IEN |= 0X20; // P0_5 设置为中断方式
PICTL &=~ 0X20; // 下降沿触发
IEN1 |= 0X20; // 允许 P0 口中断;
P0IFG = 0x00; // 初始化中断标志位
全代码如下:
/*************************************
模块:HALL 模块 功能:使用 KEY1 控制 LED1 亮灭(中断方式)
**************************************/
#include #define uint unsigned int #define uchar unsigned char
//定义控制 LED 灯的端口
#define LED1 P2_0 //LED1 为 P2_0 口控制
#define KEY1 P0_5 //中断口
//函数声明
void Delayms(uint); //延时函数
void InitLed(void); //初始化 LED
void KeyInit(); //按键初始化
uchar KeyValue=0;
/**************************** //延时函数
*****************************/
void Delayms(uint xms) //i=xms 即延时 i 毫秒
{ uint i,j; for(i=xms;i>0;i--) for(j=587;j>0;j--); }
/**************************** //LED 初始化程序
*****************************/
void InitLed(void) { P2DIR |= 0x01; //P2_0 定义为输出
LED1 = 1; //LED1 灯熄灭
}
/**************************** KEY 初始化程序--外部中断方式
*****************************/
void InitKey() { P0IEN |= 0X20; //P0_5 设置为中断方式
PICTL &=~ 0X20; // 下降沿触发
IEN1 |= 0X20; // 允许 P0 口中断
P0IFG = 0x00; // 初始化中断标志位
EA = 1; //开总中断
}
/****************************
中断处理函数
*****************************/
#pragma vector = P0INT_VECTOR //格式:#pragma vector = 中断向量,
__interrupt void P0_ISR(void) //中断处理程序
{ Delayms(10); //去除抖动
LED1=~LED1; //改变 LED1 状态
P0IFG = 0; //清中断标志
P0IF = 0; //清中断标志
}
/***************************
主函数
***************************/
void main(void) { InitLed(); //调用初始化函数
InitKey();
while(1); }
三、步骤:
- 将 CC2530 核心板插在 HALL 传感器底板,使用配套方口 USB 线连接PC 机和 DY-WSN-Kit V1.0 物联网综合开发实训平台,给开发实训平台上电,打开 HALL 传感器底板开关(传感器底板左侧开关),传感器底板电源灯亮起。
- 使用旋钮开关选择 ZigBee 仿真器要连接的设备模块(根据 LED 指示灯是否亮起判断)。在这个实验中,将旋钮选择到 HALL 传感器底板。
- 启动 IAR 开发环境,新建工程,将实验工程中代码拷贝到新建工程中。
- 在 IAR 开发环境中编译、运行、调试程序,并把程序下载到 HALL 传感器底板的 CC2530 核心板上,观察实验现象。
- 关闭开发平台电源,关闭 HALL 传感器底板电源。
注:代码为按键查询和按键中断,此过程重复两次。
初始化时led灯为亮
初始化时led灯为亮
当用磁铁模拟按键时候led会反转状态四、结果与分析:
本项目旨在通过按键控制LED灯的亮灭,利用CC2530芯片进行编程,并通过中断方式实现按键的快速响应。该项目的实现不仅可以帮助理解基本的嵌入式系统编程,还能够展示如何在微控制器上处理外部中断。
项目实现概述
-
硬件配置
使用CC2530芯片。
LED连接至P2_0引脚。
按键连接至P0_5引脚。 -
软件实现
初始化LED灯和按键。
配置按键中断触发方式(下降沿)。
实现延时去抖动。
在中断服务程序中改变LED灯的状态。
代码分析
延时函数
用于在按键按下时进行去抖动处理,避免误触发。
void Delayms(uint xms) {
uint i, j;
for(i = xms; i > 0; i--)
for(j = 587; j > 0; j--);
}
LED 初始化函数
将P2_0引脚设置为输出模式,并初始化LED灯为熄灭状态。
void InitLed(void) {
P2DIR |= 0x01; // P2_0定义为输出
LED1 = 1; // LED1灯熄灭
}
按键初始化函数
将按键连接的P0_5引脚设置为中断输入模式,并配置为下降沿触发。
void InitKey(void) {
P0IEN |= 0x20; // P0_5设置为中断方式
PICTL &=~ 0x20; // 下降沿触发
IEN1 |= 0x20; // 允许P0口中断
P0IFG = 0x00; // 初始化中断标志位
EA = 1; // 开总中断
}
中断处理函数
在按键按下时触发中断,通过延时去抖动后,改变LED灯的状态。
#pragma vector = P0INT_VECTOR
__interrupt void P0_ISR(void) {
Delayms(10); // 去除抖动
LED1 = ~LED1; // 改变LED1状态
P0IFG = 0; // 清中断标志
P0IF = 0; // 清中断标志
}
主函数
初始化LED和按键,并进入一个空循环,等待中断触发。
void main(void) {
InitLed(); // 调用初始化函数
InitKey(); // 调用按键初始化函数
while(1); // 主循环,等待中断触发
}
结果
通过上述代码的实现,本项目能够成功实现按键控制LED灯的亮灭。按下按键时,LED灯状态改变(亮变灭或灭变亮),且响应迅速,能够正确识别按键动作。
项目分析
-
硬件配置
硬件选择合理,使用CC2530芯片的GPIO和中断功能实现按键控制LED。
连接简单,易于实现和调试。 -
软件设计
程序结构清晰,模块化设计。
延时函数有效去抖动,保证了按键检测的准确性。
中断方式响应按键操作,避免了轮询方式的低效问题。 -
优点
响应迅速,按键控制LED的效果明显。
代码易于理解和维护,适合嵌入式系统初学者学习。 -
改进建议
增加更多的按键和LED,扩展功能性。
使用定时器中断进行更精确的延时处理。
增加按键长按和短按功能的识别,丰富控制方式。五、将按键中断程序与按键查询程序进行对比。
按键查询程序
实现原理
按键查询程序通过轮询的方式不断检查按键的状态。如果检测到按键被按下(低电平),则执行相应的操作。
代码实现
#include <ioCC2530.h>
#define uint unsigned int
#define uchar unsigned char
// 定义控制 LED 灯的端口
#define LED1 P2_0 // LED1 为 P2_0 口控制
#define KEY1 P0_5 // KEY1 为 P0_5 口控制
// 函数声明
void Delayms(uint xms); // 延时函数
void InitLed(void); // 初始化 LED1
void InitKey(void); // 按键初始化
uchar KeyScan(void); // 按键扫描程序
/****************************
延时函数
*****************************/
void Delayms(uint xms) {
uint i, j;
for(i = xms; i > 0; i--)
for(j = 587; j > 0; j--);
}
/****************************
LED 初始化函数
*****************************/
void InitLed(void) {
P2DIR |= 0x01; // P2_0 定义为输出
LED1 = 1; // LED1 灯熄灭
}
/****************************
按键初始化函数
*****************************/
void InitKey(void) {
P0SEL &= ~0x20; // 设置 P0_5 为普通 IO 口
P0DIR &= ~0x20; // 按键在 P0_5 口,设置为输入模式
P0INP &= ~0x20; // 打开 P0_5 上拉电阻
}
/****************************
按键检测函数
*****************************/
uchar KeyScan(void) {
if (KEY1 == 0) {
Delayms(10); // 去抖动
if (KEY1 == 0) {
while (!KEY1); // 松手检测
return 1; // 有按键按下
}
}
return 0; // 无按键按下
}
/****************************
主函数
****************************/
void main(void) {
InitLed(); // 调用初始化函数
InitKey(); // 调用按键初始化函数
while (1) {
if (KeyScan()) // 按键改变 LED 状态
LED1 = ~LED1;
}
}
按键中断程序
实现原理
按键中断程序设置按键为中断输入,配置为下降沿触发。当按键被按下时,触发中断服务程序,执行相应的操作。
代码实现
#include <ioCC2530.h>
#define uint unsigned int
#define uchar unsigned char
// 定义控制 LED 灯的端口
#define LED1 P2_0 // LED1 为 P2_0 口控制
#define KEY1 P0_5 // 中断口
// 函数声明
void Delayms(uint xms); // 延时函数
void InitLed(void); // 初始化 LED1
void InitKey(void); // 按键初始化
uchar KeyValue = 0;
/****************************
延时函数
*****************************/
void Delayms(uint xms) {
uint i, j;
for (i = xms; i > 0; i--)
for (j = 587; j > 0; j--);
}
/****************************
LED 初始化函数
*****************************/
void InitLed(void) {
P2DIR |= 0x01; // P2_0 定义为输出
LED1 = 1; // LED1 灯熄灭
}
/****************************
按键初始化函数 -- 外部中断方式
*****************************/
void InitKey(void) {
P0IEN |= 0x20; // P0_5 设置为中断方式
PICTL &= ~0x20; // 下降沿触发
IEN1 |= 0x20; // 允许 P0 口中断
P0IFG = 0x00; // 初始化中断标志位
EA = 1; // 开总中断
}
/****************************
中断处理函数
*****************************/
#pragma vector = P0INT_VECTOR
__interrupt void P0_ISR(void) {
Delayms(10); // 去除抖动
LED1 = ~LED1; // 改变 LED1 状态
P0IFG = 0; // 清中断标志
P0IF = 0; // 清中断标志
}
/****************************
主函数
****************************/
void main(void) {
InitLed(); // 调用初始化函数
InitKey(); // 调用按键初始化函数
while (1); // 主循环,等待中断触发
}
对比分析
轮询方式(按键查询程序)
优点:
- 实现简单,易于理解和调试。
- 不需要配置中断相关的寄存器。
缺点:
- 效率低,CPU需要不断轮询按键状态,浪费处理器资源。
- 在复杂系统中,这种方式可能导致响应不及时。
中断方式(按键中断程序)
优点:
- 响应迅速,按键按下时立即触发中断,无需轮询。
- CPU资源利用效率高,可以在空闲时处理其他任务。
缺点:
- 需要配置中断相关的寄存器,程序复杂度较高。
- 需要注意中断优先级和中断处理时的竞态条件等问题。
涉及中断的代码
中断初始化代码
void InitKey(void) {
P0IEN |= 0x20; // P0_5 设置为中断方式
PICTL &= ~0x20; // 下降沿触发
IEN1 |= 0x20; // 允许 P0 口中断
P0IFG = 0x00; // 初始化中断标志位
EA = 1; // 开总中断
}
中断处理函数
#pragma vector = P0INT_VECTOR
__interrupt void P0_ISR(void) {
Delayms(10); // 去除抖动
LED1 = ~LED1; // 改变 LED1 状态
P0IFG = 0; // 清中断标志
P0IF = 0; // 清中断标志
}
通过对比可以看出,轮询方式适合简单的、对实时性要求不高的应用场景。而中断方式更加高效,适合对响应速度要求较高的应用,能够充分利用CPU资源。
评论(0)
您还未登录,请登录后发表或查看评论