本次实验,主要与CC2530的串口相关。
串口电路图如下所示
首先,先介绍一下CC2530的外设I/O引脚映射,如下图所示,每个外设单元对应两组可以选择的I/O引脚。而外设I/O位置的选择使用由寄存器PERCFG来控制,其中bit1和bit0决定UART1和UART0的位置,0表示外设位置1,1表示外设位置2.
PERCFG |= 0x00;//设置UART0为外设位置1
P0SEL |= 0x0c;//设置P0_2和P0_3作为串口
由映射表可知,I/O映射可能存在冲突,可以通过设置优先级来解决冲突,与优先级设置相关的寄存器是P2SEL和P2DIR.
P2SEL |= 0x40; //端口1UART0优先
P2DIR &= ~0xc0;//端口0UART0为第1优先级
接下来介绍与UART0相关的寄存器
- USART0控制与状态寄存器。
U0CSR |= 0x80;//将USART模式选择为UART模式
U0CSR |= 0x40;//使能UART接收器
- USART0生成控制寄存器和USART0波特率控制寄存器两者共同决定串口的波特率。
//假设系统时钟为32MHz,设置串口波特率为115200
U0GCR |= 11;
U0BAUD |= 216;
- 时钟控制命令寄存器。
CLKCONCMD &= ~0x40; //设置系统时钟源为32MHz晶振
CLKCONCMD &= ~0x47; //设置系统时钟为32MHz
- 时钟状态控制寄存器。
while(CLKCONCMD & 0x40);//等待晶振稳定为32MHz
USART0接收/发送数据缓冲寄存器
中断标志寄存器5
bit2和bit1分别是USART1和USART0的中断标志位
/*CC2530通过串口发送数据到PC端,由PC端的串口助手打印显示出来*/
#include <ioCC2530.h>
#include <string.h>
typedef unsigned char uchar;
typedef unsigned int uint;
#define TX_SIZE 15
#define TX_STRING "ZIGBEE IOT "
char TX_DATA[TX_SIZE];
void delay_ms(uint ms)
{
uint i,j;
for(i=0;i<ms;i++)
for(j=0;j<555;j++);
}
void USART0Init(void)
{
PERCFG |= 0x00;//设置UART0为外设位置1
P0SEL |= 0x0c;//设置P0_2和P0_3作为串口
P2DIR &= ~0xc0;//端口0UART0为第1优先级
U0CSR |= 0x80; //选择UART模式
U0CSR |= 0x40; //使能接收器
U0GCR |= 11;
//设置波特率为115200
U0BAUD |= 216;
UTX0IF = 0; //UART0 TX中断标志位初始化为0
}
//通过串口发送一串字符
void USART0_SendString(char *data,uint length)
{
uint i;
for(i=0;i<length;i++)
{
U0DBUF = *data++;
while(UTX0IF ==0);
UTX0IF = 0;
}
}
void main(void)
{
CLKCONCMD &= ~0x40; //选择32MHz晶振为系统时钟源
while(CLKCONSTA & 0x40); //等待晶振稳定为32MHz
CLKCONCMD &= ~0x47;//设置系统时钟为32MHz
USART0Init();
memset(TX_DATA,0,TX_SIZE); //将数组TX_DATA清0
memcpy(TX_DATA,TX_STRING,sizeof(TX_STRING)); //将TX_STRING保存到数组TX_DATA
while(1)
{
USART0_SendString(TX_DATA,sizeof(TX_STRING));
delay_ms(1000);
}
}
/*在USART0实现字符的收发,CC2530从PC端的串口助手接收数据,然后CC2530再将接受到的数据发送回PC端*/
#include <ioCC2530.h>
#include <string.h>
typedef unsigned char uchar;
typedef unsigned int uint;
#define UART0_RX 0 //接收状态
#define UART0_TX 1 //发送状态
#define RX_SIZE 100 //数据接收缓冲区大小
char RX_BUF; //单个数据接收缓冲区
char UART0_Status; //USART0的状态标志量
char RX_DATA[RX_SIZE]; //数据接收缓冲区
uchar count; //计数器
void delay_ms(uint ms)
{
uint i,j;
for(i=0;i<ms;i++)
for(j=0;j<555;j++);
}
void USART0Init(void)
{
PERCFG &= ~0x01; //设置USART0的IO位置为端口0的位置1
P0SEL |= 0x0c; //将P0_2,P0_3设置为外设引脚,即USART0的引脚
P2DIR &= ~0xc0; //将端口0的USART0设置位第1优先级
U0CSR |= 0x80;//将USART设置为UART模式
U0GCR |= 11; //将波特率设置为115200
U0BAUD |= 216;
UTX0IF = 0; //将USART0 TX中断标志位初始化为0
U0CSR |= 0x40; //使能接收器
URX0IE = 1; //使能USART0的接收中断
EA = 1; //打开总中断
}
/*发送字符串*/
void USART0_SendString(char *data,uint length)
{
uint i;
for(i=0;i<length;i++)
{
U0DBUF = *data++; //将待发送字符加载到U0DBUF寄存器
while(UTX0IF ==0); //等待该字节发送完成
UTX0IF = 0; //将中断标志重置为0
}
}
/*UART RX中断*/
#pragma vector = URX0_VECTOR
__interrupt void UART0_ISR(void)
{
URX0IF = 0; //将接收中断标志重置为0
RX_BUF = U0DBUF; //将U0DBUF寄存器接受到的数据保存至RX_BUF
}
void main(void)
{
CLKCONCMD &= ~0x40;//选择32MHz的晶振作为时钟源
while(CLKCONSTA & 0x40);//等待晶振稳定
CLKCONCMD &= ~0x47;//设置系统时钟为32MHz
USART0Init(); //初始化串口
UART0_Status = UART0_RX;
memset(RX_DATA,0,RX_SIZE);
while(1)
{
if(UART0_Status==UART0_RX) //UART处于接收状态
{
if(RX_BUF != 0)
{
if((RX_BUF != '!')&&(count < RX_SIZE)) //以'!'为结束符,一次最多接收RX_SIZE个字符
RX_DATA[count++] = RX_BUF;
else
{
if(count >= RX_SIZE)
{
count = 0;
memset(RX_DATA,0,RX_SIZE);
}else
{
UART0_Status = UART0_TX;
}
}
RX_BUF = 0;
}
}
if(UART0_Status==UART0_TX) //UART处于发送状态
{
U0CSR &= ~0x40; //禁用接收器
USART0_SendString(RX_DATA,count);//发送字符串
U0CSR |= 0x40; //使能接收器
UART0_Status = UART0_RX;
count = 0; //重置计数器
memset(RX_DATA,0,RX_SIZE);//数据接收缓冲区清0
}
}
}