CC2530的串口通信原理与应用
Posted 364.99°
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CC2530的串口通信原理与应用相关的知识,希望对你有一定的参考价值。
目录
1.CC2530的串口资源
CC2530有两个串行通信接口:异步UART模式: USART0和同步SPI模式: USART1
对于每个USART外设,有5个相关的寄存器(x时USART的编号,0或1)
UxCSR: USARTx 控制状态寄存器
UxUCR: USARTx UART控制寄存器
UxGCR: USARTx 通用控制寄存器
UxBUF: USARTx UART接受/发送数据缓冲区
UxBAUD: USARTx 波特率控制寄存器
1.1.CC2530的UART串口引脚的映射关系
两个USART接口具有相同的功能,通过PERCFG寄存器可以设置两个USART接口对应外部I/O引脚的映射关系
1.2.PERCFG外设控制寄存器
2.波特率的计算与设置
CC2530的波特率有BAUD_E和BAUD_M共同决定:
F为系统时钟频率,16MHz或32MHz
TI公司提供的数据手册中,给出了32MHz系统时钟频率下各种常用波特率的参数值
由计算公式可已计算出16MHz系统时钟频率下对应的参数值
- 16MHz下9600波特率的UxBAUD.BAUD_M:U0BAUD = 59
- 16MHz下9600波特率的UxGCR.BAUD_E:U0GCR = 9
3.串口0的UART初始化设置
void Init_Uart0(){
//端口配置
PERCFG &= ~0x01; //将串口0的引脚映射到位置1,即P0_2和P0_3
P0SEL = 0x0C; //将P0_2和P0_3端口设置为外设功能
/*======使用CC2530的内部16MHz晶振产生9600的波特率====*/
//波特率配置
U0BAUD = 59;
U0GCR = 9;
//流控配置
U0UCR |= 0x80; //禁止流控,8位数据,清楚缓冲器
//串口模式配置
U0CSR |= 0xC0; //选择UART模式,使能接收器
//中断配置
UTX0IF = 0; //清除TX发送中断标志
URX0IF = 0; //清除RX接收中断标志
URX0IE = 1; //使能URAT0的接收中断
EA = 1; //使能总中断
}
4.案例
4.1.串口数据发送
要求:
- USART0选择UART模式,波特率9600,I/O引脚映射到备用位置1
- 利用看门狗定时器的定时功能实现1秒定时
- 在看门狗中断服务模式中,由串口向上机位发送“Hello World!”,回车换行
D5等作为数据发送指示灯,在字符串发送前点亮,字符串发送结束后熄灭
代码:
#include "ioCC2530.h"
#define D5 P1_3
/*=============系统时钟切换16MHz→32MHz(32MHz更为准确)====================*/
void Set_Clock_32M(){
CLKCONCMD &= ~0x40; //选择系统时钟源为32MHz晶振
while(CLKCONCMD & 0x40); //等待晶振稳定
CLKCONCMD &= ~0x47; //设置系统主时钟频率为32MHz
}
/*========================端口初始化函数====================================*/
void Init_Port(){
//初始化LED灯的I/O口
P1SEL &= ~0x1B; //P1_0、P1_1、P1_3和P1_4作为通用I/O口
P1DIR |= 0x1B; //P1_0、P1_1、P1_3和P1_4端口输出
P1 &= ~0x1B; //关灯D3~D6
}
/*==============================串口初始化函数==============================*/
void Init_Uart0(){
//设置串口引脚功能,将P0_2、P0_3设置成外设功能
PERCFG &= ~0x01;
P0SEL |= 0x0C;
//设置串口波特率:32MHz——9600 中文手册P144
U0BAUD = 59;
U0GCR = 8;
//设置UART控制U0UCR
U0UCR |= 0x80;
//设置控制与状态寄存器
U0CSR |= 0xC0;
}
/*===============看门狗初始化函数,设置为定时器模式=========================*/
void Init_WDT(){
WDCTL = 0x0C;
INE2 |= 0x20;
EA = 1;
}
/*==================看门狗定时1秒中断服务函数===============================*/
#pragma vector = WDT_VECTOR
__interrupt void Service_WDT(){
WDTIF = 0;
DS = 1;
UR0_SendString("Hello World!\\r\\n");
D5 = 0;
}
/*=====================串口字节发送函数=====================================*/
void UR0_SendByte(unsigned char dat){
U0DBUF = dat;
while(UTX0IF == 0);
UTX0IF = 0;
}
/*=============================串口字符发送函数=============================*/
void UR0_SendString(unsigned char *str){
while(*str != '\\0'){
UR0_SendByte(*str++);
}
}
/*=====================================main函数=============================*/
void main(){
Set_Clock_32M();
Init_Port();
Init_Uart0();
Init_WDT();
while(1){}
}
4.2.串口数据收发
要求:
- USART0选择UART模式,波特率9600,I/O引脚映射到备用位置1
- 串口接受到上位机的一个数据后,在原值上加1,发回上位机
- D3灯作为数据接受指示灯,在收到一个数据后,D3灯亮
- D5灯作为数据发送指示灯,在数据发送之前亮,在数据发送完成后,D3灯与D5灯同时熄灭
代码:
#include "ioCC2530.h"
#define D3 P1_0
#define D5 P1_3
/*=============系统时钟切换16MHz→32MHz(32MHz更为准确)====================*/
void Set_Clock_32M(){
CLKCONCMD &= ~0x40; //中文手册P60
while(CLKCONCMD & 0x40); //中文手册P61
CLKCONCMD &= ~0x47; //中文手册P60
}
/*========================端口初始化函数====================================*/
void Init_Port(){
P1SEL &= ~0x1B; //中文手册77
P1DIR |= 0x1B;
P1 &= ~0x1B; //关灯D3~D6
}
/*==============================串口初始化函数==============================*/
void Init_Uart0(){
//设置串口引脚功能,将P0_2、P0_3设置成外设功能,中文手册P72、P77
PERCFG &= ~0x01;
P0SEL |= 0x0C;
//设置串口波特率:32MHz——9600 中文手册P144
U0BAUD = 59;
U0GCR = 8;
//设置UART控制U0UCR,中文手册P146
U0UCR |= 0x80;
//设置控制与状态寄存器U0CSR,中文手册P145
U0CSR |= 0xC0; //UART模式
//清除中断标志
UTX0IF = 0;
URX0IF = 0;
}
/*================================串口字节发送函数==========================*/
void UR0_SendByte(unsigned char dat){
U0DBUF = dat;
while(UTX0IF == 0);
UTX0IF = 0;
}
/*=========================串口数据接受完成的中断服务函数===================*/
#pragma vector = URX0_VECTOR
__interrupt void Service_UR0Recv(){
D3 = 1;
unsigned char tmp;
tmp = U0DBUF;
tmp++;
D5 = 1;
UR0_SendByte(temp);
D3 = 0;
D5 = 0;
}
/*=====================================main函数=============================*/
void main(){
Set_Clock_32M();
Init_Port();
Init_Uart0();
while(1){}
}
4.3.串口命令控制LED灯开关
要求:
- USART0选择UART模式,波特率9600,I/O引脚映射到备用位置1
- 命令字"0xA1",点亮D4,操作完成后,返回"D4 is open!"
- 命令字"0xA2",关闭D4,操作完成后,返回"D4 is closed!"
- 命令字"0xA1",点亮D6,操作完成后,返回"D6 is open!"
- 命令字"0xA1",关闭D6,操作完成后,返回"D6 is closed!"
代码:
#include "ioCC2530.h"
#define D3 P1_0
#define D4 P1_1
#define D5 P1_3
#define D6 P1_4
unsigned char cmd = 0; //存放上机位PC发送过来的数据
/*=============系统时钟切换16MHz→32MHz(32MHz更为准确)====================*/
void Set_Clock_32M(){
CLKCONCMD &= ~0x40; //选择系统时钟源为32MHz晶振
while(CLKCONCMD & 0x40); //等待晶振稳定
CLKCONCMD &= ~0x47; //设置系统主时钟频率为32MHz
}
/*========================端口初始化函数====================================*/
void Init_Port(){
//初始化LED灯的I/O口
P1SEL &= ~0x1B; //P1_0、P1_1、P1_3和P1_4作为通用I/O口
P1DIR |= 0x1B; //P1_0、P1_1、P1_3和P1_4端口输出
P1 &= ~0x1B; //关闭所有LED灯
}
/*==============================串口初始化函数==============================*/
void Init_Uart0(){
//端口相关的配置——设置TXD和RXD引脚的外设功能
PERCFG &= ~0x01; //串口0的引脚映射到位置1,即P0_2和P0_3
P0SEL |= 0x0C; //将P0_2和P0_3端口设置成外设功能
//波特率相关配置
U0BAUD = 59; //32MHz的系统时钟产生9600BPS的波特率
U0GCR = 8; //16MHz——9,32MHz——8
//串口属性相关配置——UART控制寄存器
U0UCR |= 0x80; //禁止流控,8位数据,清除缓冲器
//串口属性相关配置——设置串口的工作模式:UART、使能接受
U0CSR |= 0xC0; //UART模式,使能接收器
//串口中断相关配置——清除中断标志
UTX0IF = 0; //清除TX发送中断标志
URX0IF = 0; //清除RX接收中断标志
//串口中断香瓜配置——使能串口中断接受
URX0IF = 1; //使能UART0的接收中断
EA = 1; //使能总中断
}
/*================================串口字节发送函数==========================*/
void UR0_Send_Byte(unsigned char dat){
U0DBUF = dat; //将要发送的1字节数据写入U0DBUF
while(UTX0IF == 0); //等待TX中断标志,即数据发送完成
UTX0IF = 0; //清除TX中断标志,准备下一次发送
}
/*=============================串口字符发送函数=============================*/
void UR0_Send_String(unsigned char *str){
while(*str != '\\0'){ //发送一个字符串
UR0_SendByte(*str++); //逐个发送字符串字节
}
}
/*=========================串口数据接受完成的中断服务函数===================*/
#pragma vector = URX0_VECTOR
__interrupt void Service_UR0Recv(){
cmd = U0DBUF; //将控制命令字节从缓冲区取出
F_UR0_Recv = 1; //标志成功接收上位机的单字节命令
}
/*=============================命令控制LED灯开关============================*/
void Control_LED(){
switch(cmd){
case 0xA1
D4 = 1;
UR0_Send_String("D4 is open!\\r\\n");
break;
case 0xA2
D4 = 0;
UR0_Send_String("D4 is closed!\\r\\n");
break;
case 0xB1
D6 = 1;
UR0_Send_String("D6 is open!\\r\\n");
break;
case 0xB2
D6 = 0;
UR0_Send_String("D6 is closed!\\r\\n");
break;
}
}
/*=====================================main函数=============================*/
void main(){
Init_Clock_32M();
Init_Port();
Init_Uart0();
while (1){
if (cmd != 0){
control_LED();
}
}
}
以上是关于CC2530的串口通信原理与应用的主要内容,如果未能解决你的问题,请参考以下文章
关于Zigbee_cc2530解决串口显示头几个乱码要怎么解决?