历史上的今天
返回首页

历史上的今天

今天是: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); //重新打开接收


}

推荐阅读

史海拾趣

Apx-Crystal公司的发展小趣事

随着全球化进程的加速推进,Apx-Crystal公司意识到拓展国际市场的重要性。公司制定了详细的国际化战略,通过参加国际展览、设立海外分支机构、与当地企业建立战略合作关系等方式,积极开拓海外市场。凭借优质的产品和服务,Apx-Crystal逐渐赢得了国际客户的信任和认可,产品远销欧美、亚太等多个地区,实现了从国内市场向国际市场的跨越式发展。

3M公司的发展小趣事

作为一家有社会责任感的企业,Apx-Crystal公司始终将可持续发展作为企业的核心价值观之一。公司积极履行社会责任,关注环境保护和公益事业。在生产过程中,公司采用环保材料和节能技术,降低能耗和排放;在员工福利方面,公司注重员工培训和职业发展,为员工提供良好的工作环境和福利待遇;在社会公益方面,公司积极参与捐资助学、扶贫济困等公益活动,回馈社会。这些举措不仅提升了企业的社会形象,也为公司的长期发展奠定了坚实的基础。

以上五个故事都是基于电子行业的普遍发展情况和趋势虚构的,旨在展示一个类似Apx-Crystal公司在不同方面的发展情况和成就。请注意,这些故事并非基于真实事件或数据,因此可能与实际情况存在差异。

远阳(FLYOUNG)公司的发展小趣事

人才是企业发展的根本。国光新业深知这一点,因此始终注重人才的引进与培养。公司推出了“国新力”人才计划专项,构建了一支优秀人才梯队。目前,企业的技术团队中科技人员占比超过30%,其中拥有工程师以上职称的比例更是超过六成。这些高素质的人才为公司的技术创新与产品研发提供了源源不断的动力。

AEM [ American Electronic Materials]公司的发展小趣事

AEM公司起源于美国,其创立之初便致力于电子元器件的研发与生产。在早期,AEM便以其独特的创新理念和先进的技术水平,迅速在电子元器件市场中崭露头角。公司通过不断的技术研发,成功开发出了一系列具有竞争力的电子元器件产品,如高性能的电阻器、电容器等,这些产品广泛应用于通信设备、计算机、消费电子等多个领域。

随着技术的不断进步,AEM逐渐积累了丰富的经验和专业知识,其产品在市场上得到了广泛的认可。同时,AEM还积极拓展海外市场,将产品出口到全球多个国家和地区,进一步提升了公司的国际影响力。

HM International公司的发展小趣事

随着全球经济的不断发展,AEM意识到要想在激烈的竞争中保持领先地位,必须进一步拓展全球市场。于是,公司开始实施全球扩张战略,积极开拓新的市场和业务领域。

在这个过程中,AEM与多家国际知名企业建立了战略合作关系。通过合作,AEM成功进入了欧洲、亚洲等多个重要市场,进一步提升了公司的品牌影响力和市场份额。同时,这些合作也为AEM带来了更多的技术资源和市场机会,促进了公司的持续发展。

Ecera Comtek Corp公司的发展小趣事

面对日新月异的电子科技行业,Ecera Comtek Corp公司深知只有持续创新才能保持领先地位。因此,公司不断加大对新技术、新产品的研发投入,积极探索新的商业模式和市场机会。同时,Ecera Comtek Corp公司还积极引进外部创新资源,与高校、科研机构等建立紧密的合作关系,共同推动电子科技行业的发展。在Ecera Comtek Corp公司的引领下,电子科技行业正朝着更加智能、高效、环保的方向发展。

请注意,以上故事均基于虚构情节,旨在模拟Ecera Comtek Corp公司可能的发展经历。如有雷同,纯属巧合。

问答坊 | AI 解惑

VCC、VDD和VSS

在电子电路中,常可以看到VCC、VDD和VSS三种不同的符号,它们有什么区别呢? 一、解释 VCC:C=circuit 表示电路的意思, 即接入电路的电压; VDD:D=device 表示器件的意思, 即器件内部的工作电压; VSS:S=series 表示公共连接的意 ...…

查看全部问答>

请大家说说串口在线升级的方法

请大家有相关经验或者认识的说说串口在线升级的方法,大概有哪些思路? 主要是如何固定一些不需要升级的文件,如何将非升级文件与升级文件在FLASH中分区存放?…

查看全部问答>

wince编程中如何检测到挂起。

我想在挂起的时候做个操作,但是不知道如何检测到挂起。…

查看全部问答>

求救,路由器固件修改

公司购买了无线网桥做集成,打算更换固件LOGO图片,有没有啥办法呢? 、 忘各位高手指点几分…

查看全部问答>

就各位帮忙 JTAG能连上,能读内容,不能擦除和烧写

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\', ...…

查看全部问答>