CC2541蓝牙学习——串口_1

时间:2024-03-03 19:55:46

CC2541有两个串行通信接口,分别是USART0和USART1,它们能够分别运行于异步UART模式或者同步SPI模式。两个USART具体同样的功能,可以设置在单独的I/O引脚。

1.UART模式

UART模式提供异步串行接口,在UART模式中,有2种接口选择方式:2线接口和4线接口。

  • 2线接口,使用RXD、TXD。
  • 4线接口,使用RXD、TXD、RTS和CTS。

I/O外设引脚映射如下图所示:

根据上面的外设I/O引脚映射可知

UART0对应的外部设置IO引脚关系为:位置1:P0_2----RX    P0_3----TX     位置2:P1_4----RX    P1_5----TX

UART1对应的外部设置IO引脚关系为:位置1:P0_5----RX    P0_4----TX     位置2:P1_7----RX    P1_6----TX

UART模式的操作有以下特点。

  • 8位或者9位负载数据
  • 奇校验、偶校验或者无奇偶校验
  • 配置起始位和停止位电平
  • 配置LSB(最低有效位)或MSB(最高有效位)首先传输
  • 独立接收中断
  • 独立收发DMA触发
  • 奇偶校验和帧检验出错状态

UART模式提供全双工传送,也就是说可以同时收发数据,传送一个UART字节包括1个起始位,8个数据位,1个作为可选的第9位数据或者奇偶校验位,再加上1个或者2个停止位。

UART操作由USART控制和状态寄存器UxCSR以及UART控制寄存器UxUCR来控制,x是USART的编号,数值为0或者1。

当UxCSR.MODE设置为1时设定为UART模式。

1)UART的发送过程

当USART收发数据缓冲器UxDBUF写入数据时,该字节自动发送到输出引脚TXD,UxDBUF寄存器时双缓冲的。当字节传送开始时,UxCSR.ACTIVE位变为高电平,而当字节传送结束时变为低电平。当传送结束时,UxCSR.TX_BYTE位设置为1。当USART收发数据缓冲寄存器就绪,准备接收新的发送数据时,就产生了一个中断请求,该中断在传送开始后立刻发生。

2)UART的接收过程

当1写入UxCSR.RE位时,UART开始接收数据。UART在输入引脚RXD上寻找有效起始位,并且设置UxCSR.ACTIVE位为1,当检测出有效起始位时,收到的字节就传入到接收寄存器,UxCSR.RX_BYTE位设置为1,该操作完成时,产生接收中断,同时UxCSR.ACTIVE变为0,通过寄存器UxDBUF提取收到的数据字节。当UxDBUF读出时,UxCSR.RX_BYTE位由硬件清零。

当运行UART模式时,内部的波特率发生器设置UART波特率。当运行在SPI模式时,内部的波特率发生器设置SPI主时钟频率。波特率由寄存器UxBAUD.BAUD_M[7:0] 和UxGCR.BAUD_E[4:0]定义。该波特率用于UART传送,也用于SPI传送的串行时钟速率。波特率定义公式:

式中:f是系统的时钟频率,等于16MHz或者32MHz

标准波特率所需的寄存器值如下表所示,该表适用于32MHz系统时钟。波特率误差,用百分数表示。

CC2530配置串口的一般步骤

1、配置串口的备用位置,是备用位置1,还是备用位置2。配置寄存器PERCFG外设控制寄存器

2、配置端口的外设优先级。此处配置P0外设优先作为UART0。配置寄存器P2DIR

3、配置IO,使用外部设备功能。此处配置P0_2和P0_3用作串口UART0。配置寄存器P0SEL

4、配置相应串口的控制和状态寄存器。配置寄存器U0CSR、U0UCR

5、配置串口工作的波特率。配置寄存器U0GCR、U0BAUD

6、将对应的串口接收/发送中断标志位清0,清零:TCON.URX0IF、TCON.URX1IF、IRCON2.UTX0IF、IRCON2.UTX1IF

7、使能串口接收中断(一般发送不用中断),置1 IEN0.URX0IE

8、开总中断

中断相关的寄存器如下:

IEN0(0xA8)

TCON(0x88)

 

 IRCON2(0xE8)

 1 /*****************************************************************************
 2 *函 数 名:InitUART
 3 *功    能:UART0串口初始化,波特率:115200
 4 *入口参数:无
 5 *出口参数:无
 6 ******************************************************************************/
 7 void InitUART(void)
 8 {
 9   PERCFG &= ~0x01;     //USART0为位置1
10   P2DIR &= ~0xc0;      //优先级USART0 >USART1 >定时器1
11   P0SEL |= 0x0c;       //P0_2,P0_3 用作串口(外部设备功能)
12   U0CSR |= 0x80;       //设置为UART 方式
13   U0CSR |= 0x40;       //使能接收器
14   
15   U0UCR = 0x02;        //禁止流控制,8bits,无校验位,1位停止位
16                        //起始位低电平,停止位高电平
17   U0GCR |=11;          //32MHz 下的BAUD_E:11, 115200
18   U0BAUD |= 216;       //32MHz 下的BAUD_M:216 11520
19   UTX0IF = 0;          //UART0 TX 中断标志初始置位0
20   IEN0 |= 0x04;        //使能USART0 RX中断
21   EA = 1;              //开总中断
22 }

实例程序:串口控制LED1和LED2等的亮灭以及上位机控制串口接收,这里的通信协议比较简单,上位机发送两字节的数据:一个控制灯亮灭的字节,一个结束字节\'#\'

"1#":LED1灭

"2#":LED1亮

"3#":LED2灭

"4#":LED2亮

"5#":LED1、LED2亮

"6#":LED1、LED2灭

"7#":CC2541向上位机发送字符串”Hello Chen Zhao!“ 按一下界面上的”接收“按钮,接收下位机发送过来的字符串。

这个程序写的比较简单,这里只是一个演示,很容易出现发送解码错误,应该组帧,以一定的通信协议传输数据,包括帧头、校验、数据字节、帧尾,在后续串口介绍中,将专门介绍下这方面的技巧。

为了验证程序,我做了一个上位机程序,界面如下,用labview软件编写的。如果需要的话,可以拿走源程序。

  1 /******************************************************************************
  2 *文 件 名:main.c
  3 *作    者:陈照
  4 *时    间:2015-05-18
  5 *版    本:1.0
  6 *描    述:UART串口发送与接收
  7 ******************************************************************************/
  8 #include <iocc2541.h>
  9 #include <string.h>
 10 
 11 typedef unsigned char uchar;
 12 typedef unsigned int  uint;
 13 
 14 #define LED1 P1_0
 15 #define LED2 P1_1
 16 
 17 char Rxdata[2] = " " ;  //串口接收字符串
 18 char Txdata[] = "Hello Chen Zhao!" ;  //串口接收字符串
 19 int  txnum = sizeof(Txdata);
 20 
 21 char temp;             //串口接收字符
 22 uchar datanum = 0;     //串口接收字符串长度
 23 uchar RXflag = 1;
 24 uchar TXflag = 0;
 25 
 26 /****************************************************************
 27 *函 数 名:InitClock
 28 *功    能:系统时钟初始化
 29 *入口参数:无
 30 *出口参数:无
 31 *****************************************************************/
 32 void InitClock(void)
 33 {
 34 CLKCONCMD &= ~0x40; // 设置系统时钟源为 32MHZ晶振
 35 while(CLKCONSTA & 0x40); // 等待晶振稳定 
 36 CLKCONCMD &= ~0x47; // 设置系统主时钟频率为 32MHZ
 37 }
 38 
 39 /******************************************************************************
 40 *函 数 名:InitLED
 41 *功    能:LED口功能初始化
 42 *入口参数:无
 43 *出口参数:无
 44 ******************************************************************************/
 45 void InitLED(uchar On_Off)
 46 {
 47   P1SEL &= ~0x03;      //P1.0、P1.1设置为通用I/O口
 48   P1DIR |=  0x03;      ///P1.0、P1.1设置为输出
 49   LED1 = On_Off;       ///P1.0、P1.1亮灭初始化
 50   LED2 = On_Off;
 51 }
 52 
 53 /******************************************************************************
 54 *函 数 名:InitUART
 55 *功    能:UART0串口初始化,波特率:115200
 56 *入口参数:无
 57 *出口参数:无
 58 ******************************************************************************/
 59 void InitUART(void)
 60 {
 61   PERCFG &= ~0x01;     //USART0为位置1
 62   P2DIR &= ~0xc0;      //优先级USART0 >USART1 >定时器1
 63   P0SEL |= 0x0c;       //P0_2,P0_3 用作串口(外部设备功能)
 64   U0CSR |= 0x80;       //设置为UART 方式
 65   U0CSR |= 0x40;       //使能接收器
 66   
 67   U0UCR = 0x02;        //禁止流控制,8bits,无校验位,1位停止位
 68                        //起始位低电平,停止位高电平
 69   U0GCR |=11;          //32MHz 下的BAUD_E:11, 115200
 70   U0BAUD |= 216;       //32MHz 下的BAUD_M:216 11520
 71   UTX0IF = 0;          //UART0 TX 中断标志初始置位0
 72   IEN0 |= 0x04;        //使能USART0 RX中断
 73   //IEN2 |= 0x04;      //使能USART0 TX中断
 74   EA = 1;              //开总中断
 75 }
 76 
 77 /****************************************************************************
 78 * 名    称: UartSendString()
 79 * 功    能: 串口发送函数
 80 * 入口参数: Data:发送缓冲区   len:发送长度
 81 * 出口参数: 无
 82 ****************************************************************************/
 83 void UartSendString(char *Data, int len)
 84 {
 85   uint i;
 86   U0CSR &= ~0x40;  
 87   
 88   for(i=0; i<len; i++)
 89   {
 90     U0DBUF = *Data++;
 91     while(UTX0IF == 0);
 92     UTX0IF = 0;
 93   }
 94   TXflag = 0;  
 95   U0CSR |= 0x40;       //使能接收器
 96 }
 97 
 98 /******************************************************************************
 99 *函 数 名:UART0_ISR
100 *功    能:串口0中断服务程序
101 *入口参数:无
102 *出口参数:无
103 ******************************************************************************/
104 #pragma vector = URX0_VECTOR 
105 __interrupt void UART0_ISR(void) 
106 { 
107   URX0IF = 0;           //UART0 RX中断标志位清0
108   temp = U0DBUF;        //读取U0DBUF的值
109 }
110 
111 /******************************************************************************
112 *程序入口函数
113 ******************************************************************************/
114 int main(void)
115 {  
116   InitClock();
117   InitLED(0);          //LED初始化,熄灭LED1、LED2
118   InitUART();          //UART0串口初始化
119   
120   UartSendString(Txdata,txnum); 
121   while(1)
122   {
123     if(RXflag == 1)
124     {
125       if(temp !=0)
126       {
127         if((temp != \'#\') && (datanum < 2))
128         {
129           Rxdata[datanum++] = temp;
130         }
131         else
132         {
133           RXflag = 2;
134         }
135 
136           temp = 0;
137       }
138     }
139     if(RXflag == 2)
140     {
141       switch(Rxdata[0])
142       {
143         case \'1\':LED1 = 0;break;
144         case \'2\':LED1 = 1;break;
145         case \'3\':LED2 = 0;break;
146         case \'4\':LED2 = 1;break;
147         case \'5\':
148         {
149           LED1 = 1;
150           LED2 = 1;
151           break;
152         }
153         case \'6\':
154         {
155           LED1 = 0;
156           LED2 = 0;
157           break;
158         }
159         case \'7\':
160         {
161            TXflag = 1;
162            break;
163            
164         }
165         default: 
166         {//LED1 = 0;
167          //LED2 = 0;
168         }
169       }
170       RXflag = 1;
171       memset(Rxdata, 0, 2);
172       datanum = 0;
173     }
174     if(TXflag == 1)
175     {
176        UartSendString(Txdata,txnum); 
177        
178     }
179   }
180 }
View Code