前言:上一节讲UART基本知识介绍完了,并深入剖析了一个串口发送工程,本节将进一步介绍串口收发!
1、初始化
在串口初始化部分,和上一节不同的地方是:
51 U0CSR |= 0x40; //允许接收
52 IEN0 |= 0x84; //开总中断允许接收中断
第51行使能接收数据,上一节介绍的仅仅是发送,所以没有这一句配置:
第51行开总中断和UART0中断:
/****************************************************************************
* 文 件 名: main.c
* 描 述: 设置串口调试助手波特率:115200bps 8N1
* 串口调试助手给CC2530发字符串时,开发板会返回接收到的字符串
****************************************************************************/
#include <ioCC2530.h>
#include <string.h> typedef unsigned char uchar;
typedef unsigned int uint; #define UART0_RX 1
#define UART0_TX 2
#define SIZE 51 char RxBuf;
char UartState;
uchar count;
char RxData[SIZE]; //存储发送字符串 /****************************************************************************
* 名 称: DelayMS()
* 功 能: 以毫秒为单位延时
* 入口参数: msec 延时参数,值越大,延时越久
* 出口参数: 无
****************************************************************************/
void DelayMS(uint msec)
{
uint i,j; for (i=; i<msec; i++)
for (j=; j<; j++);
} /****************************************************************************
* 名 称: InitUart()
* 功 能: 串口初始化函数
* 入口参数: 无
* 出口参数: 无
****************************************************************************/
void InitUart(void)
{
PERCFG = 0x00; //外设控制寄存器 USART 0的IO位置:0为P0口位置1
P0SEL = 0x0c; //P0_2,P0_3用作串口(外设功能)
P2DIR &= ~0xC0; //P0优先作为UART0 U0CSR |= 0x80; //设置为UART方式
U0GCR |= ;
U0BAUD |= ; //波特率设为115200
UTX0IF = ; //UART0 TX中断标志初始置位0
U0CSR |= 0x40; //允许接收
IEN0 |= 0x84; //开总中断允许接收中断
} /****************************************************************************
* 名 称: UartSendString()
* 功 能: 串口发送函数
* 入口参数: Data:发送缓冲区 len:发送长度
* 出口参数: 无
****************************************************************************/
void UartSendString(char *Data, int len)
{
uint i; for(i=; i<len; i++)
{
U0DBUF = *Data++;
while(UTX0IF == );
UTX0IF = ;
}
} /****************************************************************************
* 名 称: UART0_ISR(void) 串口中断处理函数
* 描 述: 当串口0产生接收中断,将收到的数据保存在RxBuf中
****************************************************************************/
#pragma vector = URX0_VECTOR
__interrupt void UART0_ISR(void)
{
URX0IF = ; // 清中断标志
RxBuf = U0DBUF;
}
/****************************************************************************
* 程序入口函数
****************************************************************************/
void main(void)
{
CLKCONCMD &= ~0x40; //设置系统时钟源为32MHZ晶振
while(CLKCONSTA & 0x40); //等待晶振稳定为32M
CLKCONCMD &= ~0x47; //设置系统主时钟频率为32MHZ InitUart(); //调用串口初始化函数
UartState = UART0_RX; //串口0默认处于接收模式
memset(RxData, , SIZE); while()
{
if(UartState == UART0_RX) //接收状态
{
if(RxBuf != )
{
if((RxBuf != '#')&&(count < ))//以'#'为结束符,一次最多接收50个字符
RxData[count++] = RxBuf;
else
{
if(count >= ) //判断数据合法性,防止溢出
{
count = ; //计数清0
memset(RxData, , SIZE);//清空接收缓冲区
}
else
UartState = UART0_TX; //进入发送状态
}
RxBuf = ;
}
} if(UartState == UART0_TX) //发送状态
{
U0CSR &= ~0x40; //禁止接收
UartSendString(RxData, count); //发送已记录的字符串。
U0CSR |= 0x40; //允许接收
UartState = UART0_RX; //恢复到接收状态
count = ; //计数清0
memset(RxData, , SIZE); //清空接收缓冲区
}
}
}
2、中断回调函数
第77~82行是UART0中断处理函数,每次有数据从上位机发送下来都会触发该函数执行,在概述内将上位机发送来的数据保存在RxBuf中:
77 #pragma vector = URX0_VECTOR
78 __interrupt void UART0_ISR(void)
79 {
80 URX0IF = 0; // 清中断标志
81 RxBuf = U0DBUF;
82 }
3、main函数流程
串口初始状态为接收状态,其中100-118行把中断处理函数中暂存的接收数据RxBuf转存到RxData数组中,接收过程中发现结束标志位则将状态转换为发送状态,则120~128行发送数据的代码段将被执行:
120 if(UartState == UART0_TX) //发送状态
121 {
122 U0CSR &= ~0x40; //禁止接收
123 UartSendString(RxData, count); //发送已记录的字符串。
124 U0CSR |= 0x40; //允许接收
125 UartState = UART0_RX; //恢复到接收状态
126 count = 0; //计数清0
127 memset(RxData, 0, SIZE); //清空接收缓冲区
128 }
这里要特别注意,发送的时候要禁止接收,发送完毕要使能接收,着也就是122行和124行代码的意图!
Zigbee系列文章:
[ZigBee] 3、ZigBee基础实验——GPIO输出控制实验-控制Led亮灭
[ZigBee] 5、ZigBee基础实验——图文与代码详解定时器1(16位定时器)(长文)
[ZigBee] 6、ZigBee基础实验——定时器3和定时器4(8 位定时器)
[ZigBee] 7、ZigBee之UART剖析(ONLY串口发送)
PS:如果您觉得还不错,点个赞,让更多人受益~
@beautifulzzzz 2016-07-16 continue~
e-mail:beautifulzzzz@qq.com
sina:http://weibo.com/beautifulzzzz?is_all=1