ZigBee串口收发数据.docx
《ZigBee串口收发数据.docx》由会员分享,可在线阅读,更多相关《ZigBee串口收发数据.docx(21页珍藏版)》请在冰豆网上搜索。
ZigBee串口收发数据
本文转载自:
串口接收发送数据有两种方式,一种是中断的模式,另一种是DMA方式,这里主要以中断的方式,来看一下使用串口来发送,接收数据的整个流程。
这里以SerialApp例程为例子。
在mian函数中的调用HalDriverInit();函数,在函数中初始化串口,主要是配置管脚和DMA通道
voidHalDriverInit(void)
{
...................................
#if(definedHAL_UART)&&(HAL_UART==TRUE)
HalUARTInit();
#endif
....................................
}
从程序中可以看出要想使用协议栈中串口,初始化串口必须定义HAL_UART和HAL_UART TRUE在hal_board_cfg.h文件中。
#ifndefHAL_UART
#if(definedZAPP_P1)||(definedZAPP_P2)||(definedZTOOL_P1)||(definedZTOOL_P2)
#defineHAL_UARTTRUE
#else
#defineHAL_UARTFALSE
#endif
#endif
然后在osal_start_system()开始系统后,会调用Hal_ProcessPoll()来读取时间和串口。
在CC2430的数据手册中有这样一段话。
DatareceptionontheUARTisinitiatedwhena1iswrittentothe UxCSR.REbitTheUARTwillthensearchforavalidstartbitontheRXDxinputpinandsettheUxCSR.ACTIVEbithigh.Whenavalidstartbithasbeendetectedthereceived byteisshiftedintothereceiveregister.The UxCSR.RX_BYTEbitissetandareceiveinterruptisgeneratedwhentheoperationhascompleted.ThereceiveddatabyteisavailablethroughtheUxBUFregister.WhenUxBUFisread, UxCSR.RX_BYTEisclearedbyhardware.
当有数据接收时,UxCSR.RE位将被置1,然后,UART将在RXDx的输入引脚上查找一个有效的开始位,当找到这个开始位时,将设置UxCSR.ACTIVE位为高电平。
当一个有效的开始位被查找到,收到的字节将被移动到接收寄存器中。
然后,UxCSR.RX_BYTE位设为1.并且,当这个接收操作完成后接收中断会被产生。
接收到的数据可以通过操作UxBUF寄存器,当UxBUF寄存器的数据被读出后,UxCSR.RX_BYTE位被硬件清除。
串口发生中断首先调用中断的处理函数,这个是接收的中断函数。
#ifHAL_UART_0_ENABLE
HAL_ISR_FUNCTION(halUart0RxIsr,URX0_VECTOR)
{
cfg0->rxBuf[cfg0->rxHead]=U0DBUF;
if(cfg0->rxHead==cfg0->rxMax)
{
cfg0->rxHead=0;
}
else
{
cfg0->rxHead++;
}
}
#endif
该中断函数主要是把U0DBUF寄存器,也就是接收到数据的寄存器,把数据读取来放到UART的结构体中的,cfg0->rxBuf[],中,这个数组的内存分配是在HalUARTOpen()函数中。
SerialApp.c中有下面的定义
#if!
defined(SERIAL_APP_RX_MAX)
#if(defined(HAL_UART_DMA))&&HAL_UART_DMA
#defineSERIAL_APP_RX_MAX 128
#else
#defineSERIAL_APP_RX_MAX 64
#endif
#endif
SerialApp_Init()函数中有下面的赋值,
=SERIAL_APP_RX_MAX;
HalUARTOpen()函数中有下面的赋值:
所以其cfg->rxMax=128,
cfg->rxMax=config->rx.maxBufSize;
其中rxHead这个参数始终指向像一个参数被存放到rxBuf的位置。
因为硬件串口缓存器U0DBUF只能存放一个字节,如果不及时把这个接收到的转移出去,那么就会被下一个到来的字节覆盖掉,所以rxHead变量就指向了这个存放的地址,当然是基于定义的rxBuf存储空间。
而if(cfg0->rxHead==cfg0->rxMax)这一句判断也说明的很清楚,一旦这个计数达到了定义的最大接收数量,也就是说已经把rxBuf存储空间占满了,那么就不能在继续存放了。
中断函数执行完后,就应该跳到发生中断时执行的地方,这时程序继续执行,然后在osal_start_system()开始系统后,会循环调用Hal_ProcessPoll()来读取时间和串口,
voidHal_ProcessPoll()
{
HalTimerTick();
#if(definedHAL_UART)&&(HAL_UART==TRUE)
HalUARTPoll();
#endif
}
下面是HalUARTPoll();函数的源代码,在这里有对接收到的数据进行处理的程序。
voidHalUARTPoll(void)
{
#if(HAL_UART_0_ENABLE|HAL_UART_1_ENABLE)
staticuint8tickShdw;
uartCfg_t*cfg;
uint8tick;
#ifHAL_UART_0_ENABLE
//当发生串口接收中断时cfg0就会改变,如果串口没有数据输入cfg0为空,当接收到数据时cfg0将在串口中断服务程序中被改变
if(cfg0)
{
cfg=cfg0;
}
#endif
#ifHAL_UART_1_ENABLE
if(cfg1)
{
cfg=cfg1;
}
#endif
//UsetheLSBofthesleeptimer(ST0mustbereadfirstanyway).
//系统上电后,睡眠定时器就会自动启动做自增计数ST0即睡眠定时器启动到现在计算值的最低8位
tick=ST0-tickShdw;
tickShdw=ST0;
//下面是一个无限循环
do
{
//------------发送超时时间
if(cfg->txTick>tick)
{
cfg->txTick-=tick;
}
else
{
cfg->txTick=0;
}
//---------------------接收超时时间
if(cfg->rxTick>tick)
{
cfg->rxTick-=tick;
}
else
{
cfg->rxTick=0;
}
//是使用DMA方式还是使用中断方式
#ifHAL_UART_ISR
#ifHAL_UART_DMA
if(cfg->flag&UART_CFG_DMA)
{
pollDMA(cfg);
}
else//中断方式
#endif
{
pollISR(cfg);
}
#elifHAL_UART_DMA
pollDMA(cfg);
#endif
if(cfg->rxHead!
=cfg->rxTail)//不相等表示有数据
{
uint8evt;
if(cfg->rxHead>=(cfg->rxMax-SAFE_RX_MIN))
{
//已保存的数据已经超过了安全界限,发送接收满事件
evt=HAL_UART_RX_FULL;
}
elseif(cfg->rxHigh&&(cfg->rxHead>=cfg->rxHigh))
{
//rxBuf[]接收到预设值(默认80字节),则触发事件,为什么是80,在上一篇转载的文章中有介绍,这里重点关注执行的流程。
evt=HAL_UART_RX_ABOUT_FULL;
}
elseif(cfg->rxTick==0)
{
//超时事件
evt=HAL_UART_RX_TIMEOUT;
}
else
{
evt=0;
}
//如果发生事件,并且配置了回调函数则调用回调函数
if(evt&&cfg->rxCB)
{
//(cfg->flag&UART_CFG_U1F)!
=0)判读是那个串口,如果是串口1则为1,否则为0
cfg->rxCB(((cfg->flag&UART_CFG_U1F)!
=0),evt);
}
}
#ifHAL_UART_0_ENABLE
if(cfg==cfg0)
{
#ifHAL_UART_1_ENABLE
if(cfg1)
{
cfg=cfg1;
}
else
#endif
break;
}
else
#endif
break;
}while(TRUE);
#else
return;
#endif
}
说明:
(1)下面我们看一下pollISR()函数
staticvoidpollISR(uartCfg_t*cfg)
{
//计算rxBuf[]中还有多少数据没有读出(以字节为单位)
uint8cnt=UART_RX_AVAIL(cfg);
//如果串口没有接收到数据,也就是说没有发生过串口接收中断,那么cfg应为是为空的,则cnt=0如果发生了串口中断,则cnt计算出串口缓存中还有多少数据没有读出,这个缓存并不是硬件寄存器的缓存,而是程序中开辟一段空间
if(!
(cfg->flag&UART_