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----515V 逻辑1---- -5-15V。

计算机的串行通信接口是RS-232的标准接口,而CC2530单片机的UART接口则是TTL电平,两者的电气规范不一致,所以要完成两者之间的数据通信,就需要借助接口芯片在两者之间进行电平转换,常用的有MAX232芯片。

注意:DB9接口中,公头和母头的排列顺序是不同的。

四、原理图数据手册分析

配置串口的步骤

五、代码示例

(1) 示例1: 编写串口初始化函数,实现串口字符串发送 (CPU频率在32MHZ下,波特率的为115200)

cpp 复制代码
 #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;     //32MHz的系统时钟产生115200BPS的波特率
   U0GCR&=~(0x1F<<0);//清空波特率指数
   U0GCR|=11<<0;      //32MHz的系统时钟产生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;       //清除发送完成标志,准备下一次发送
   }
 }
 ​
 /****************************************** 
  * 函数描述:32M系统时钟下的毫秒延时函数 
  ******************************************/  
 void Delay_ms(unsigned int ms)  
 {  
   unsigned int i,j;  
   for(i = 0; i < ms; i++)  
   {  
     for(j = 0;j < 1774; j++);  
   }  
 }  
 ​
 ​
 /*主函数*/
 void main(void)
 {
     char buff[]="-----万邦易嵌嵌入式开发-----\r\n";
     unsigned char key;
     CLKCONCMD &= ~0x40;            //设置系统时钟源为32MHz晶振  
     for(; CLKCONSTA & 0x40;);      //等待晶振稳定  
     CLKCONCMD &= ~0X47;            //设置系统主时钟频率为32MHz  
   
     LED_Init();//初始化LED灯控制IO口
     KEY_Init();//按键初始化
     Init_Uart0();        //初始化串口0
     while(1)          
     {  
        key=Key_Scan();
        if(key)
        {
           //先发送一个字符串,测试串口0数据传输是否正确
           UR0SendString(buff,strlen(buff));     
           LED2 = !LED2;
        }       
     }
 }
 ​
 ​

(2)示例2: 编写串口初始化函数,实现串口字符串发送 (CPU频率在16MHZ下,波特率为115200)

cpp 复制代码
 #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;       //清除发送完成标志,准备下一次发送
   }
 }
 ​
 /****************************************** 
  * 函数描述:32M系统时钟下的毫秒延时函数 
  ******************************************/  
 void Delay_ms(unsigned int ms)  
 {  
   unsigned int i,j;  
   for(i = 0; i < ms; i++)  
   {  
     for(j = 0;j < 1774; j++);  
   }  
 }  
 ​
 ​
 /*主函数*/
 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;
        }       
     }
 }
 ​
 ​

(3)示例3:中断接收

cpp 复制代码
 #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();
       }
     }
 }
 ​
 ​
 ​

六、波特率计算

计算波特率

CC2530的波特率由BAUD_E和BAUD_M共同决定:

F为微控制器的系统时钟频率:16MHz或32MHz。

在TI公司提供的数据手册中,给出了32MHz系统时钟下各常用波特率的参数值,由计算公式亦不难得出16MHz系统时钟下对应的参数值。

相关推荐
ღ᭄ꦿ࿐Never say never꧂4 分钟前
微服务架构中的负载均衡与服务注册中心(Nacos)
java·spring boot·后端·spring cloud·微服务·架构·负载均衡
.生产的驴13 分钟前
SpringBoot 消息队列RabbitMQ 消息确认机制确保消息发送成功和失败 生产者确认
java·javascript·spring boot·后端·rabbitmq·负载均衡·java-rabbitmq
海里真的有鱼21 分钟前
Spring Boot 中整合 Kafka
后端
布瑞泽的童话27 分钟前
无需切换平台?TuneFree如何搜罗所有你爱的音乐
前端·vue.js·后端·开源
写bug写bug36 分钟前
6 种服务限流的实现方式
java·后端·微服务
离开地球表面_991 小时前
索引失效?查询结果不正确?原来都是隐式转换惹的祸
数据库·后端·mysql
Victor3561 小时前
Oracle(138)如何监控数据库性能?
后端
不修×蝙蝠2 小时前
eclipse使用 笔记02
前端·笔记·后端·eclipse
吃面不喝汤664 小时前
Flask + Swagger 完整指南:从安装到配置和注释
后端·python·flask
讓丄帝愛伱5 小时前
spring boot启动报错:so that it conforms to the canonical names requirements
java·spring boot·后端