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系统时钟下对应的参数值。

相关推荐
追逐时光者6 小时前
推荐 12 款开源美观、简单易用的 WPF UI 控件库,让 WPF 应用界面焕然一新!
后端·.net
Jagger_6 小时前
敏捷开发流程-精简版
前端·后端
苏打水com6 小时前
数据库进阶实战:从性能优化到分布式架构的核心突破
数据库·后端
间彧7 小时前
Spring Cloud Gateway与Kong或Nginx等API网关相比有哪些优劣势?
后端
间彧7 小时前
如何基于Spring Cloud Gateway实现灰度发布的具体配置示例?
后端
间彧7 小时前
在实际项目中如何设计一个高可用的Spring Cloud Gateway集群?
后端
间彧7 小时前
如何为Spring Cloud Gateway配置具体的负载均衡策略?
后端
间彧8 小时前
Spring Cloud Gateway详解与应用实战
后端
EnCi Zheng9 小时前
SpringBoot 配置文件完全指南-从入门到精通
java·spring boot·后端
烙印6019 小时前
Spring容器的心脏:深度解析refresh()方法(上)
java·后端·spring