CC2530(zigbee)入门开发: 串口收发配置

举报
DS小龙哥 发表于 2022/02/28 09:25:18 2022/02/28
【摘要】 串口传输协议是嵌入式开发里比较常见的传输协议,开发阶段用的最多的方式就是将MCU的调试信息打印到PC机串口终端显示,方便调试错误。 一般传输协议分为两种: 并口和串口。

一、串口协议介绍

串口传输协议是嵌入式开发里比较常见的传输协议,开发阶段用的最多的方式就是将MCU的调试信息打印到PC机串口终端显示,方便调试错误。

一般传输协议分为两种: 并口和串口。

并口传输协议:指数据的各位同时发送或接收,每个数据位使用单独的一条导线。传输速度快、效率高,但需要的数据线较多,成本高。

串口传输协议:指数据一位接一位地顺 序发送或接收。需要的数据线少,成本低,但传输速度慢,效率低。

CC2530一共有两个串口通信接口,分别是USART0和USART1,它们能够配置成异步UART模式或者同步SPI模式。

两个USART接口具有相同的功能,通过PERCFG寄存器可以设置两个USART接口对应外部I/O引脚的映射关系:

	位置1RX0 --- P0_2   TX0 --- P0_3               RX1 --- P0_5   TX1 --- P0_4
	位置2RX0 --- 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。

串口通信过程中,速度的指标由波特率表示。

常见的波特率设置表如下:
image.png

计算波特率的方法: CC2530的波特率由BAUD_E和BAUD_M共同决定:

image.png

二、原理图数据手册分析

image.png

image.png

image.png

image.png

image.png

三、串口配置代码示例

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();
      }
    }
}

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。