第5课 CC2530的串行接口原理与应用
小蜜蜂笔记网 / 广东职业技术学院 欧浩源
一、并行通信与串行通信
微控制器与外设之间的数据通信,根据连线结构和传送方式的不同,可以分为两种:并行通信和串行通信。
并行通信:指数据的各位同时发送或接收,每个数据位使用单独的一条导线。传输速度快、效率高,但需要的数据线较多,成本高。
串行通信:指数据一位接一位地顺 序发送或接收。需要的数据线少,成本低,但传输速度慢,效率低。
二、CC2530的串口通信模块
CC2530有两个串行通信接口USART0和USART1,它们能够分别运行于异步UART模式或者同步SPI模式。
两个USART接口具有相同的功能,通过PERCFG寄存器可以设置两个USART接口对应外部I/O引脚的映射关系:
位置1:RX0 --- P0_2 TX0 --- P0_3 RX1 --- P0_5 TX1 --- P0_4
位置2:RX0 --- P1_4 TX0 --- P1_5 RX1 --- P1_7 TX1 --- P1_6
对每个USART串口通信编程,本质是设置相关的5个寄存器:
<1> UxCSR: USARTx的控制和状态寄存器。
<2> UxUCR: USARTx的UART控制寄存器。
<3> UxGCR: USARTx的通用控制寄存器。
<4> UxDBUF:USARTx的接收/发送数据缓冲寄存器。
<4> UxBAUD:USARTx的波特率控制寄存器。
三、UART口与计算机的COM口连接
先认识两种电平:TTL电平和RS232电平。
TTL电平: 逻辑0----小于0.8V 逻辑1----大于2.4V。
RS232电平: 逻辑0----5~15V 逻辑1---- -5~-15V。
计算机的串行通信接口是RS-232的标准接口,而CC2530单片机的UART接口则是TTL电平,两者的电气规范不一致,所以要完成两者之间的数据通信,就需要借助接口芯片在两者之间进行电平转换,常用的有MAX232芯片。
注意:DB9接口中,公头和母头的排列顺序是不同的。
四、实训项目:上位机通过串口控制LED灯的开关
【1】计算波特率
CC2530的波特率由BAUD_E和BAUD_M共同决定:
F为微控制器的系统时钟频率:16MHz或32MHz。
在TI公司提供的数据手册中,给出了32MHz系统时钟下各常用波特率的参数值,由计算公式亦不难得出16MHz系统时钟下对应的参数值。
【2】串口0的初始化函数
选择外设的引脚映射位置,并将对应的引脚设置为外设功能 ,然后对波特率、控制寄存器和中断的相关控制位进行设置。
【3】数据接收中断服务函数
USART0发送完成的中断向量是:0x3B ,也可以使用宏定义:URX0_VEXTOR 。在该中断服务函数中,要手工清除接收中断标志位URX0IF。
当数据接收完毕后,通过将一个自定义的变量Flag设置为1,告诉主函数,已经成 功接收到所需要的数据,主函数可以对其进行解析和执行指令。
【4】发送字节及发送字符串函数
当USART 的发送/接收数据缓冲寄存器UxDBUF被写入数据时,该字节就会发送到TXD引脚,开始数据的传输。由于UxDBUF是双缓冲的,所以在发送开始后会立即触发TX完成中断标志UTX0IF,并且数据缓冲器被卸载,也就是说,当字节正在发送时,新 的字节能够装入数据缓冲器UxDBUF。
在单字节的发送函数中,把要发送的数据写入UxDBUF后,查询TX完成标志UTX0IF,当该标志被置1时,表示数据发送完成,然后清除该标志。
【5】项目源代码
#include "ioCC2530.h" #define LED5 P1_3 #define LED6 P1_4 unsigned char dataRecv; unsigned char Flag = 0; /*===================UR0初始化函数====================*/ void Init_Uart0() { PERCFG = 0x00; //串口0的引脚映射到位置1,即P0_2和P0_3 P0SEL = 0x0C; //将P0_2和P0_3端口设置成外设功能 U0BAUD = 59; //16MHz的系统时钟产生9600BPS的波特率 U0GCR = 9; U0UCR |= 0x80; //禁止流控,8位数据,清除缓冲器 U0CSR |= 0xC0; //选择UART模式,使能接收器 UTX0IF = 0; //清除TX发送中断标志 URX0IF = 0; //清除RX接收中断标志 URX0IE = 1; //使能URAT0的接收中断 EA = 1; //使能总中断 } /*================UR0接收中断服务函数================*/ #pragma vector = URX0_VECTOR __interrupt void UR0_RecvInt() { URX0IF = 0; //清除RX接收中断标志 dataRecv = U0DBUF; //将数据从接收缓冲区读出 Flag = 1; //设置接收指令标志 } /*=================UR0发送单字节函数=================*/ void UR0SendByte(unsigned char dat) { U0DBUF = dat; //将要发送的1字节数据写入U0DBUF while(!UTX0IF); //等待TX中断标志,即数据发送完成 UTX0IF = 0; //清除TX中断标志,准备下一次发送 } /*=================UR0发送字符串函数===============*/ void UR0SendString(unsigned char *str) { while(*str != \'\0\') //发送一个字符串 { UR0SendByte(*str++); //逐个发送字符串中的字节 } } /*================执行上位机的指令=================*/ void ExecuteTheOrder() { Flag = 0 ; //清除接收指令标志 switch(dataRecv) { case 0xa1: LED5 = 1; UR0SendString("The LED5 is Open!\r\n"); break; case 0xa2: LED5 = 0; UR0SendString("The LED5 is Closed!\r\n"); break; case 0xb1: LED6 = 1; UR0SendString("The LED6 is Open!\r\n"); break; case 0xb2: LED6 = 0; UR0SendString("The LED6 is Closed!\r\n"); break; } } /*=================端口初始化函数====================*/ void Init_Port() { P1SEL &= ~0x18; //将P1_3和P1_4设置为通用I/O端口功能 P1DIR |= 0x18; //将P1_3和P1_4的端口设置为输出 LED5 = 0; //关闭LED5灯 LED6 = 0; //关闭LED6灯 } /*===================主函数=========================*/ void main() { Init_Port(); //初始化端口 Init_Uart0(); //初始化串口0 //先发送一个字符串,测试串口0数据传输是否正确 UR0SendString("*广东职业技术学院--欧浩源*\r\n"); while(1) { if(Flag == 1) //查询是否收到上位机指令 { ExecuteTheOrder(); //解析并执行指令 } } }