历史上的今天
今天是:2025年04月09日(星期三)
2019年04月09日 | ZigBee串口说明
2019-04-09 来源:eefocus
一、串口的初始化
//系统初始化
byte osal_init_system( void )
{
……
osalInitTasks();//系统任务初始化
……
}
//任务初始化
void osalInitTasks( void )
{
……
#if defined( MT_TASK )//如果定义了MT_TASK就初始化MT任务,所以要使用uart必须编译MT_TASK
MT_TaskInit( taskID++ );
#endif
……
}
//MT_TASK初始化
void MT_TaskInit( byte task_id )
{
MT_TaskID = task_id;//分配任务ID
……
SPIMgr_Init();//SPI(UART)管理初始化
} /* MT_TaskInit() */
//SPI(UART)管理初始化
void SPIMgr_Init ()
{
halUARTCfg_t uartConfig;
/* Initialize APP ID */
App_TaskID = 0;//应用层TaskID初始化为0,在后面应用层如果想使用uart需要注册该TaskID
/* UART Configuration */
uartConfig.configured = TRUE;
uartConfig.baudRate = SPI_MGR_DEFAULT_BAUDRATE;
uartConfig.flowControl = SPI_MGR_DEFAULT_OVERFLOW;
uartConfig.flowControlThreshold = SPI_MGR_DEFAULT_THRESHOLD;
uartConfig.rx.maxBufSize = SPI_MGR_DEFAULT_MAX_RX_BUFF;
uartConfig.tx.maxBufSize = SPI_MGR_DEFAULT_MAX_TX_BUFF;
uartConfig.idleTimeout = SPI_MGR_DEFAULT_IDLE_TIMEOUT;
uartConfig.intEnable = TRUE;
#if defined (ZTOOL_P1) || defined (ZTOOL_P2)
uartConfig.callBackFunc = SPIMgr_ProcessZToolData; //回调函数
#elif defined (ZAPP_P1) || defined (ZAPP_P2)
uartConfig.callBackFunc = SPIMgr_ProcessZAppData; //回调函数
#else
uartConfig.callBackFunc = NULL;
#endif
/* Start UART */
#if defined (SPI_MGR_DEFAULT_PORT)
HalUARTOpen (SPI_MGR_DEFAULT_PORT, &uartConfig); //打开默认串口
#else
……
}
到这里串口的初始化基本就完成了,还有个打开串口,先不下去了,下面的水是越来越浑,过几天总结底层的…
二、串口的事件处理
//系统主循环
void osal_start_system( void )
{
……
Hal_ProcessPoll(); // 串口与定时器轮询函数
……
}
// 串口与定时器轮询函数
void Hal_ProcessPoll ()
{
HalTimerTick();
#if (defined HAL_UART) && (HAL_UART == TRUE)
HalUARTPoll();
#endif
}
//串口轮询函数
void HalUARTPoll( void )
{
……//这里会根据是DMA还是普通串口有两种不同的轮询方式,这里说普通串口
#if HAL_UART_ISR
#if HAL_UART_DMA
if ( cfg->flag & UART_CFG_DMA )
{
pollDMA( cfg );
}
else
#endif
{
pollISR( cfg );
}
#elif HAL_UART_DMA
pollDMA( cfg );
#endif
……
}
//普通串口轮询函数
static void pollISR( uartCfg_t *cfg )
{
……
轮询完事再次回到void HalUARTPoll函数中,看是否触发事件,如果触发了HAL_UART_RX_FULL、HAL_UART_RX_ABOUT_FULL、HAL_UART_RX_TIMEOUT三个中任意一个就调用回调函数处理。
if ( evt && cfg->rxCB )
{
cfg->rxCB( ((cfg->flag & UART_CFG_U1F)!=0), evt );
}
//串口回调函数
#define SPI_MGR_ZAPP_RX_READY 0x01
SPIMgr_ZAppRxStatus = SPI_MGR_ZAPP_RX_READY;
函数:
void SPIMgr_ProcessZAppData ( uint8 port, uint8 event )
{
osal_event_hdr_t *msg_ptr;
uint16 length = 0;
uint16 rxBufLen = Hal_UART_RxBufLen(SPI_MGR_DEFAULT_PORT);
//获取串口buf中数据的长度
……
if (event & ( HAL_UART_RX_FULL | HAL_UART_RX_ABOUT_FULL | HAL_UART_RX_TIMEOUT))
{
if ( App_TaskID )//必须这里被注册
{
// 准备向上层发送数据
//如果接收状态为READY,并且数据长度大于0说明有数据了
if ((SPIMgr_ZAppRxStatus == SPI_MGR_ZAPP_RX_READY ) && (length != 0))
{
/*要读取这些数据了,先关闭接收!*/
SPIMgr_AppFlowControl ( SPI_MGR_ZAPP_RX_NOT_READY );
/* 2 more bytes are added, 1 for CMD type, other for length */
msg_ptr = (osal_event_hdr_t *)osal_msg_allocate( length + sizeof(osal_event_hdr_t) );
//分配内存一个字节存放命令event,一个字节存放长度。剩下的存放length的内存存放数据
if ( msg_ptr )
{
msg_ptr->event = SPI_INCOMING_ZAPP_DATA;
msg_ptr->status = length;//这里状态存放了数据的长度
HalUARTRead( SPI_MGR_DEFAULT_PORT, (uint8 *)(msg_ptr + 1), length );//读入buf中的数值
//下面是触发函数
osal_msg_send( App_TaskID, (uint8 *)msg_ptr );
//这里我觉得还要打开串口,让它接收数据啊。怎么没有来这么一句话
//SPIMgr_AppFlowControl ( SPI_MGR_ZAPP_RX_READY );
}
}
}
}
}
关闭接收函数:
void SPIMgr_AppFlowControl ( bool status )
{
/* Make sure only update if needed */
if (status != SPIMgr_ZAppRxStatus )
{
SPIMgr_ZAppRxStatus = status;
}
/* App is ready to read again, ProcessZAppData have to be triggered too */
if (status == SPI_MGR_ZAPP_RX_READY)
{
SPIMgr_ProcessZAppData(SPI_MGR_DEFAULT_PORT, HAL_UART_RX_TIMEOUT );
}
}
因为在 SPIMgr_AppFlowControl ( SPI_MGR_ZAPP_RX_NOT_READY )中SPI_MGR_ZAPP_RX_NOT_READY=0,而SPIMgr_ZAppRxStatus=1;所以会执行SPIMgr_ZAppRxStatus = status;,即接收状态SPIMgr_ZAppRxStatus =0;不再满足SPIMgr_ZAppRxStatus == SPI_MGR_ZAPP_RX_READY。所以不接收数据了。
重点说明:我认为在串口回调函数加上SPIMgr_AppFlowControl ( SPI_MGR_ZAPP_RX_READY )使得串口处理完一次后立即处理下一次。
但是如果在回调函数结束前(函数内)加上这句,那么就会在流控函数中再次调用了SPIMgr_ProcessZAppData()。而导致协议栈陷入一个死循环,所以最后更正为这句话加在事件处理后,即SPI_INCOMING_ZAPP_DATA事件处理以后。不加是不行的!
三、与应用层联姻
底层和应用层联姻呢?在TI的协议栈很多都是通过注册Register。按键、串口…
通过注册可以传递任务ID,即TaskID。从而利用偷梁换柱、浑水摸鱼的技术将底层的任务传到应用层
//注册函数
void SPIMgr_RegisterTaskID( byte taskID )
{
App_TaskID = taskID;//任务ID被偷梁换柱了
}
//如果应用层调用了这个函数,则此时App_TaskID就变成了应用层的任务ID了……
现在我们在回去简单看一下串口的回调函数
void SPIMgr_ProcessZAppData ( uint8 port, uint8 event )
{
……
if (event & ( HAL_UART_RX_FULL | HAL_UART_RX_ABOUT_FULL | HAL_UART_RX_TIMEOUT))
{
if ( App_TaskID )//这时已经被偷梁换柱了,可怜的底层,就这样被欺骗了
{
//下面是触发函数
osal_msg_send( App_TaskID, (uint8 *)msg_ptr );
//将msg_ptr发送到App_TaskID,即你注册的应用层
……
}
应用层代码:
我是在SampleApp这个例子里修改的:
事件处理函数修改:
uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events )
{
afIncomingMSGPacket_t *MSGpkt;
if ( events & SYS_EVENT_MSG )
{
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );
while ( MSGpkt )
{
switch ( MSGpkt->hdr.event )
{
……
case SPI_INCOMING_ZAPP_DATA:
SampleApp_UART(MSGpkt);
……
}
void SampleApp_UART(afIncomingMSGPacket_t *pkt)
{
HalUARTWrite(0,(uint8 *)((osal_event_hdr_t *)pkt+1),pkt->hdr.status);//将串口数据写到PC(再写回去)
SPIMgr_AppFlowControl(true); //重新打开接收
}
史海拾趣
|
在电子电路中,常可以看到VCC、VDD和VSS三种不同的符号,它们有什么区别呢? 一、解释 VCC:C=circuit 表示电路的意思, 即接入电路的电压; VDD:D=device 表示器件的意思, 即器件内部的工作电压; VSS:S=series 表示公共连接的意 ...… 查看全部问答> |
|
请大家有相关经验或者认识的说说串口在线升级的方法,大概有哪些思路? 主要是如何固定一些不需要升级的文件,如何将非升级文件与升级文件在FLASH中分区存放?… 查看全部问答> |
|
at91fr40162s的CPU,晶振用的66M的。用的JTAG线是之前调at91fr40162的CPU的线和JTAG板子,是 20口的,因为at91fr40162s的CPU的JTAG线是直接从MCU接出来,只有四跟,TDI,TDO,TCK,TMS, 再接上两根电源和地线,有六跟,根据网上的说明自己弄了一 ...… 查看全部问答> |
|
ADC设计,能够输入电压,也能够输入电流。电压0-5V。电流4-20mA。那位大侠能帮帮忙 本帖最后由 dontium 于 2015-1-23 13:36 编辑 那位大侠能帮帮忙,设计一个8路ADC,需要电压和电流都能够输入。用户通过跳线来选择输入方式。电压0-5V,电流4-20mA。不省感激。谢谢分享 … 查看全部问答> |
|
volatile unsigned int *xy=(volatile unsigned int *)0x3401; 编译,这句话报错: erro:"declaration may not appear after executable statement in block" 是什么地方出了问题? #define conval 0x15 .. unsigned int a=conval; 也报 ...… 查看全部问答> |
|
大家好,我是某大学里的一名本科生,马上就毕业了。我学的是机械,以及力学。但我个人却对电路设计和单片机什么的比较有兴趣。最近,也在花相当一部分时间学习嵌入式。我个人觉得,未来机电结合才是王道。大家觉得我的想法怎么样?对于一个外行,非 ...… 查看全部问答> |
|
【视频分享】SimpleLink WiFi CC3000快速体验 TI工程师Nick为您介绍快速使用CC3000 FRAM开发包的经验。CC3000 FRAM开发包包括了MSP430 FRAM EVM板,CC3000模组EVM板,不含电池的3A电池盒,以及用于接入无线网络的无线路由器。 $(\'swf_ypz\').innerHTML=AC_FL_RunContent(\'width\', \'550\', ...… 查看全部问答> |




