目录
4.1点亮1个LED实验
了解芯片IO的基本配置方法,点亮1个LED。
首先根据开发板硬件原理图确定LED与CC2530芯片的连接引脚,如图4-1所示。
图4-1 开发板LED原理图
可以看到开发板上的3个LED分别连接在芯片的P10、P11及P14引脚,P10、P11低电平点亮,P14高电平点亮,要使芯片P10引脚输出低电平需要配置三个IO口配置寄存器 P1SEL、P1DIR、P1INP,如表4-1所示。
表4-1 IO口寄存器说明
P1SEL |
端口1功能选择寄存器 |
0:通用IO;1:外设功能 |
P1DIR |
端口1方向选择寄存器 |
0:输入;1:输出 |
P1INP |
端口1输入模式寄存器 |
0:上拉/下拉;1:三态 |
P1 |
端口1 IO寄存器 |
|
按照表4-1寄存器说明,我们对P10端口进行配置,当P10输出低电平时 LED中的D3被点亮,配置如下:
#define LED1 P1_0 //定义P10口为D3(LED1)控制端
P1SEL &= ~0x01; // P10口作为普通 IO 口
P1DIR |= 0x01; //P10口定义为输出
LED1 = 0; //输出低电平
由于P1SEL寄存器上电默认为0x00,所以仅需要配置:
P1DIR |= 0x01; //P10 定义为输出
LED1 = 0x00; //输出低电平
具体程序如下:
#include <ioCC2530.h>
#define LED1 P1_0 //定义P10口为D3(LED1)控制端
void main(void)
{
P1DIR |= 0x01; //P10定义为输出
LED1 = 0; //输出低电平
while(1);
}
观察开发板D3(LED1)灯,D3灯常亮。
4.2流水灯实验
了解使用空循环延时的方法,循环点亮2个LED。
首先根据开发板硬件原理图确定LED与CC2530芯片的连接引脚,如图4-2所示。
图4-2开发板LED原理图
可以看到开发板上的3个LED分别连接在芯片的P10、P11及P14引脚,P10、P11低电平点亮,P14高电平点亮,按照上一节点亮单个LED的说明,我们分别对D3、D4进行配置,循环点亮D 3,D4。
具体程序如下:
#include <ioCC2530.h>
#define LED1 P1_0 //定义P10口为D3(LED1)控制端
#define LED2 P1_1 //定义P11口为D4(LED2)控制端
/****************************
//延时
*****************************/
void Delay(int n)
{
int i;
for(i=0;i<n;i++);
for(i=0;i<n;i++);
for(i=0;i<n;i++);
for(i=0;i<n;i++);
for(i=0;i<n;i++);
}
/***************************
//主函数
***************************/
void main(void)
{
P1DIR |= 0x03; //P1_0,P1_1定义为输出
LED1 = 1;
LED2 = 1;
while(1)
{
LED1 = ! LED1;
LED2 = ! LED2;
Delay(10000);
}
}
观察开发板,依次点亮D3(LED1)和D4(LED2),2个LED不停的闪烁。
4.3按键控制LED实验
了解使用按键方法,使用按键切换LED的状态。
首先根据开发板硬件原理图确定LED与CC2530芯片的连接引脚,如图4-3所示。
图4-3开发板LED和按键原理图
可以看到开发板上的D3连接在芯片的P10引脚,按键S3连接在芯片的P04引脚,按照4.1节点亮单个LED的说明,我们分别对P10配置为输出,对按键引脚P04配置为输入,由于外部连接有上拉电阻所以不需要配置引脚的内部上拉。
具体程序如下:
#include <ioCC2530.h>
#define uint unsigned int
#define uchar unsigned char
//定义控制LED灯的端口
#define LED1 P1_0 // D3(LED1)为P10口控制
#define KEY1 P0_4 //S3(KEY1)为P04口控制
//函数声明
void Delayms(uint); //延时函数
void InitLed(void); //初始化D3(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)
{
P1DIR |= 0x01; //P10定义为输出
LED1 = 1; // D3(LED1)灯熄灭
}
/****************************
按键初始化函数
*****************************/
void InitKey()
{
P0SEL &= ~0X10; //设置P04为普通IO口
P0DIR &= ~0X10; //按键在P04口,设置为输入模式
P0INP &= ~0x10; //打开P04上拉电阻,不影响
}
/****************************
按键检测函数
*****************************/
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;
}
}
}
按下开发板按键S3(KEY1)控制D3(LED1)的亮和灭。
4.4外部中断实验
了解使用外部中断的方法,在中断处理函数中切换LED的状态。
首先根据开发板硬件原理图确定LED与CC2530芯片的连接引脚,如图4-4所示。
图4-4开发板LED和按键原理图
与上一节相同,D3连接在芯片的P10引脚,按键S3连接在芯片的P04引脚,按照4.1节点亮单个LED的说明,我们对P10配置为输出。
CC2530 的外部中断我们需要配置三个寄存器P0IEN、PICTL、P0IFG、IEN1,配置寄
存器将按键引脚P04的中断使能与总中断打开,使用到的寄存器如表4-2所示
表4-2外部中断寄存器说明
P0IEN(0xAB) |
P0[7:0]中断掩码寄存器。0:关中断 1:开中断 |
PICTL(0x8C) |
P0口的中断触发控制寄存器 |
P0IFG(0x89) |
P0[7:0]中断标志位,在中断发生时,相应位置1 |
IEN1(0xB8) |
Bit5为P0[7:0]中断使能位:0:关中断 1:开中断 |
具体程序如下:
#include <ioCC2530.h>
#define LED1 P1_0
/****************************
//初始化按键为中断输入方式
*****************************/
void InitKeyINT(void)
{
P0IEN |= 0X10; //P04设置为中断方式
PICTL |= 0X01; //下降沿触发
EA = 1; //总中断使能
IEN1 |= 0X20; //P0中断使能;
P0IFG |= 0x00; //初始化中断标志位
}
/***************************
//主函数
***************************/
void main(void)
{
P1DIR |= 0x01; //P10定义为输出
LED1 = 1;
InitKeyINT();
while (1) ;
}
/****************************
//中断处理函数
*****************************/
#pragma vector = P0INT_VECTOR
__interrupt void P0_ISR(void)
{
if (P0IFG > 0) //按键中断
{
LED1 = !LED1;
P0IFG = 0; //清中断标志
}
}
按下开发板按键S3(KEY1)控制D3(LED1)的亮和灭。
4.5定时器实验
了解使用定时器的方法,定时切换LED的状态.
首先根据开发板硬件原理图确定LED与CC2530芯片的连接引脚,如图4-5所示。
图4-5开发板LED原理图
与4.1节相同, D3连接在芯片的P10引脚,按照4.1节点亮单个LED的说明,我们对P10配置为输出,配置寄存器将定时器1的中断使能与总中断打开,使用到的寄存器如表4-3所示:
表4-3定时器1寄存器说明
T1CTL |
位3:2 配置定时器值分频器划分值 |
TIMIF |
位6 位定时器1中断屏蔽位 |
IEN1(0XB8) |
位1为定时器1中断使能 |
T1STAT |
定时器1状态位 |
具体程序如下:
#include <ioCC2530.h>
#define LED1 P1_0
/****************************
//T1初始化程序
***************************/
void InitialT1test(void)
{
//初始化计数器1
T1CTL = 0x0D;
TIMIF = 0x40;
IEN1 = 0x02;
EA = 1; //总中断使能
T1STAT = 0; //清中断标志
}
/***************************
//主函数
***************************/
void main(void)
{
P1DIR = 0x01; //P1_0 定义为输出
LED1 = 1;
InitialT1test();
while (1) ;
}
//中断处理函数
#pragma vector = T1_VECTOR
__interrupt void T1_ISR(void)
{
if (T1STAT > 0) //按键中断
{
LED1 = ! LED1;
T1STAT = 0; //清中断标志
}
}
观察开发板,D3(LED1)周期性闪烁。
4.6串口数据收发实验
1.了解串口通信的相关知识;
2.学习CC2530单片机串口相关寄存器配置,实现串口通信功能;
CC2530芯片有两个串行接口UART0和UART1:
UART0对应RXD(P02)、TXD(P03);
UART1对应RXD(P04)、TXD(P05);
在开发板中只接出了串口0(UART0),从串口原理图就可以看出,CC2530的串口信号与P02、P03复用,由于USB接口的众多优势,越来越普遍的被应用到计算机以及工业现场,而RS232接口的市场地位也逐渐淡漠,如图4-6所示,我们的开发板将RS232 信号通过PL2303转换为USB信号与电脑或者工业设备进行串口通信。
图4-6 开发板串口TTL与USB转换电路原理图
要实现CC2530的串口通信除了掌握硬件电路原理,还有一个关键的环节就是有关串口通信寄存器软件配置U0CSR、U0GCR、U0BAUD、U0DBUF、UTX0IF,串口相关寄存器功能描述如表4-4所示:
表4-4相关寄存器功能描述
U0CSR(UART0 控 制和状态寄存器)
|
Bit7:MODE |
0:SPI 模式 |
1:UART 模式 |
||
Bit6:RE |
0:接收器禁止 |
|
1:接收器使能 |
||
Bit5:SLAVE |
0:SPI 主模式 |
|
1:SPI 从模式 |
||
Bit4:FE |
0:没有检测出帧错误 |
|
1:收到字节停止位电平出错 |
||
Bit3:ERR |
0:没有检测出奇偶检验出错 |
|
1:收到字节奇偶检验出错 |
||
Bit2:RX_BYTE |
0:没有收到字节 |
|
1:收到字节就绪 |
||
Bit1:TX_BYTE |
0:没有发送字节 |
|
1:写到数据缓冲区寄存器的最后字节已 经发送 |
||
Bit0:ACTIVE |
0:USART空闲 |
|
1:USART忙 |
||
U0GCR(UART0 通 用控制寄存器) |
Bit7:CPOL |
0:SPI 负时钟极性 |
1:SPI 正时钟极性 |
||
Bit6:CPHA |
0:当来自 CPOL 的 SCK 反相之后又返回CPOL 时,数据输出到 MOSI;当来自 CPOL的 SCK 返回 CPOL 反相时,输入数据采样到MISO |
|
1:当来自 CPOL 的 SCK 返回 CPOL 反相时,数据输出到 M OSI ;当来自 CPOL 的 SCK 反相之后又返回 CPOL 时,输入数据采样到 MISO |
||
Bit5:ORDER |
0:LSB 先传送 |
|
1:MSB 先传送 |
||
Bit[4:0]:BAUD_E |
波特率指数值 BAUD_E 连同 BAUD_M 一起决定了 UART 的波特率 |
|
U0BAUD(UART0 波特率控制寄存器) |
Bit[7:0]:BAUD_M |
波特率尾数值 BAUD_M 连同 BAUD_E 一起决定了 UART 的波特率 |
U0DBUF ( UART0 收发数据缓冲区) |
|
串口发送/接收数据缓冲区 |
UTX0IF(发送中断 标志) |
中断标志5 IRCON2 的Bit1 |
0:中断未挂起 |
1:中断挂起 |
在本实验中我们采用USART0接口,具体的软件操作以及串口寄存器配置步骤如下:
1、硬件接口配置,配置P02和P03用作串口 UART0。
2、配置相应串口的控制和状态寄存器。
3、配置串口工作的波特率。CC2530单片机的串口数据传输的波特率决定于通用控制寄存器U0GCR的Bit[4:0]——BAUD_E和波特率控制寄存器U0BAUD——BAUD_M,具体的计算公式如式4-1
波特率
在32MHz的系统时钟下常用的波特率所对应的BAUD_M和BAUD_E的值如下表4-5。
表4-5在32MHz的系统时钟下常用的波特率所对应的BAUD_M和BAUD_E的值
常用的波特率 |
BAUD_M |
BAUD_E |
误差 |
2400 |
59 |
6 |
0.14 |
4800 |
59 |
7 |
0.14 |
9600 |
59 |
8 |
0.14 |
14400 |
216 |
9 |
0.03 |
19200 |
59 |
10 |
0.14 |
28800 |
216 |
11 |
0.03 |
38400 |
59 |
12 |
0.14 |
57600 |
216 |
13 |
0.03 |
76800 |
59 |
14 |
0.14 |
115200 |
216 |
15 |
0.03 |
230400 |
216 |
16 |
0.03 |
串口寄存器配置程序如下
CLKCONCMD &= ~0x40; //设置系统时钟源为 32MHZ 晶振
while(CLKCONSTA & 0x40); //等待晶振稳定
CLKCONCMD &= ~0x47; //设置系统主时钟频率为 32MHZ
PERCFG = 0x00; //位置 1 P0 口
P0SEL = 0x3c; //P0_2,P0_3,P0_4,P0_5 用作串口,第二功能
P2DIR &= ~0XC0; //P0 优先作为 UART0 ,优先级
U0CSR |= 0x80; //UART 方式
U0GCR |= 11; //U0GCR 与 U0BAUD 配合
U0BAUD |= 216; // 波特率设为 9600
UTX0IF = 0; //UART0 TX 中断标志初始置位 1 (收发时候)
U0CSR |= 0X40; //允许接收
IEN0 |= 0x84; // 开总中断,接收中断
具体程序如下:
#include <ioCC2530.h>
#include <string.h>
#define uint unsigned int
#define uchar unsigned char
//定义控制LED灯的端口
#define LED1 P1_0 //定义LED1为P10口控制
#define LED2 P1_1 //定义LED1为P11口控制
//函数声明
void Delayms(uint xms); //延时函数
void InitLed(void); //初始化P1口
void InitUart(); //初始化串口
void Uart_Send_String(char *Data,int len);
char Rxdata[50];
uchar RXTXflag = 1;
char temp;
uchar datanumber = 0;
/****************************
延时函数
*****************************/
void Delayms(uint xms)
{
uint i,j;
for(i=xms;i>0;i--)
for(j=587;j>0;j--);
}
/****************************
//初始化程序
*****************************/
void InitLed(void)
{
P1DIR |= 0x03; //P10、P11定义为输出
LED1 = 0;
LED2 = 0;
}
/****************************************************************
串口初始化函数
***********************************************************/
void InitUart()
{
CLKCONCMD &= ~0x40; // 设置系统时钟源为 32MHZ晶振
while(CLKCONSTA & 0x40); // 等待晶振稳定
CLKCONCMD &= ~0x47; // 设置系统主时钟频率为 32MHZ
PERCFG = 0x00; //位置1 P0口
P0SEL = 0x3c; //P0_2,P0_3,P0_4,P0_5用作串口,第二功能
P2DIR &= ~0XC0; //P0优先作为UART0 ,优先级
U0CSR |= 0x80; //UART 方式
U0GCR |= 8; //U0GCR与U0BAUD配合
U0BAUD |= 59; //波特率设为9600
UTX0IF = 0; //UART0 TX 中断标志初始置位1 (收发时候)
U0CSR |= 0X40; //允许接收
IEN0 |= 0x84; //开总中断,接收中断
}
/****************************************************************
串口发送字符串函数
****************************************************************/
void Uart_Send_String(char *Data,int len)
{
int j;
for(j=0;j<len;j++)
{
U0DBUF = *Data++;
while(UTX0IF == 0); //发送完成标志位
UTX0IF = 0;
}
}
/***************************
//主函数
***************************/
void main(void)
{
InitLed(); //调用初始化函数
InitUart();
while(1)
{
if(RXTXflag == 1) //接收状态
{
LED1=1; //接收状态指示
if( temp != 0)
{
//'#'被定义为结束字符,最多能接收50个字符
if((temp!='#')&&(datanumber<50))
{
Rxdata[datanumber++] = temp;
}
else
{
RXTXflag = 3; //进入发送状态
LED1=0; //关指示灯
}
temp = 0;
}
}
if(RXTXflag == 3) //发送状态
{
LED2= 1;
U0CSR &= ~0x40; //禁止接收
Uart_Send_String(Rxdata,datanumber); //发送已记录的字符串。
U0CSR |= 0x40; //允许接收
RXTXflag = 1; //恢复到接收状态
datanumber = 0; //指针归0
LED2 = 0; //关发送指示
}
}
}
/****************************************************************
串口接收一个字符: 一旦有数据从串口传至CC2530, 则进入中断,
将接收到的数据赋值给全局变量temp.
****************************************************************/
#pragma vector = URX0_VECTOR
__interrupt void UART0_ISR(void)
{
URX0IF = 0; //清中断标志
temp = U0DBUF;
}
实验时,下载程序到开发板后,插上USB线,然后将S1开关拨到ON,即可进行串口实验,实验效果如图4-7所示
图4-7 实验效果图
扩展知识——串口通信基础
在串行通信中,数据在1位宽的单条线路上进行传输,一个字节的数据要分为8次,由低位到高位按顺序一位一位的进行传送。
串行通信的数据是逐位传输的,发送方发送的每一位都具有固定的时间间隔,这就要求接收方也要按照发送方同样的时间间隔来接收每一位。不仅如此,接收方还必须能够确定一个信息组的开始和结束。
常用的两种基本串行通信方式包括同步通信和异步通信。
异步通信规定传输的数据格式由起始位(start bit)、数据位(data bit)、奇偶校验位(parity bit)和停止位(stop bit)组成,如图4-8所示(该图中未画出奇偶校验位,因为奇偶检验位不是必须有的,如果有奇偶检验位,则奇偶检验位应该在数据位之后,停止位之前)。
图4-8 异步通信数据格式
(1)起始位:起始位必须是持续一个比特时间的逻辑0电平,标志传输一个字符的开始,接收方可用起始位使自己的接收时钟与发送方的数据同步。
(2)数据位:数据位紧跟在起始位之后,是通信中的真正有效信息。数据位的位数可以由通信双方共同约定,一般可以是5位、7位或8位,标准的ASCII码是0~127(7位),扩展的ASCII码是0~255(8位)。传输数据时先传送字符的低位,后传送字符的高位。
(3)奇偶校验位:奇偶校验位仅占一位,用于进行奇校验或偶校验,奇偶检验位不是必须有的。如果是奇校验,需要保证传输的数据总共有奇数个逻辑高位;如果是偶校验,需要保证传输的数据总共有偶数个逻辑高位。
举例来说,假设传输的数据位为01001100,如果是奇校验,则奇校验位为0(要确保总共有奇数个1),如果是偶校验,则偶校验位为1(要确保总共有偶数个1)。
由此可见,奇偶校验位仅是对数据进行简单的置逻辑高位或逻辑低位,不会对数据进行实质的判断,这样做的好处是接收设备能够知道一个位的状态,有可能判断是否有噪声干扰了通信以及传输的数据是否同步。
(4)停止位:停止位可以是是1位、1.5位或2位,可以由软件设定。它一定是逻辑1电平,标志着传输一个字符的结束。
(5)空闲位:空闲位是指从一个字符的停止位结束到下一个字符的起始位开始,表示线路处于空闲状态,必须由高电平来填充。
4.7 AD采集内部温度实验
1.学习CC2530内部温度传感器控制;
2.学习AD数据采集;
3.实现CC2530温度采集并通过串口发送到上位机。
温度检测在工业现场以及物联网领域都有着较为广泛的应用,对于智能控制需要以采集到的环境温度作为控制依据,CC2530单片机在芯片的内部就集成了温度传感器,不需要再外接温度传感器电路,提高了系统的集成度,降低了电路设计的复杂度,但是传感器与MCU的集成由于芯片本身的发热会导致检测温度的偏差,通常需要软件的矫正。
要实现CC2530的温度检测并通过串口发送给上位机,在串口通信部分已经将通信解决,在需要的就是AD与温度检测寄存器的相关配置,所涉及到的寄存器有:
CC2530 的内部温度检测需要配置的寄存器比较多,包括温度和 AD 的
CLKCONCMD、PERCFG、U0CSR、U0GSR、U0BAUD、CLKCONSTA、IEN0、U0DUB、ADCCON1、ADCCON3、ADCH、ADCL。各寄存器功能如下表4-6所示:
表4-6 AD温度检测相关寄存器功能描述
ADC控制寄存器1ADCCON1(0XB4) |
ADC 转换完成标志位Bit7:EOC |
0:AD 转换进行中 |
1:AD 转换完成 |
||
手动启动 AD 转换 Bit6:RE |
0:关 |
|
1:启动 AD 转换(需要 Bit5:Bit4=11) |
||
AD 转换启动方式选择 Bit[5:4] |
00:外部触发 |
|
01:全速转换,不需要触发 |
||
10:T1 通道 0 比较触发 |
||
11:手动触发 |
||
16 位随机数发生器控制位 Bit[3:2]FE |
00:普通模式 (13x 打开) |
|
01:开启 LFSR 时钟一次 (13x 打开) |
||
10:保留位 |
||
11:关 |
||
序列 AD 转换控制寄存器 2ADCCON2(0XB5) |
选择 AD 转换参考电压SREF Bit[7:6] |
00:内部参考电压(1.25V) |
01:外部参考电压 AIN7 输入 |
||
10:模拟电源电压 |
||
11:外部参考电压 AIN6-AIN7 差分输入 |
||
设置 AD 转换分辨率Bit[5:4] |
00: 64dec,7位有效 |
|
01: 128dec,9位有效 |
||
10: 256dec,10位有效 |
||
11: 512dec,12位有效 |
||
设置序列 AD 转换最末通道,如果置位 时 ADC 正在运行,则在完成序列 AD 转换后立刻开始, 否则置位后立即开始 AD 转换,转换完成后自动清 0. Bit[3:0]ORDER |
0000: AIN0 |
|
0001: AIN1 |
||
0010: AIN2 |
||
0011: AIN3 |
||
0100: AIN4 |
||
0101: AIN5 |
||
0110: AIN6 |
||
0111: AIN7 |
||
1000: AIN0-AIN1 差分 |
||
1001: AIN2-AIN3 差分 |
||
1010: AIN4-AIN5 差分 |
||
1011: AIN6-AIN7 差分 |
||
1100:GND |
||
1101:保留 |
||
1110:温度传感器 |
||
1111:1/3模拟电源电压 |
||
Bit[4:0]:BAUD_E |
波特率指数值 BAUD_E 连同 BAUD_M 一起决定了 UART 的波特率 |
|
单通道 AD 转换控制寄存器 2 ADCCON3(0XB5) |
选择单通道AD 转换参考电压SREF Bit[7:6]: |
00:内部参考电压(1.25V) |
01:外部参考电压 AIN7 输入 |
||
10:模拟电源电压 |
||
11 :外部参考电压 AIN6-AIN7 差分输入 |
||
设置单通道 AD 转换分辨率 Bit[5:4] |
00: 64dec,7 位有效 |
|
01: 128dec,9 位有效 |
||
10: 256dec,10 位有效 |
||
11: 512dec,12 位有效 |
||
单通道 AD 转换选择,如果置位时 ADC 正在运行,则在完成 AD 转换后立刻开始,否则置位后 立即开始 AD 转换,转换完成后自动清 0. Bit[3:0] |
0000:AIN0 |
|
0001: AIN1 |
||
0010:AIN2 |
||
0011: AIN3 |
||
0100:AIN4 |
||
0101: AIN5 |
||
0110:AIN6 |
||
0111: AIN7 |
||
1000:AIN0-AIN1 差分 |
||
1001: AIN2-AIN3 差分 |
||
1010:AIN4-AIN5 差分 |
||
1011: AIN6-AIN7 差分 |
||
1100:GND |
||
1101:保留 |
||
1110:温度传感器 |
||
1111:1/3 模拟电源电压 |
||
TR0 (0x624B) |
Bit0 |
置 1 表示将温度传感器与 ADC 连接起来 |
ATEST(0x61BD) |
Bit0 |
置 1 表示将温度传感器启用 |
根据表中相关寄存器的功能说明,具体进行如下配置:
TR0 = 0X01; //置”1”连接温度传感器与AD采集
ATEST= 0X01; // 使能温度传感器功能
AD 数据采集配置:
ADCCON3 = (0x3E); //选择 1.25V 为参考电压;14 位分辨率;片内采样
ADCCON1 |= 0x30; //选择 ADC 的启动模式为手动
ADCCON1 |= 0x40; //启动 AD 转换
具体程序如下:
#include <ioCC2530.h>
#define uint unsigned int
#define uchar unsigned char
#define uint16 unsigned short
#define DISABLE_ALL_INTERRUPTS() (IEN0 = IEN1 = IEN2 = 0x00)
/**************************
系统时钟 不分频
计数时钟 32分频
**************************/
void InitClock(void)
{
CLKCONCMD &= ~0x40; //设置系统时钟源为 32MHZ晶振
while(CLKCONSTA & 0x40); //等待晶振稳定
CLKCONCMD &= ~0x47; //设置系统主时钟频率为 32MHZ
}
/********************************************************
温度传感器初始化函数
********************************************************/
void initTempSensor(void)
{
DISABLE_ALL_INTERRUPTS(); //关闭所有中断
InitClock(); //设置系统主时钟为 32M
TR0=0X01; //set '1' to connectthe temperature sensorto the SOC_ADC.
ATEST=0X01; // Enablesthe temperature sensor
}
/****************************************************************
读取温度传感器 AD 值函数
****************************************************************/
float getTemperature(void)
{
uint value;
ADCCON3 = (0x3E); //选择1.25V为参考电压;14位分辨率;对片内温度传感器采样
ADCCON1 |= 0x30; //选择ADC的启动模式为手动
ADCCON1 |= 0x40; //启动AD转化
while(!(ADCCON1 & 0x80)); //等待 AD 转换完成
value = ADCL >> 4; //ADCL 寄存器低 2 位无效
value |= (((uint16)ADCH) << 4);
return (value-1367.5)/4.5-5; //根据 AD 值,计算出实际的温度,芯片手册有错,温度系数应该是4.5 /℃
//进行温度校正,这里减去5℃(不同芯片根据具体情况校正)
}
/*****************************************
串口初始化函数:初始化串口 UART0
*****************************************/
void InitUART0(void)
{
PERCFG = 0x00; //位置1 P0口
P0SEL = 0x3c; //P0用作串口
P2DIR &= ~0XC0; //P0优先作为UART0
U0CSR |= 0x80; //串口设置为UART方式
U0GCR |= 8;
U0BAUD |= 59; //波特率设为9600
UTX0IF = 1; //UART0 TX中断标志初始置位1
U0CSR |= 0X40; //允许接收
IEN0 |= 0x84; //开总中断,接收中断
}
/****************************************************************
串口发送字符串函数
****************************************************************/
void UartTX_Send_String(char *Data,int len)
{
int j;
for(j=0;j<len;j++)
{
U0DBUF = *Data++;
while(UTX0IF == 0);
UTX0IF = 0;
}
U0DBUF = 0x0A; //换行
while(UTX0IF == 0);
UTX0IF = 0;
}
/****************************
//延时函数
*****************************/
void Delayms(uint xms)
{
uint i,j;
for(i=xms;i>0;i--)
for(j=587;j>0;j--);
}
/****************************************************************
主函数
****************************************************************/
void main(void)
{
char i;
char TempValue[7];
float AvgTemp;
InitUART0(); //初始化串口
initTempSensor(); //初始化 ADC
while(1)
{
AvgTemp = 0;
for(i = 0 ; i < 64 ; i++)
{
AvgTemp += getTemperature();
AvgTemp=AvgTemp/2; //每次累加后除 2
}
/****温度转换成ascii码发送****/
TempValue[0] = (unsigned char)(AvgTemp)/10 + 48; //十位
TempValue[1] = (unsigned char)(AvgTemp)%10 + 48; //个位
TempValue[2] = '.'; //小数点
TempValue[3] = (unsigned char)(AvgTemp*10)%10+48; //十分位
TempValue[4] = (unsigned char)(AvgTemp*100)%10+48; //百分位
TempValue[5] = '\r'; //字符串结束符
TempValue[6] = '\n';
UartTX_Send_String( TempValue,7);
Delayms(2000); //使用32M晶振,故这里2000约等于1S
}
}
图4-9 实验效果图
扩展知识——AD模数转换
以8位的寄存器为例, A/D转换器片内有D/A转换和电压比较器,首先向片内D/A转换器输入1000 0000,若电压比较器:VIN > VN (VN为片内D/A转换的输出,VIN为A/D转换器的输入电压),N位寄存器的首位置1 (若VIN < VN,则寄存器首位写0);再向D/A转换输入1100 0000(首位写0时,输入0111 1111),若VIN > VN则寄存器第二位置1(若VIN < VN,则写0);再向D/A转换输入1110 0000(或0011 1111),若VIN > VN则寄存器第三位置1(若小于,则写0);依次下去直到寄存器第8位赋值结束,控制逻辑监测到比较放大器进行8次后,EOC输入信号,让A/D转换器将结果通过锁存缓存器输出至D0~D9。
4.8睡眠唤醒实验
1.学习CC2530的低功耗控制方式;
2.CC2530的中断和定时器唤醒。
对于远距离的无限传输设备,功耗是一个较为关键的技术指标,而基于单片机CC2530单片机的ZigBee系统在低功耗方面有着较为明显的优势,节点模块闲时可以进入睡眠模式,在需要传输数据时候进行唤醒,能进一步节省电量。本节将讲述CC2530 在睡眠模式下的 2 种唤醒方法:外部中断唤醒和定时器唤醒。
ZigBee节点的唤醒有两种方式分别为:定时器唤醒和中断唤醒睡眠,定时器用于设置系统进入和退出低功耗睡眠模式之间的周期,还用于当系统进入低功耗模式后,维持 MAC 定时器(T2)的定时。其特性如下:24位定时计数器运行在 32.768KHZ 的工作频率。24 位的比较器具有中断和 DMA 触发功能在 PM2 低功耗模式下运行。
1.中断唤醒
CC2530 需要配置的主要寄存器如下:PCON ,SLEEPCMD。功能如表4-7所示:
表4-7 CC2530中断方式唤醒休眠相关控制寄存器
系统电源模式控制寄存器PCON(0x87) |
Bit0 |
1 |
将强制系统进入 SLEEPCMD 所指定的电源模式,所有中断信号都可以 清除此置位。 |
0 |
|
||
系统电源模式设定SLEEPCMD(0xBE)
|
Bit1:Bit0 |
00 |
全功能模式 |
01 |
PM1 |
||
10 |
PM2 |
||
11 |
PM3 |
2.定时器唤醒
定时器唤醒除了要对寄存器PCON、SLEEPCMD进行设置,还需要对定时器计数寄存器ST0、ST1、ST2进行设置,其具体功能描述如表4-8:
表4-8 CC2530定时器方式唤醒休眠相关控制寄存器
ST0(0x95) |
睡眠计数器数据 Bit7 :Bit0 |
ST1(0x96) |
睡眠计数器数据 Bit15:Bit8 |
ST2(0x97) |
睡眠计数器数据 Bit23:Bit16 |
根据表中相关寄存器的功能说明,具体进行如下配置:
SLEEPCMD |= i; // 设置系统睡眠模式,i=0,1,2,3
PCON = 0x01; // 进入睡眠模式 ,通过中断打断
PCON = 0x00; // 系统唤醒 ,通过中断打断
UINT32 sleepTimer = 0;
sleepTimer |= ST0;
sleepTimer |= (UINT32)ST1 << 8;
sleepTimer |= (UINT32)ST2 << 16;
sleepTimer += ((UINT32)sec * (UINT32)32768) //低速晶振;
ST2 = (UINT8)(sleepTimer >> 16);
ST1 = (UINT8)(sleepTimer >> 8);
ST0 = (UINT8) sleepTimer;
具体程序如下所示:
中断唤醒程序
#include <ioCC2530.h>
#define uint unsigned int
#define uchar unsigned char
//定义控制LED灯和按键的端口
#define LED2 P1_1 //定义LED2为P11口控制
#define KEY1 P0_4
//函数声明
void Delayms(uint); //延时函数
void InitLed(void);
void SysPowerMode(uchar sel); //系统工作模式
/****************************
延时函数
*****************************/
void Delayms(uint xms) //i=xms 即延时i毫秒
{
uint i,j;
for(i=xms;i>0;i--)
for(j=587;j>0;j--);
}
/****************************
//初始化程序
*****************************/
void InitLed(void)
{
P1DIR |= 0x02; //P1_1定义为输出
LED2 = 1; //LED2灯熄灭
P0INP &= ~0X10; //设置P0口输入电路模式为上拉/ 下拉
P0IEN |= 0X10; //P01设置为中断方式
PICTL |= 0X10; // 下降沿触发
}
/****************************************************************
系统工作模式选择函数
* para1 0 1 2 3
* mode PM0 PM1 PM2 PM3
****************************************************************/
void SysPowerMode(uchar mode)
{
uchar i,j;
i = mode;
if(mode<4)
{
SLEEPCMD |= i; // 设置系统睡眠模式
for(j=0;j<4;j++);
PCON = 0x01; // 进入睡眠模式 ,通过中断打断
}
else
{
PCON = 0x00; // 系统唤醒 ,通过中断打断
}
}
/***************************
主函数
***************************/
void main(void)
{
uchar count = 0;
InitLed(); //调用初始化函数
IEN1 |= 0X20; // 开P0口总中断
P0IFG |= 0x00; //清中断标志
EA = 1;
while(1)
{
LED2=~LED2;
if(++count>=10)
{
count=0;
SysPowerMode(3); //5次闪烁后进入睡眠状态PM3,等待按键S3中断唤醒
}
Delayms(500);
}
}
/*****************************************
中断处理函数-系统唤醒
*****************************************/
#pragma vector = P0INT_VECTOR
__interrupt void P0_ISR(void)
{
if(P0IFG>0)
{
P0IFG = 0; //清标志位
}
P0IF = 0;
SysPowerMode(4); //正常工作模式
}
定时器唤醒程序
#include <ioCC2530.h>
#define uint unsigned int
#define uchar unsigned char
#define UINT8 unsigned char
#define UINT32 long unsigned int
//定义控制 LED 灯和按键的端口
#define LED2 P1_1 //定义 LED2 为 P11口控制
#define KEY1 P0_4
//函数声明
void Delayms(uint xms); //延时函数
void InitLed(void); //初始化 P1 口
void SysPowerMode(uchar sel); //系统工作模式
/****************************
延时函数
*****************************/
void Delayms(uint xms) //i=xms 即延时 i 毫秒
{
uint i,j;
for(i=xms;i>0;i--)
for(j=587;j>0;j--);
}/****************************
//初始化程序
*****************************/
void InitLed(void)
{
P1DIR |= 0x02; //P1_1 定义为输出
LED2 = 1; //LED2 灯熄灭
P0INP &= ~0X10; //设置 P0 口输入电路模式为上拉/ 下拉
P0IEN |= 0X10; //P01 设置为中断方式
PICTL |= 0X10; // 下降沿触发
}
/***************************************************************
系统工作模式选择函数
* para1 0 1 2 3
* mode PM0 PM1 PM2 PM3
***************************************************************/
void SysPowerMode(uchar mode)
{
uchar I,j;
I = mode;
if(mode<4)
{
SLEEPCMD |= I; // 设置系统睡眠模式
for(j=0;j<4;j++);
PCON = 0x01; // 进入睡眠模式 ,通过中断打断
}
else
{
PCON = 0x00; // 系统唤醒 ,通过中断打断
}
}
/*****************************************
//初始化 Sleep Timer (设定后经过指定时间自行唤醒)
*****************************************/
void Init_SLEEP_TIMER(void)
{
ST2 = 0X00;
ST1 = 0X0F;
ST0 = 0X0F;
EA = 1; //开中断
STIE = 1; //SleepTimerinterrupt enable
STIF = 0; //SleepTimerinterrupt flag 还没处理的
}
/***************************************************************
设置睡眠时间
***************************************************************/
void Set_ST_Period(uint sec)
{
UINT32 sleepTimer = 0;
sleepTimer |= ST0;
sleepTimer |= (UINT32)ST1 << 8;
sleepTimer |= (UINT32)ST2 << 16;
sleepTimer += ((UINT32)sec * (UINT32)32768);//低频晶振 PM2 模式
ST2 = (UINT8)(sleepTimer >> 16);
ST1 = (UINT8)(sleepTimer >> 8);
ST0 = (UINT8) sleepTimer;
}/***************************
//主函数
***************************/
void main(void)
{
uchar i;
InitLed(); //调用初始化函数
Init_SLEEP_TIMER(); //初始化 SLEEPTIMER
while(1)
{
for(i=0;i<6;i++) //闪烁 3 下
{
LED2=~LED2;
Delayms(200);
}
Set_ST_Period(3); //重新进入睡眠模式
SysPowerMode(2); //进入 PM2 低频晶振模式
}
}
//睡眠中断唤醒
#pragma vector = ST_VECTOR
__interrupt void ST_ISR(void)
{
STIF = 0; //清标志位
SysPowerMode(4); //进入正常工作模式
}
在中断唤醒模式下,通过按下按键 S3(KEY1)产生外部中断进行唤醒,D4(LED2)闪烁5次后进入睡眠状态,重新进入工作模式。
在定时器唤醒模式下,通过设置定时器在特定时间内进行唤醒,重新进入工作模式,每次唤醒D4(LED2)闪烁3下。
扩展知识——CC2530的电源管理
系统电源管理(工作方式如下):
1. 全功能模式,高频晶振(16M 或者 32M )和低频晶振(32.768K RCOSC/XOSC )
全部工作,数字处理模块正常工作。
2. PM1:高频晶振(16M 或者 32M )关闭,低频晶振(32.768K RCOSC/XOSC )
工作,数字核心模块正常工作。
3.PM2:低频晶振(32.768K RCOSC/XOSC )工作,数字核心模块关闭,系统通过 RESET,外部中断或者睡眠计数器溢出唤醒。
4. PM3:晶振全部关闭,数字处理核心模块关闭,系统只能通过 RESET 或外部中断唤醒。此模式下功耗最低。
4.9看门狗实验
1.学习CC2530看门狗的工作方式;
2.学习看门狗功能在系统中的运行机制;
有过项目开发经验的读者对于看门狗应该并不陌生,而且看门狗对于一个系统的可靠的运行有着至关重要的作用,它会在软件程序跑飞的情况下,对系统进行复位,以保证程序重新开始正常运行,但是前提是定时喂狗。
CC2530 的看门狗控制较为简单,只涉及到一个寄存器WDCTL,其功能描述如下表4-9所示:
表4-9看门狗控制相关寄存器
系统电源模式控制寄存器PCON(0x87) |
清除计数器值Bit[7:4] |
|
在看门狗模式下,如果此四位在一个看门狗周期内先后写入0xA,0x5, 则清除 WDT 的值。简称喂狗。 |
WDT 工作模式选择寄存器Bit[3:2] |
00 |
IDLE |
|
01 |
IDLE(未使用) |
||
10 |
看门狗模式 |
||
11 |
定时器模式 |
||
看门狗周期选择寄存器Bit[1:0] |
00 |
1 秒 |
|
01 |
0.25 秒 |
||
10 |
15.625 毫秒 |
||
11 |
1.9 毫秒 |
根据表中相关寄存器的功能说明,具体进行如下配置:
Init_Watchdog:
WDCTL = 0x00; //这是必须的,打开 IDLE 才能设置看门狗
WDCTL |= 0x08; //时间间隔一秒,看门狗模式
FeedDog:
WDCTL = 0xa0; //按寄存器描述来喂狗
WDCTL = 0x50;
具体程序如下所示:
#include <ioCC2530.h>
#define uint unsigned int
#define uchar unsigned char
//定义控制LED灯的端口
#define LED1 P1_0
#define LED2 P1_1
//函数声明
void Delayms(uint xms);//延时函数
void InitLed(void); //初始化P1口
/****************************
//延时函数
*****************************/
void Delayms(uint xms) //i=xms 即延时i毫秒
{
uint i,j;
for(i=xms;i>0;i--)
for(j=587;j>0;j--);
}
/****************************
//初始化程序
*****************************/
void InitLed(void)
{
P1DIR |= 0x03; //P1_0、P1_1定义为输出
LED1 = 1; //LED1灯熄灭
LED2 = 1; //LED2灯熄灭
}
void Init_Watchdog(void)
{
WDCTL = 0x00; //这是必须的,打开IDLE才能设置看门狗
WDCTL |= 0x08;
//时间间隔一秒,看门狗模式
}
void FeetDog(void)
{
WDCTL = 0xa0;
WDCTL = 0x50;
}
/***************************
//主函数
***************************/
void main(void)
{
InitLed(); //调用初始化函数
Init_Watchdog();
LED1=1;
while(1)
{
LED2=~LED2; //仅指示作用。
Delayms(300);
LED1=0;
//通过注释测试,观察LED1,系统在不停复位。
FeetDog();//防止程序跑飞
}
}
在定时喂狗的情况下,软件程序正常运行,D3(LED1)上电后长亮,D4(LED2)按照延时闪烁。
将喂狗程序注释掉,软件程序会按照预先设定的喂狗频率进行复位,从而导致D3(LED1)也按照喂狗频率闪烁,证明系统在不停的复位。
4.10 LCD Nokia 5110液晶实验
学习使用LCD Nokia 5110液晶,并显示自定义的内容。
首先根据开发板硬件原理图确定LCD Nokia 5110与CC2530芯片的连接引脚,如图4-10所示。
图4-10 LCD Nokia 5110接口图
Nokia5110液晶是诺基亚手机的二手拆机屏,底板四角有定位孔,同时提供一排接线端口,排列如下:
1.RST ——复位
2.CE —— 片选
3.DC —— 数据/指令选择
4.DIN —— 串行数据线
5.CLK —— 串行时钟线
6.VCC —— 电源输入(3.3V和5V均可,经过实验验证,没有问题)
7.BL —— 背光控制端
8.GND —— 地线
程序中引脚定义
#define SCLK P2_4 //CLK--串行时钟线
#define SDIN P2_3 // DIN--串行数据线
#define LCD_DC P1_3 // DC--数据/指令选择
#define LCD_CE P1_2 // CE--片选
#define LCD_RST P2_0 // RST--复位
主函数部分程序如下:
#include <ioCC2530.h>
#include "nokia_5110.h"
#include "bmp_pixel.h"
void main(void)
{
LCD_init(); //初始化液晶
LCD_clear(); //LCD清屏
LCD_write_chinese_string(0,0,12,7,0,0);//液晶显示“风云物联网科技”
LCD_write_english_string(20,2,"FYWLWKJ");//液晶显示“FYWLWKJ”
LCD_write_english_string(3,3,"ZigBee CC2530"); //液晶显示“ZigBee CC2530”
LCD_write_chinese_string(18,4,12,4,7,0);//液晶显示“风网天下”
while(1)
{
}
}
图4-11实验效果图
4.11温度传感器DS18B20实验
学习使用温度传感器DS18B20,并在串口显示温度数据。
开发板硬件设计有温湿度传感器DHT11,原理图如图4-12-1所示,可以用此接口代替DS18B20,DS18B20实物图如图4-12-2所示,电源对应连接至DHT11接口,DQ连接至P06接口。
图4-12-1 DHT11接口图 图4-12-2 DS18B20引脚
主函数部分程序如下:
#include"iocc2530.h"
#include"uart.h"
#include"ds18b20.h"
#include"delay.h"
void Initial() //系统初始化
{
CLKCONCMD = 0x80; //选择32M振荡器
while(CLKCONSTA&0x40); //等待晶振稳定
UartInitial(); //串口初始化
P0SEL &= 0xbf; //DS18B20的io口初始化
}
void main()
{
char data[5]="Temp="; //串口提示符
Initial();
while(1)
{
Temp_test(); //温度检测
/*******温度信息打印 ***********/
UartTX_Send_String(data,5);
UartSend(temp/10+48);
UartSend(temp%10+48);
UartSend('\n');
Delay_ms(1000); //延时函数使用定时器方式
}
}
图4-13 实验效果图
4.12温湿度传感器DHT11实验
学习使用温湿度传感器DHT11,并在串口显示温湿度数据。
首先根据开发板硬件原理图确定温湿度传感器DHT11与CC2530芯片的连接引脚,如图4-14所示。
图4-14 DHT11接口图
DHT11模块参数如下:
1.可以检测周围环境的湿度和温度
2.传感器采用 DHT11
3.湿度测量范围:20%-95%(0 度-50 度范围)湿度测量误差:+-5%
4.温度测量范围:0 度-50 度 温度测量误差:+-2 度
4.工作电压 3.3V-5V
5.输出形式 数字输出
6.设有固定螺栓孔,方便安装
7.小板 PCB 尺寸:3.2cm * 1.4cm
8.电源指示灯(红色)
DHT11 模块接口说明
1 VCC 外接 3.3V-5V
2 DATA 小板开关数字量输出接口接单片机IO口
3 GND 外接 GND
主函数部分程序如下:
#include <ioCC2530.h>
#include <string.h>
#include "UART.H"
#include "DHT11.H"
/***************************
主函数
***************************/
void main(void)
{
Delay_ms(1000);//让设备稳定
InitUart(); //串口初始化
while(1)
{
DHT11(); //获取温湿度
P0DIR |= 0x40; //IO口需要重新配置
/******温湿度的ASC码转换*******/
temp[0]=wendu_shi+0x30;
temp[1]=wendu_ge+0x30;
humidity[0]=shidu_shi+0x30;
humidity[1]=shidu_ge+0x30;
/*******信息通过串口打印********/
Uart_Send_String(temp1,5);
Uart_Send_String(temp,2);
Uart_Send_String("\n",1);
Uart_Send_String(humidity1,9);
Uart_Send_String(humidity,2);
Uart_Send_String("\n",1);
Delay_ms(2000); //延时,使周期性2S读取1次
}
}
图4-15 实验效果图
4.13烟雾传感器实验
学习使用烟雾传感器。
首先根据开发板硬件原理图确定烟雾传感器MQ-2与CC2530芯片的连接引脚,如图4-16所示。
图4-16 烟雾传感器接口图
简要说明:
一、 尺寸:mm Xmm Xmm 长X宽X高
二、 主要芯片:气体传感器
三、 工作电压:直流5伏
四、 特点:
1、具有信号输出指示。
2、双路信号输出(模拟量输出及TTL电平输出)
3、TTL输出有效信号为低电平。(当输出低电平时信号灯亮,可直接接单片机)
4、模拟量输出0~5V电压,浓度越高电压越高。
5、对液化气,天然气,城市煤气有较好的灵敏度。
6、具有长期的使用寿命和可靠的稳定性
7、快速的响应恢复特性
五、应用:
适用于家庭或工厂的气体泄漏监测装置,适宜于液化气、丁烷、丙烷、甲烷、酒精、氢气、烟雾等监测装置。
全部程序如下:
#include <ioCC2530.h>
//烟雾传感器IO定义
#define AIR P0_7
//LED灯IO定义
#define LED1 P1_0
#define LED2 P1_1
void main(void)
{
/******烟雾传感器电路初始化******/
P0SEL &= ~0X80; //设置P07为普通IO口
P0DIR &= ~0X80; // 在P07口,设置为输入模式
P0INP &= ~0x80; //打开P07上拉电阻
/******LED P1_0,P1_1方向初始化******/
P1DIR |= 0x03; //P1_0,P1_1设置为输出模式
LED1 = 1; //熄灭LED1
LED2 = 1; //熄灭LED2
while(1)
{
if(AIR==1)
{
LED1 = 1; //无烟雾,熄灭LED1
LED2 = 1; //无烟雾,熄灭LED2
}
else
{
LED1 = 0; //有烟雾,点亮LED1
LED2 = 0; //有烟雾,点亮LED2
}
}
}
无烟雾的情况下,D3(LED1)和D4(LED2)会处于熄灭状态;有烟雾的情况下,D3和D4会处于点亮状态。
4.14蓝牙控制实验
学习使用蓝牙模块,并通过风云串口助手控制。
首先根据开发板硬件原理图确定蓝牙模块与CC2530芯片的连接引脚,如图4-17所示。
图4-17 蓝牙模块接口图
此节可参考4.6节串口数据收发实验以及查阅风云蓝牙模块说明书进行学习。
蓝牙模块采用风云蓝牙模块,引脚定义:
蓝牙模块 TXD:蓝牙模块的发送端,正常通信必须接另一个设备的 RXD。
蓝牙模块 RXD:蓝牙模块的接收端,正常通信必须接另一个设备的 TXD。
蓝牙模块 STATE:蓝牙模块的状态引脚,与蓝牙 led 表示的状态一致(此引脚不常用) 。
蓝牙模块 EN:蓝牙模块的使能端(此引脚不常用) 。
蓝牙模块 5V:蓝牙模块的电源引脚。
蓝牙模块 GND:蓝牙模块的接地引脚
注意:通常仅使用 TXD、RXD 、5V 、 GND 即可通信
主函数部分程序如下:
#include <iocc2530.h>
//LED灯IO定义
#define LED1 P1_0
#define LED2 P1_1
unsigned char temp;
void initUART0(void);
/****************************************************************
串口(UART0)初始化函数:
****************************************************************/
void initUART0(void)
{
CLKCONCMD &= ~0x40; //设置系统时钟源为32MHZ晶振
while(CLKCONSTA & 0x40); //等待晶振稳定
CLKCONCMD &= ~0x47; //设置系统主时钟频率为32MHZ
PERCFG = 0x00; //位置1 P0口
P0SEL = 0x3c; //P0用作串口
P2DIR &= ~0XC0; //P0优先作为UART0
U0CSR |= 0x80; //串口设置为UART方式
U0GCR |= 8;
U0BAUD |= 59; //波特率设为9600
UTX0IF = 1; //UART0 TX中断标志初始置位1
U0CSR |= 0X40; //允许接收
IEN0 |= 0x84; //开总中断,接收中断
}
/****************************************************************
主函数
****************************************************************/
void main(void)
{
/******LED P1_0,P1_1方向初始化******/
P1DIR |= 0x03; //P1_0,P1_1设置为输出模式
LED1 = 1; //熄灭LED1
LED2 = 1; //熄灭LED2
initUART0();
while(1)
{
if(temp == 0x01)
{
LED1 = 0; //点亮LED1
}
if(temp == 0x02)
{
LED2 = 0; //点亮LED2
}
if(temp == 0x11)
{
LED1 = 1; //熄灭LED1
}
if(temp == 0x22)
{
LED2 = 1; //熄灭LED2
}
}
}
/****************************************************************
一旦有数据从串口传至CC2530,则进入中断,将接收到的数据赋值给变量temp.
****************************************************************/
#pragma vector = URX0_VECTOR
__interrupt void UART0_ISR(void)
{
URX0IF = 0; //清中断标志
temp = U0DBUF;
}
将风云蓝牙模块接插到开发板相应位置,注意接插方向,请按照正确说明接插进去,然后下载程序,安装给手机安装风云蓝牙串口助手,如图4-18,手机连接蓝牙模块,发送指令如下:
发送0x01指令,开发板D3(LED1)点亮,发送0x11指令,开发板D3(LED1)熄灭;
发送0x02指令,开发板D4(LED2)点亮,发送0x22指令,开发板D4(LED2)熄灭。
图4-18 风云蓝牙串口助手