ZigBee的IO操作与中断
ZigBee无线模块基本工作电路
TI示范CC2530应用电路
DIE ATTACH PAD
—接地XOSC_Q1、XOSC_Q2
—接晶振,为CPU提供32MHz高频时钟源RF_N、RF_P
—无线信号收发C401
—去耦电容R301
—偏置电阻P2_3、P2_4
—可选,提供32.768KHz低频时钟源(主要为睡眠定时器、看门狗使用)
ZigBee无线模块电路
增设复位电路,复位键按下产生超过1us的低电平
增设JTAG下载电路
GPIO设置
IO相关寄存器
- CC2530只具备QFN40封装
- 工作范围:2~3.6V(推荐选3.3V)
- 21个通用IO口,其中21个分为3组P0/P1/P2
- 21个端口都可以作为普通IO或片上外设控制
以配置P1_0
为输出为例:
P1SEL &= 0xFE; //让P1_0处于普通IO模式
P1DIR |= 0x01; //让P1_0处于输出状态
P1_0 = 1; //将P1_0电平拉高
IO口配置相关寄存器
PxSEL
、PxDIR
、PxINP
3种寄存器,x=0,1,2
,复位默认都是0
PxSEL
寄存器作用:有8位,每一位对应一个IO口,0表示普通IO口,1表示片上外设
PxSEL寄存器位,x=0,1 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
Px对应IO口的位 | Px_7 | Px_6 | Px_5 | Px_4 | Px_3 | Px_2 | Px_1 | Px_0 |
P2
组只有5个口,P2_1和P2_2用于下载程序用,不需配置
P2SEL寄存器位 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
P2对应IO口的位 | P2_4 | P2_3 | P2_0 |
PxDIR
寄存器作用:有8位,每一位对应一个IO口,0表示输入,1表示输出
PxDIR寄存器位,x=0,1 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
Px对应IO口的位 | Px_7 | Px_6 | Px_5 | Px_4 | Px_3 | Px_2 | Px_1 | Px_0 |
P2
组只有5个口,后面的位不用管
P2DIR寄存器位 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
P2对应IO口的位 | P2_4 | P2_3 | P2_2 | P2_1 | P2_0 |
PxINP
寄存器作用:在输入的时候,有8位,每一位对应一个IO口,决定它是上下拉模式还是三态,0表示上下拉模式,1表示三态
PxINP寄存器位,x=0,1 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
Px对应IO口的位 | Px_7 | Px_6 | Px_5 | Px_4 | Px_3 | Px_2 | Px_1 | Px_0 |
P2
组只有5个口,后面的三位决定在配置为上下拉模式时,组为上拉/下拉,0表示上拉,1表示下拉
P2INP寄存器位 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
P2对应IO口的位 | P2组 | P1组 | P0组 | P2_4 | P2_3 | P2_2 | P2_1 | P2_0 |
三个端口寄存器
Bit | Reset | R/W | |
---|---|---|---|
P0 | 7:0 | 0xFF | R/W |
P1 | 7:0 | 0xFF | R/W |
P2 | 4:0 | 0xFF | R/W |
基础按键实验
按键KEY1(P0_0
)控制LED1(P1_0
)亮/灭
#include <iocc2530.h>
#define uint unsigned int
void Delayms(uint xms){
uint i,j;
for(i=xms;i>0;i--)
for(j=587;j>0;j--);
}
int main()
{
P1SEL &= 0xFE; //P1_0普通IO 1111 1110
P1DIR |= 0x01; //输出 0000 0001
P1_0 = 0;
P0SEL &= 0xFE; //P0_0 1111 1110
P0DIR &= 0xFE; //输入 1111 1110
P0INP &= 0xFE; //上下拉模式 1111 1110
P2INP &= 0xDF; //P0_0上拉1101 1111
//按键轮询
while(1){
if(P0_0 == 0){
Delayms(10); //防抖
if(P0_0 == 0){
while(!P0_0); //松手检测
P1_0 = ~P1_0; //电平翻转
}
}
}
}
外部中断配置
中断总览
配置流程
- 初始化IO工作在普通IO、上拉输入状态
- 首先开IO口组中断
- 开组内对应的某具体IO口中断
- 上升沿还是下降沿触发
- 开CPU总中断EA=1
IO中断寄存器
组配置IEN0
寄存器相关位:EA
IEN0寄存器 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
名称 | EA | - | STIE | ENCIE | UR1XIE | URX0IE | ADCIE | RFERRIE |
组配置IEN1
寄存器相关位:P0IE
IEN1寄存器 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
名称 | - | - | P0IE | T4IE | T3IE | T2IE | T1IE | DMAIE |
组配置IEN2
寄存器相关位:P1IE
、P2IE
(由于寄存器地址不是0/8结尾,这里不能直接操作P1IE
、P2IE
)
IEN2寄存器 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
名称 | - | - | WDTIE | P1IE | UT1XIE | UTX0IE | P2IE | RFIE |
组内配置寄存器P0IEN
BIt | Name | Reset | R/W |
---|---|---|---|
7:0 | P0_[7:0]IEN | 0x00 | R/W |
组内配置寄存器P1IEN
BIt | Name | Reset | R/W |
---|---|---|---|
7:0 | P1_[7:0]IEN | 0x00 | R/W |
组内配置寄存器P2IEN
BIt | Name | Reset | R/W |
---|---|---|---|
7:6 | - | 00 | R/W |
5 | DPIEN | 0 | R/W |
4:0 | P2_[4:0]IEN | 00000 | R/W |
组中断控制寄存器PICTL
:0代表上升沿触发,1代表下降沿触发
PICTL寄存器 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
控制端口 | I/O驱动能力 | - | - | - | P2_0~P0_4 | P1_4~P1_7 | P1_0~P1_3 | P0_0~P0_7 |
中断标志寄存器IRCON
相关位:P0IF
IRCON寄存器 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
名称 | STIF | - | P0IF | T4IF | T3IF | T2IF | T1IF | DMAIF |
中断标志寄存器IRCON
相关位:P1IF
、P2IF
IRCON寄存器 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
名称 | - | - | - | WDTIF | P1IF | UTX1IF | UTX0IF | P2IF |
按键中断处理示例
按键KEY1(P0_0
)控制LED1(P1_0
)亮/灭
#include <IOCC2530.h>
void delay(){
int i, j;
for(i=0;i<1000;i++)
for(j=0;j<30;j++);
}
int main()
{
//P0_0配置
P0SEL &= 0xFE; //1111 1110
P0DIR &= 0xFE; //1111 1110
P0INP &= 0xFE; //1111 1110
P2INP &= 0xDF; //1101 1111 上拉
//中断寄存器配置
EA = 1;
P0IE = 1;
P0IEN |= 0x01; //0000 0001
PICTL |= 0x01; //0000 0001 P0组下降沿触发
//P1_0配置
P1DIR |= 0x01;
P1_0 = 0;
while(1);
}
//进入按键中断
#pragma vector=P0INT_VECTOR
__interrupt void P0_ISR(){
if(P0IFG &= 0x01){ //0000 0001
//P0组第一位发生外部中断
delay();
if(P0_0 == 0){
P1_0 ^= 1;
}
}
P0IFG = 0;
P0IF = 0;
}
中断函数模板
#pragma vector=PxINT_VECTOR
__interrupt void fun(){
//
//中断响应,处理事件
//
P0IFG = 0;
P0IF = 0;
}