欢迎来到冰点文库! | 帮助中心 分享价值,成长自我!
冰点文库
全部分类
  • 临时分类>
  • IT计算机>
  • 经管营销>
  • 医药卫生>
  • 自然科学>
  • 农林牧渔>
  • 人文社科>
  • 工程科技>
  • PPT模板>
  • 求职职场>
  • 解决方案>
  • 总结汇报>
  • ImageVerifierCode 换一换
    首页 冰点文库 > 资源分类 > DOCX文档下载
    分享到微信 分享到微博 分享到QQ空间

    ZStack中串口发送接收的流程.docx

    • 资源ID:919820       资源大小:21.42KB        全文页数:14页
    • 资源格式: DOCX        下载积分:3金币
    快捷下载 游客一键下载
    账号登录下载
    微信登录下载
    三方登录下载: 微信开放平台登录 QQ登录
    二维码
    微信扫一扫登录
    下载资源需要3金币
    邮箱/手机:
    温馨提示:
    快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。
    如填写123,账号就是123,密码也是123。
    支付方式: 支付宝    微信支付   
    验证码:   换一换

    加入VIP,免费下载
     
    账号:
    密码:
    验证码:   换一换
      忘记密码?
        
    友情提示
    2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
    3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
    4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
    5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

    ZStack中串口发送接收的流程.docx

    1、ZStack中串口发送接收的流程Z-Stackxx串口发送接收的流程串口接收发送数据有两种方式,一种是中断的模式,另一种是DMA方式,这里主要以中断的方式,来看一下使用串口来发送,接收数据的整个流程。这里以SerialApp例程为例子。在mian函数中的调用HalDriverInit();函数,在函数中初始化串口,主要是配置管脚和DMA通道void HalDriverInit (void)/* UART */#if (defined HAL_UART) & (HAL_UART = TRUE)HalUARTInit();#endif从程序中可以看出要想使用协议栈中串口,初始化串口必须定义HAL_

    2、UART和HAL_UART TRUE 在hal_board_cfg.h文件中。#ifndef HAL_UART#if (defined ZAPP_P1) | (defined ZAPP_P2) | (defined ZTOOL_P1) |(defined ZTOOL_P2)#define HAL_UART TRUE#else#define HAL_UART FALSE#endif /* ZAPP, ZTOOL */#endif /* HAL_UART */然后在osal_start_system()开始系统后,会调用Hal_ProcessPoll()来读取时间和串口。在CC2430的数据手册中

    3、有这样一段话。Data reception on the UART is initiatedwhen a 1 is written to the UxCSR.RE bitThe UART will then search for a valid start bit on the RXDx input pin and set the hardware.当有数据接收时,UxCSR.RE位将被置1,然后,UART将在RXDx的输入引脚上查找一个有效的开始位,当找到这个开始位时,将设置UxCSR.ACTIVE位为高电平。当一个有效的开始位被查找到,收到的字节将被移动到接收寄存器中。然后,UxCSR.R

    4、X_BYTE位设为1.并且,当这个接收操作完成后接收中断会被产生。接收到的数据可以通过操作UxBUF寄存器,当UxBUF寄存器的数据被读出后,UxCSR.RX_BYTE位被硬件清除。串口发生中断首先调用中断的处理函数,这个是接收的中断函数。#if HAL_UART_0_ENABLEHAL_ISR_FUNCTION( halUart0RxIsr, URX0_VECTOR )cfg0-rxBufcfg0-rxHead = U0DBUF;if ( cfg0-rxHead = cfg0-rxMax )cfg0-rxHead = 0;elsecfg0-rxHead+;#endif该中断函数主要是把U0D

    5、BUF寄存器,也就是接收到数据的寄存器,把数据读取来放到UART的结构体中的,cfg0-rxBuf,中,这个数组的内存分配是在HalUARTOpen()函数中。SerialApp.c中有下面的定义#if !defined( SERIAL_APP_RX_MAX )#if (defined( HAL_UART_DMA ) & HAL_UART_DMA#define SERIAL_APP_RX_MAX128#else/* The generic safe Rx minimum is 48, but if you know your PC Appwill not* continue to send m

    6、ore than a byte after receiving the CTS,lower max* here and safe min in _hal_uart.c to just 8.*/#define SERIAL_APP_RX_MAX64#endif#endifSerialApp_Init()函数中有下面的赋值,uartConfig.rx.maxBufSize = SERIAL_APP_RX_MAX;HalUARTOpen()函数中有下面的赋值:所以其cfg-rxMax=128,cfg-rxMax = config-rx.maxBufSize;其中rxHead这个参数始终指向像一个参数

    7、被存放到rxBuf的位置。因为硬件串口缓存器U0DBUF只能存放一个字节,如果不及时把这个接收到的转移出去,那么就会被下一个到来的字节覆盖掉,所以rxHead变量就指向了这个存放的地址,当然是基于定义的rxBuf存储空间。而if ( cfg0-rxHead = cfg0-rxMax )这一句判断也说明的很清楚,一旦这个计数达到了定义的最大接收数量,也就是说已经把rxBuf存储空间占满了,那么就不能在继续存放了。中断函数执行完后,就应该跳到发生中断时执行的地方,这时程序继续执行,然后在osal_start_system()开始系统后,会循环调用Hal_ProcessPoll()来读取时间和串口,

    8、void Hal_ProcessPoll ()/* Timer Poll */HalTimerTick();/* UART Poll */#if (defined HAL_UART) & (HAL_UART = TRUE)HalUARTPoll();#endif下面是HalUARTPoll();函数的源代码,在这里有对接收到的数据进行处理的程序。void HalUARTPoll( void )#if ( HAL_UART_0_ENABLE | HAL_UART_1_ENABLE )static uint8 tickShdw;uartCfg_t *cfg;uint8 tick;#if HAL_U

    9、ART_0_ENABLE/当发生串口接收中断时cfg0就会改变,如果串口没有数据输入cfg0为空,当接收到数据时cfg0将在串口中断服务程序中被改变if ( cfg0 )cfg = cfg0;#endif#if HAL_UART_1_ENABLEif ( cfg1 )cfg = cfg1;#endif/ Use the LSB of the sleep timer (ST0 must be read first anyway)./系统上电后,睡眠定时器就会自动启动做自增计数ST0即睡眠定时器启动到现在计算值的最低8位tick = ST0 - tickShdw;tickShdw = ST0;/下

    10、面是一个无限循环do/-发送超时时间if ( cfg-txTick tick )cfg-txTick -= tick;elsecfg-txTick = 0;/-接收超时时间if ( cfg-rxTick tick )cfg-rxTick -= tick;elsecfg-rxTick = 0;/是使用DMA方式还是使用中断方式#if HAL_UART_ISR#if HAL_UART_DMAif ( cfg-flag & UART_CFG_DMA )pollDMA( cfg );else/中断方式#endifpollISR( cfg );#elif HAL_UART_DMApollDMA( cfg

    11、 );#endif/* The following logic makes continuous callbacks on any eligibleflag* until the condition corresponding to the flag is rectified.* So even if new data is not received, continuous callbacks aremade./如果接收缓存中有数据,当接收数据时rxHead会增计数,当读取数据时rxTail会增计数,两个标志的初始值都为0,所以这两个标志的差值就指示了缓存中有多少的数据*/if ( cfg-r

    12、xHead != cfg-rxTail )/不相等表示有数据uint8 evt;if ( cfg-rxHead = (cfg-rxMax - SAFE_RX_MIN) )/已保存的数据已经超过了安全界限,发送接收满事件evt = HAL_UART_RX_FULL;else if ( cfg-rxHigh & (cfg-rxHead = cfg-rxHigh) )/rxBuf 接收到预设值(默认80字节),则触发事件,为什么是80,在上一篇转载的文章中有介绍,这里重点关注执行的流程。evt = HAL_UART_RX_ABOUT_FULL;else if ( cfg-rxTick = 0 )/超

    13、时事件evt = HAL_UART_RX_TIMEOUT;elseevt = 0;/如果发生事件,并且配置了回调函数则调用回调函数if ( evt & cfg-rxCB )/(cfg-flag & UART_CFG_U1F)!=0)判读是那个串口,如果是串口1则为1,否则为0cfg-rxCB( (cfg-flag & UART_CFG_U1F)!=0), evt );#if HAL_UART_0_ENABLEif ( cfg = cfg0 )#if HAL_UART_1_ENABLEif ( cfg1 )cfg = cfg1;else#endifbreak;else#endifbreak; w

    14、hile ( TRUE );#elsereturn;#endif说明:(1)下面我们看一下pollISR()函数static void pollISR( uartCfg_t *cfg )/计算rxBuf中还有多少数据没有读出(以字节为单位) if ( !(cfg-flag & UART_CFG_RXF) )/这里是针对流控制的,如果又有新的数据接收到了那么就要重置超时时间(超时时间由睡眠定时器来控制),而且需要把已经读出的数据数目减去!/ If anything received, reset the Rx idle timer. /当接收缓存超过安全界限的时候停止RX流*/if ( cfg-

    15、rxCnt = (cfg-rxMax - SAFE_RX_MIN) )RX_STOP_FLOW( cfg );#endifpollISR()函数主要作用就是设置rxTick和rxCn,/关于安全界限,在程序中有下面一段: * after asserting flow control, but before the transmitter has obeyedit.* At the max expected baud rate of 115.2k, 16 bytes will only take1.3 msecs,* but at the min expected baud rate of 38

    16、.4k, they could take 4.2msecs.* SAFE_RX_MIN and DMA_RX_DLY must both be consistentaccording to* the min & max expected baud rate.*/如果声明了流控制,为保证数据的正确接收需要在RX缓存区中预留出足够的空间。CC2430可以使用的最大串口波特率为115.2k。这个安全界限的数字跟使用的波特率还有串口tick有关。具体参考Z-STACK问题之串口结构uartCfg_t乱说文章。可以看到,在初始化时rxHead=rxTail=0,如果发生接收中断,在中断服务函数中把U0D

    17、BUF寄存器中的数据传送到rxbuf中,这时rxHead和rxTail的值不在相等,其中,rxHead是rxBuf接收到数据的个数,rxTail是rxBuf移出的数据个数,再根据两者的差值,判断具体的事件evt。然后,根据evt和设置的回调函数,通过cfg-rxCB调用相应的回调函数。代码也是体显在下面一句。cfg-rxCB( (cfg-flag & UART_CFG_U1F)!=0), evt );第一个参数主要是判断,是UART1还是UART0.第二个参数是触发的事件类型,那个个回调函数,具体是指向函数呢?首先,我们在void SerialApp_Init( uint8 task_id )

    18、初始化函数中,对串口进行了配置,其中下面两句中有关于回调函数的。#elseuartConfig.callBackFunc = rxCB;#endifHalUARTOpen (SERIAL_APP_PORT, &uartConfig);其中,在HalUARTOpen()函数中,有下面的一条语句,uint8 HalUARTOpen( uint8 port, halUARTCfg_t *config )cfg-rxCB = config-callBackFunc;也就是调用下面的rxCB函数。程序中定义了两个串口接收缓冲区:otaBuf上otaBuf2.当otaBuf中无数据时,处于空闲状态时,由o

    19、taBuf接收串口数据;当otaBuf中保留有数据时,下等待接收节点发送接收数据响应或由于某些正在重新给接收节点发送数据时,可通过otaBuf2接收数据,当otaBuf和otaBuf2都没有处于空闲状态时,说明数据没有及时发送给接收节点,发生了数据累积,缓冲区被占用,需要进行流量控制,所以直接退出接收回调函数,暂不接收数据。static void rxCB( uint8 port, uint8 event )uint8 *buf, len;/* While awaiting retries/response, only buffer 1 next buffer:otaBuf2.* If all

    20、ow the DMA Rx to continue to run, allocating Rx buffers, theap * When the Rx data available is not read, the DMA Rx Machineautomatically* sets flow control off - it is automatically re-enabled upon Rx dataread.* When the back-logged otaBuf2 is sent OTA, an Rx data read isscheduled.*/if ( otaBuf2 )/缓

    21、冲区被占用return;if ( !(buf = osal_mem_alloc( SERIAL_APP_RX_CNT ) )return;/* HAL UART Manager will turn flow control back on if it can afterread.* Reserve 1 byte for the sequence number.这里的SERIAL_APP_RX_CNT为80这里为什么是80,上篇文章中也有分析*/len = HalUARTRead( port, buf+1, SERIAL_APP_RX_CNT-1 );if ( !len )/ Length is

    22、 not expected to ever be zero.osal_mem_free( buf );return;/* If the local global otaBuf is in use, then either the responsehandshake* is being awaited or retries are being attempted. When thewait/retries* process has been exhausted, the next OTA msg will be attemptedfrom* otaBuf2, if it is not NULL.

    23、 otaBuf正在使用,则就使用otaBuf2*/if ( otaBuf )/otaBuf正在被占用otaBuf2 = buf;/otaBuf2接收数据otaLen2 = len;elseotaBuf = buf;/otaBuf接收数据otaLen = len;/* Dont call SerialApp_SendData() from here in the callbackfunction.* Set the event so SerialApp_SendData() runs during this taskstime slot.产生发送数据事件*/osal_set_event( Ser

    24、ialApp_TaskID,SERIALAPP_MSG_SEND_EVT );#endif在事件处理函数中,有下面的判断。UINT16 SerialApp_ProcessEvent( uint8 task_id, UINT16 events )if ( events & SERIALAPP_MSG_SEND_EVT )SerialApp_SendData( otaBuf, otaLen );/return ( events SERIALAPP_MSG_SEND_EVT );下面是SerialApp_SendData()函数的源代码,调用AF_DataRequest(),通过OTA发送数据。由于

    25、在数据包之前增加了序列号SerialApp_SeqTx,多次重发的数据不会被接收节点重复发送到串口。static void SerialApp_SendData( uint8 *buf, uint8 len )afStatus_t stat;/ Pre-pend sequence number to the start of the Rx buffer.*buf = +SerialApp_SeqTx;otaBuf = buf;otaLen = len+1;stat = AF_DataRequest( &SerialApp_DstAddr,(endPointDesc_t *)&SerialApp

    26、_epDesc,SERIALAPP_CLUSTERID1,otaLen, otaBuf,&SerialApp_MsgID, 0, AF_DEFAULT_RADIUS );if ( (stat = afStatus_SUCCESS) | (stat = afStatus_MEM_FAIL) )/在设定的时间内没有发送成功,则重新发送。osal_start_timerEx( SerialApp_TaskID,SERIALAPP_MSG_RTRY_EVT,SERIALAPP_MSG_RTRY_TIMEOUT );rtryCnt = SERIALAPP_MAX_RETRIES;elseFREE_OTA

    27、BUF();/重发的次数 uint8 stat;uint8 seqnb;uint8 delay;switch ( pkt-clusterId )/ A message with a serial data block to be transmitted on the serialport./接收节点收到的接收数据命令,case SERIALAPP_CLUSTERID1:seqnb = pkt-cmd.Data0;/ Keep message if not a repeat packetif ( (seqnb SerialApp_SeqRx) |/ Normal(seqnb 0x80) ) /W

    28、rap-around/ Transmit the data on the serial port.接收到的发送到串口if ( HalUARTWrite( SERIAL_APP_PORT, pkt-cmd.Data+1, SerialApp_SeqRx = seqnb;stat = OTA_SUCCESS;elsestat = OTA_SER_BUSY;elsestat = OTA_DUP_MSG;/ Select approiate OTA flow-control delay.delay = (stat = OTA_SER_BUSY) ? SERIALAPP_NAK_DELAY :SERIA

    29、LAPP_ACK_DELAY;/ Build & send OTA response message.发送响应消息rspBuf0 = stat;rspBuf1 = seqnb;rspBuf2 = LO_UINT16( delay );rspBuf3 = HI_UINT16( delay );/发送接收数据响应命令stat = AF_DataRequest( &(pkt-srcAddr),(endPointDesc_t*)&SerialApp_epDesc,SERIALAPP_CLUSTERID2,SERIAL_APP_RSP_CNT ,rspBuf,&SerialApp_MsgID, 0,AF

    30、_DEFAULT_RADIUS );if ( stat != afStatus_SUCCESS )osal_start_timerEx( SerialApp_TaskID,SERIALAPP_RSP_RTRY_EVT,SERIALAPP_RSP_RTRY_TIMEOUT );/ Store the address for the timeout retry.存储发送超时的,目的地址osal_memcpy(&SerialApp_RspDstAddr, &(pkt-srcAddr),sizeof( afAddrType_t );break;/ A response to a received serial data block.接收到接收数据响应命令case SERIALAPP_CLUSTERID2:if ( (pkt-cmd.Data1 = SerialApp_SeqTx) &(pkt-cmd.Data0 =


    注意事项

    本文(ZStack中串口发送接收的流程.docx)为本站会员主动上传,冰点文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰点文库(点击联系客服),我们立即给予删除!

    温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




    关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

    copyright@ 2008-2023 冰点文库 网站版权所有

    经营许可证编号:鄂ICP备19020893号-2


    收起
    展开