串口相关实验
1、串口
串口即串行通信接口,CC2530有两个串行通信接口:USART0
和USART1。两个USART具有相同的功能,可以通过设置相应
的寄存器来决定选用哪一个串口。它们能够分别运行于异步 USART 模式或者同步 SPI 模式。
USART0 对应的外部设备 IO 引脚关系为: P0_2 —— RX
P0_3 —— TX
USART1 对应的外部设备 IO 引脚关系为: P0_5 —— RX
P0_4 —— TX
TX:发送数据
RX:接收数据
2、串口发送:CC2530向PC发送内容
(1)CC2530 配置串口的一般步骤
在本次实验中,我们用到的是UART0 。
1 、 配置 IO, 使用外部设备功能。 此处配置 P0_2 和 P0_3 用作串口 USART0,参考下图
2 、 配置相应串口的控制和状态寄存器。此处配置 USART0 的工作寄存器
3 、 配置串口工作的波特率。此处配置为波特率为 115200。寄存器设置参考下表
(2)与串口配置相关的寄存器
1)PERCFG
它是外设I/O寄存器之一,称作:外设控制寄存器。它用来控制外设功能的备用位置。(备用位置:串口在I/O端口中有对应的位置。比如USART0当使用UART模式时,备用位置1根据映射表就知道,使用的是P0_2 P0_3端口来实现接收和发送数据的,其中P0_2对应TX,其中P0_3对应RX。)并且它是一个八位的寄存器,它的第0位是负责USART0 I/O控制。0:表示备用位置1 1:表示备用位置2。
例:串口0备用位置设置。
/设置串口0位备用位置1/
PERCFG &=~ 0x01;
2)P0SEL
它是一个八位功能寄存器。用来设置P0端口的每个引脚为通用I/O或者外设I/O。当某个引脚作为串口时就是外设功能。
3)P2DIR
它是一个八位方向寄存器,设置端口2。它除了设置端口P2_0~P2_4输出/输入方向之外,第6位和第7位还可以用来决定串口的优先级别。当串口0、串口1和定时器1共同使用CC2530的某些引脚时就需要设置其优先级别。
例:串口0优先级别设置
/设置串口0为第一优先级别/
P2DIR &=~0XC0;//0000 0000
4)U0CSR
八位寄存器。串口0的控制和状态寄存器。可以用来选择串口模式。它的第7位主要负责串口模式选择。
7:
0:选择SPI模式
1:选择UART模式
例:U0CSR寄存器配置
/UART方式/
U0CSR|=0x80;
5)U0GCR、U0BAUD
都是八位寄存器。U0GCR是串口0的通用控制寄存器。U0BAUD是串口0的波特率控制寄存器。它们通常是搭配使用来设置串口的波特率。波特率的计算公式:
通过寄存器U0GCR的4~0位的设置来决定BAUD_E 值,通过寄存器U0BAUD的7~0位的设置来决定 BAUD_M的值。
6)UTX0IF
USART0发送完成中断标志。
2. 相关代码
串口通讯(HELLO WEBEE)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
|
#include <string.h>
#define uint unsigned int
#define uchar unsigned char
#define LED1 P1_0
#define LED2 P1_1
char Txdata[14];
void ()
{
CLKCONCMD = 0x88;
while(CLKCONSTA & 0x40);
}
void Config_GPIO()
{
P1DIR |= 0x03;
P1INP |= 0X01;
LED1=0;
LED2=0;
}
void Delay(unsigned int k)
{
for(unsigned int i = k; i > 0; i --)
for(unsigned int j = 587; j >0; j --);
}
void Config_UART0_TX()
{
PERCFG = 0x00;
P0SEL = 0x0c;
P2DIR &= ~0XC0;
U0CSR = 0x80;
U0UCR = 0x02;
U0GCR = 11;
U0BAUD = 216;
}
void UART0_TX_String(char * txData,char num)
{
int j;
for(j=0;j<len;j++)
{
U0DBUF = *txData++;
while(UTX0IF == 0);
UTX0IF = 0;
}
}
void main(void)
{
Config_32M_Clock();
Config_GPIO();
Config_UART0_TX();
strcpy(Txdata,"HELLO WEBEE ");
while(1)
{ UART0_TX_String(Txdata,sizeof("HELLO WEBEE "));
Delay(500);
LED1=!LED1;
}
}
|
然后将代码烧写进入实验板,串口设置如下。然后在 IAR中点击GO,就会出现下面的界面
串口通讯(send & receive)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76大专栏 串口span> 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
|
#include <string.h>
#define uint unsigned int
#define uchar unsigned char
#define LED1 P1_0
#define LED2 P1_1
char Rxdata[50];
char temp;
uchar RXTXflag = 1;
uchar datanumber = 0;
#define len 10
char bufferedData[len] = {0};
void ()
{ CLKCONCMD = 0x88; while(CLKCONSTA & 0x40); }
void Config_GPIO()
{
P1DIR |= 0x03;
P1INP |= 0X01;
LED1=0;
LED2=0;
}
void Config_UART0_TX()
{
PERCFG = 0x00;
P0SEL = 0x0c;
P2DIR &= ~0XC0;
U0CSR = 0x80;
U0UCR = 0x02;
U0GCR = 11;
U0BAUD = 216;
}
void Config_UART0_RX()
{
EA = 1;
URX0IE = 1;
IT1 = 1;
U0CSR |= 0x40;
}
void main(void)
{
Config_32M_Clock();
Config_GPIO();
Config_UART0_TX();
Config_UART0_RX();
while(1)
{ if(RXTXflag == 1) { LED1=1; if( temp != 0) { if((temp!='#')&&(datanumber<50)) Rxdata[datanumber++] = temp; else { RXTXflag = 3; LED1=0; } temp = 0; } } if(RXTXflag == 3) { LED2= 1; U0CSR &= ~0x40; Uart_Send_String(Rxdata,datanumber);
U0CSR |= 0x40; RXTXflag = 1; datanumber = 0; LED2 = 0; } }
}
|
其中RXTXflag只是作为一个表示是发送还是接收状态的标志
本实验需要使用中断
我们参考手册
利用第三节外部中断的知识我们可以知道串口接收的配置为
中断处理函数为
PS:一定要记得清除中断标志位
对本次试验的一些理解
一开始程序从main函数开始执行,一直执行到程序的最后接受区都没有任何内容显示。直到我们在串口调试助手中点击“手动发送”(这个行为其实就表明有数据从串口传至CC2530),这实际上是一个触发中断事件,则接下来会进入中断,执行中断函数。这一个中断函数的最终结果就是将temp有了不为零的值。此时程序从while(1)开始执行,就会出现现象。
UART0-控制LED
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
| void main(void)
{
InitLed();
InitUart();
while(1)
{
if(RXTXflag == 1)
{
if( temp != 0)
{
if((temp!='#')&&(datanumber<3))
Rxdata[datanumber++] = temp;
else
{
RXTXflag = 3;
} temp = 0; } } if(RXTXflag == 3) { if(Rxdata[0]=='L')
switch(Rxdata[1]-48) { case 1: { LED1=~LED1; break; } case 2: { LED2=~LED2; break; } } RXTXflag = 1; datanumber = 0; } }
}
|
只写出了main函数部分 ,因为其余部分没有区别只是把CC2530向PC发数据改成了根据接收的数据来使LED亮起来
小测试
通过输入LED使两个LED都亮起来
提示:引入一个字符串比较函数,比较输入的字符串是不是LED。