小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
一、串口协议介绍
串口传输协议是嵌入式开发里比较常见的传输协议,开发阶段用的最多的方式就是将MCU的调试信息打印到PC机串口终端显示,方便调试错误。
一般传输协议分为两种: 并口和串口。
并口传输协议:指数据的各位同时发送或接收,每个数据位使用单独的一条导线。传输速度快、效率高,但需要的数据线较多,成本高。
串口传输协议:指数据一位接一位地顺 序发送或接收。需要的数据线少,成本低,但传输速度慢,效率低。
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的波特率控制寄存器。
在与PC机进行串口通信的时候是,通常需要借助USB转TTL芯片进行电压转换。 所以,在学习串口编程之前,先认识两种电平:TTL电平和RS232电平
TTL电平: 逻辑0----小于0.8V 逻辑1----大于2.4V。
RS232电平: 逻辑0----5~15V 逻辑1---- -5~-15V。
串口通信过程中,速度的指标由波特率表示。
常见的波特率设置表如下:
计算波特率的方法: CC2530的波特率由BAUD_E和BAUD_M共同决定:
二、原理图数据手册分析
三、串口配置代码示例
3.1 编写串口初始化函数,实现串口字符串发送 (CPU频率在16MHZ下,波特率的为9600)
#include <ioCC2530.h>
#include <string.h>
//定义LED灯的端口
#define LED1 P1_2
#define LED2 P1_3
//定义KEY按键的端口
#define KEY1 P1_0 //定义按键为P1_0口控制
#define KEY2 P1_1 //定义按键为P1_1口控制
/* 函数功能:LED灯IO口初始化 硬件连接:LED1-->P1_2 , LED2-->P1_3 */
void LED_Init(void) {
P1DIR |=0x3<<2; //配置P1_2、P1_3为输出模式
LED1 = 1;
LED2 = 1;
}
/* 函数功能:按键IO口初始化 硬件连接:KEY1-->P1_0 KEY2-->P1_1 */
void KEY_Init(void) {
P1SEL&=~(0x3<<0); //配置P1_0,P1_1处于通用GPIO口模式
P1DIR&=~(0x3<<0); //配置P1_0,P1_1为输入模式
P1INP|= 0x3<<0; //上拉
}
void delay10ms(void) //误差 0us {
unsigned char a,b,c;
for(c=193;c>0;c--)
for(b=118;b>0;b--)
for(a=2;a>0;a--);
}
/* 函数功能:按键扫描 返 回 值:按下的按键值 */
unsigned char Key_Scan(void) {
static unsigned char stat=1;
if((KEY1==0||KEY2==0)&&stat)
{
stat=0;
delay10ms();
if(KEY1==0)return 1;
if(KEY2==0)return 2;
}
else
{
if(KEY1&&KEY2)stat=1;
}
return 0;
}
/* 函数功能:串口0初始化 */
void Init_Uart0(void) {
PERCFG&=~(1<<0); //串口0的引脚映射到位置1,即P0_2和P0_3
P0SEL|=0x3<<2; //将P0_2和P0_3端口设置成外设功能
U0BAUD = 59; //16MHz的系统时钟产生9600BPS的波特率
U0GCR&=~(0x1F<<0);//清空波特率指数
U0GCR|=9<<0; //配置波特率的指数值
U0UCR |= 0x80; //禁止流控,8位数据,清除缓冲器
U0CSR |= 0x3<<6; //选择UART模式,使能接收器
}
/* 函数功能:UART0发送字符串函数 */
void UR0SendString(char *str,unsigned int len) {
int j;
for(j=0;j<len;j++)
{
U0DBUF = *str++; //将要发送的1字节数据写入U0DBUF
while(UTX0IF == 0);//等待数据发送完成
UTX0IF = 0; //清除发送完成标志,准备下一次发送
}
}
/*主函数*/
void main(void) {
char buff[]="-----CC2530嵌入式开发-----\r\n";
unsigned char key;
LED_Init();//初始化LED灯控制IO口
KEY_Init();//按键初始化
Init_Uart0(); //初始化串口0
while(1)
{
key=Key_Scan();
if(key)
{
//先发送一个字符串,测试串口0数据传输是否正确
UR0SendString(buff,strlen(buff));
LED1 = !LED1;
LED2 = !LED2;
}
}
}
3.2 编写串口初始化函数,实现串口字符串发送 (CPU频率在16MHZ下,波特率为115200)
#include <ioCC2530.h>
#include <string.h>
//定义LED灯的端口
#define LED1 P1_2
#define LED2 P1_3
//定义KEY按键的端口
#define KEY1 P1_0 //定义按键为P1_0口控制
#define KEY2 P1_1 //定义按键为P1_1口控制
/* 函数功能:LED灯IO口初始化 硬件连接:LED1-->P1_2 , LED2-->P1_3 */
void LED_Init(void) {
P1DIR |=0x3<<2; //配置P1_2、P1_3为输出模式
LED1 = 1;
LED2 = 1;
}
/* 函数功能:按键IO口初始化 硬件连接:KEY1-->P1_0 KEY2-->P1_1 */
void KEY_Init(void) {
P1SEL&=~(0x3<<0); //配置P1_0,P1_1处于通用GPIO口模式
P1DIR&=~(0x3<<0); //配置P1_0,P1_1为输入模式
P1INP|= 0x3<<0; //上拉
}
void delay10ms(void) //误差 0us {
unsigned char a,b,c;
for(c=193;c>0;c--)
for(b=118;b>0;b--)
for(a=2;a>0;a--);
}
/* 函数功能:按键扫描 返 回 值:按下的按键值 */
unsigned char Key_Scan(void) {
static unsigned char stat=1;
if((KEY1==0||KEY2==0)&&stat)
{
stat=0;
delay10ms();
if(KEY1==0)return 1;
if(KEY2==0)return 2;
}
else
{
if(KEY1&&KEY2)stat=1;
}
return 0;
}
/* 函数功能:串口0初始化 */
void Init_Uart0(void) {
PERCFG&=~(1<<0); //串口0的引脚映射到位置1,即P0_2和P0_3
P0SEL|=0x3<<2; //将P0_2和P0_3端口设置成外设功能
U0BAUD = 216; //16MHz的系统时钟产生115200BPS的波特率
U0GCR&=~(0x1F<<0);//清空波特率指数
U0GCR|=12<<0; //16MHz的系统时钟产生115200BPS的波特率
U0UCR |= 0x80; //禁止流控,8位数据,清除缓冲器
U0CSR |= 0x3<<6; //选择UART模式,使能接收器
}
/* 函数功能:UART0发送字符串函数 */
void UR0SendString(char *str,unsigned int len) {
int j;
for(j=0;j<len;j++)
{
U0DBUF = *str++; //将要发送的1字节数据写入U0DBUF
while(UTX0IF == 0);//等待数据发送完成
UTX0IF = 0; //清除发送完成标志,准备下一次发送
}
}
/*主函数*/
void main(void) {
char buff[]="-----万邦易嵌嵌入式开发-----\r\n";
unsigned char key;
LED_Init();//初始化LED灯控制IO口
KEY_Init();//按键初始化
Init_Uart0(); //初始化串口0
while(1)
{
key=Key_Scan();
if(key)
{
//先发送一个字符串,测试串口0数据传输是否正确
UR0SendString(buff,strlen(buff));
LED1 = !LED1;
LED2 = !LED2;
}
}
}
3.3 配置串口中断接收数据
#include <ioCC2530.h>
#include <string.h>
//定义LED灯的端口
#define LED1 P1_2
#define LED2 P1_3
//定义KEY按键的端口
#define KEY1 P1_0 //定义按键为P1_0口控制
#define KEY2 P1_1 //定义按键为P1_1口控制
unsigned char dataRecv;
unsigned char Flag = 0;
/* 函数功能:LED灯IO口初始化 硬件连接:LED1-->P1_2 , LED2-->P1_3 */
void LED_Init(void) {
P1DIR |=0x3<<2; //配置P1_2、P1_3为输出模式
LED1 = 1;
LED2 = 1;
}
/* 函数功能:按键IO口初始化 硬件连接:KEY1-->P1_0 KEY2-->P1_1 */
void KEY_Init(void) {
P1SEL&=~(0x3<<0); //配置P1_0,P1_1处于通用GPIO口模式
P1DIR&=~(0x3<<0); //配置P1_0,P1_1为输入模式
P1INP|= 0x3<<0; //上拉
}
void delay10ms(void) //误差 0us {
unsigned char a,b,c;
for(c=193;c>0;c--)
for(b=118;b>0;b--)
for(a=2;a>0;a--);
}
/* 函数功能:按键扫描 返 回 值:按下的按键值 */
unsigned char Key_Scan(void) {
static unsigned char stat=1;
if((KEY1==0||KEY2==0)&&stat)
{
stat=0;
delay10ms();
if(KEY1==0)return 1;
if(KEY2==0)return 2;
}
else
{
if(KEY1&&KEY2)stat=1;
}
return 0;
}
/* 函数功能:串口0初始化 */
void Init_Uart0(void) {
PERCFG&=~(1<<0); //串口0的引脚映射到位置1,即P0_2和P0_3
P0SEL|=0x3<<2; //将P0_2和P0_3端口设置成外设功能
U0BAUD = 216; //16MHz的系统时钟产生115200BPS的波特率
U0GCR&=~(0x1F<<0);//清空波特率指数
U0GCR|=12<<0; //16MHz的系统时钟产生115200BPS的波特率
U0UCR |= 0x80; //禁止流控,8位数据,清除缓冲器
U0CSR |= 0x3<<6; //选择UART模式,使能接收器
UTX0IF = 0; //清除TX发送中断标志
URX0IF = 0; //清除RX接收中断标志
URX0IE = 1; //使能URAT0的接收中断
EA = 1; //使能总中断
}
/* 函数功能:UART0发送字符串函数 */
void UR0SendString(char *str,unsigned int len) {
int j;
for(j=0;j<len;j++)
{
U0DBUF = *str++; //将要发送的1字节数据写入U0DBUF
while(UTX0IF == 0);//等待数据发送完成
UTX0IF = 0; //清除发送完成标志,准备下一次发送
}
}
/*================UR0接收中断服务函数================*/
#pragma vector = URX0_VECTOR
__interrupt void UART0_RecvInterrupt() {
URX0IF = 0; //清除RX接收中断标志
dataRecv = U0DBUF; //将数据从接收缓冲区读出
Flag = 1; //设置接收指令标志
}
/*================执行上位机的指令=================*/
void ExecuteTheOrder() {
Flag = 0 ; //清除接收指令标志
switch(dataRecv)
{
case 'A':
UR0SendString("选择1!\r\n",9);
break;
case 'B':
UR0SendString("选择2!\r\n",9);
break;
case 'C':
UR0SendString("选择3!\r\n",9);
break;
case 'D':
UR0SendString("选择4!\r\n",9);
break;
}
}
/*主函数*/
void main(void) {
char buff[]="-----嵌入式开发-----\r\n";
unsigned char key;
LED_Init();//初始化LED灯控制IO口
KEY_Init();//按键初始化
Init_Uart0(); //初始化串口0
while(1)
{
key=Key_Scan();
if(key)
{
//先发送一个字符串,测试串口0数据传输是否正确
UR0SendString(buff,strlen(buff));
LED2 = !LED2;
}
if(Flag == 1) //查询是否收到上位机指令
{
ExecuteTheOrder();
}
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/16100.html