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 }
来源:https://www.cnblogs.com/chenzhao207/p/4531941.html
