




已阅读5页,还剩2页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
typedef structuint8 *rxBuf;/接收缓存uint8 rxHead;/头uint8 rxTail;/尾uint8 rxMax;/接收最大长度uint8 rxCnt;/计数uint8 rxTick;/时间uint8 rxHigh;/高位uint8 *txBuf;#if HAL_UART_BIG_TX_BUFuint16 txHead;uint16 txTail;uint16 txMax;uint16 txCnt;#elseuint8 txHead;uint8 txTail;uint8 txMax;uint8 txCnt;#endifuint8 txTick;uint8 flag;/标志位halUARTCBack_t rxCB; uartCfg_t;有个朋友问我上面的问题,说句老实话,我可是第一次见这个东东,拿到手之后比我那朋友还迷糊,那位朋友至少还知道大概是什么功能,仅仅是不清楚每个参数的具体含义和功能。为了解决这个问题,我可是遍寻名家,最终结果是人家也不是很清楚,因为平常大家只管用,哪管那么多这些具体细节?没办法,我只有自己解决了,希望我的努力能给大家一点点启示!首先说说这个结构的应用范畴,它是直接面向串口的应用层,也就是与客户接触的还是比较紧密的一个结构,一般是在串口接收数据和发送数据的时候使用。而串口有两种方式,一种是普通的串口,一种是DMA方式。这里我只针对普通串口来分析这个结构。首先来看看这个结构在什么地方用到了?static void pollDMA( uartCfg_t *cfg )static void pollISR( uartCfg_t *cfg )这两个函数直接就用到了这个结构作为参数,应该说是联系最紧密的了,是我们重点剖析的对象了,但是这里不看DMA,因为这个俺很外行-哈哈!uint16 HalUARTRead( uint8 port, uint8 *buf, uint16 len )uint8 HalUARTOpen( uint8 port, halUARTCfg_t *config )void HalUARTClose( uint8 port )void HalUARTPoll( void )uint16 Hal_UART_RxBufLen( uint8 port )uint16 HalUARTWrite( uint8 port, uint8 *buf, uint16 len )这几个函数都在其中定义了这个结构的变量在使用,所以我们也需要关注。可以看出,这个结构与串口的应用,也就是数据的接收和发送有关,而与串口的初始化灯没有关系。所以这里排除串口初始化的任何可能。还要来关系两个全局变量的定义:#if HAL_UART_0_ENABLEstatic uartCfg_t *cfg0;#endif#if HAL_UART_1_ENABLEstatic uartCfg_t *cfg1;#endif可以看出,串口0对应变量cfg0,串口1对应变量cfg1。这两个变量的变化使我们关注的重点,因为只要了解其变化过程和使用方法,基本上就能摸清每个参数的意义了。为了更明确每个参数的意思,所以一个个来分析。这个是逆向解决问题的方法,正向思维就是先把每个函数都看完看明白,自然也就知道了。但是我哪有那能耐和功夫?所以就偷懒从后面出发!1、uint8 *rxBuf;/接收缓存这个参数我觉得没必要太多解释,就是串口接收缓存。直观理解就是串口接收放数据的地方,体现这个含义最明显的地方就是串口接收函数了:cfg-rxBuf = osal_mem_alloc( cfg-rxMax+1 );这里是在打开串口函数中的语句,就是为接收缓存分配存储空间。osal_mem_free( cfg-rxBuf );这个函数是在关闭串口函数中,就是释放存储空间。HAL_ISR_FUNCTION( halUart0RxIsr, URX0_VECTOR )cfg0-rxBufcfg0-rxHead = U0DBUF;if ( cfg0-rxHead = cfg0-rxMax ) cfg0-rxHead = 0;else cfg0-rxHead+;这个是串口0中断函数:其中cfg0-rxBufcfg0-rxHead = U0DBUF,显然是把U0DBUF中的数据转移到存储区去。从这个函数中还能看出两个问题:rxHead是否用作了串口接收计数,而rxMax代表最大的接收数据长度。2、uint8 rxHead字面理解为接收头,但是上面已经提到了似乎起到了串口接收计数的功能。那下面就来看看它到底有什么意义。cfg-rxHead = cfg-rxTail = 0;在打开串口中有这么赋值,把它初始化为0.其实从上面那个中断函数就已经把这个参数的功能体现的淋漓尽致了:就是串口接收数据,这个参数始终指向像一个参数被存放到rxBuf的位置。因为硬件串口缓存器U0DBUF只能存放一个字节,如果不及时把这个接收到的转移出去,那么就会被下一个到来的字节覆盖掉,所以rxHead变量就指向了这个存放的地址,当然是基于定义的rxBuf存储空间。相当于一个数组赋值,那么必然有个变量会指向该数组的下一个赋值的参数,当然这个变量的最终值也能在一定程度上体现这个被赋值数组的大小。所以rxHead在这里起到了类似的作用,而if ( cfg0-rxHead = cfg0-rxMax )这一句判断也说明的很清楚,一旦这个计数达到了定义的最大接收数量,也就是说已经把rxBuf存储空间占满了,那么就不能在继续存放了,否则存放的位置就未知,而且有可能造成程序中其他变量的损坏,那么这个时候如果串口还有数据怎么办?那就需要把rxBuf清空在接收了,否则就会丢失数据。3、uint8 rxTail;这个变量就与上面提到的清空rxBuf密切相关了。while ( (cfg-rxTail != cfg-rxHead) & (cnt rxBufcfg-rxTail; if ( cfg-rxTail = cfg-rxMax ) cfg-rxTail = 0; else cfg-rxTail+; cnt+;这里是在uint16 HalUARTRead( uint8 port, uint8 *buf, uint16 len )函数中调用的,实际上把rxBuf空间的数据读走,然后rxBuf可以继续串口数据的接收了。可以看到*buf+ = cfg-rxBufcfg-rxTail这个是在转移数据,而转移多少的计数是以rxTail来计数的。一旦计数达到rxMax,那么该计数归0,因为rxMax定义了rxBuf的最大的数据量。这里需要强调一点:rxTail和rxHead的区别。我第一眼看到这个两个变量的反应是:rxHead为串口数据串接收的头,而rxTail为串口数据串接收的尾(结束),因为这样理解符合我们平常编写串口通信协议习惯,有头有尾。但是仔细看了只有,虽然也是头与尾的概念,但是却不应该这么理解。rxTail和rxHead应该是针对rxBuf来说的。rxHead是往rxBuf装数据的计数,而rxTail是从rxBuf取走数据的计数。希望这个一定要注意。所以我们就不难理解:rxHead是在串口接收中断的时候强调使用,而rxTail是在HalUARTRead函数中使用了。这里还需要注意一点点,HalUARTRead并不是读取UxBUF数据,而是读取rxBuf中数据。其实仔细想想,这两个参数还是与串口的头和尾有关的。头又名开始,串口接收数据开始存放数据的指向;尾又名结束,是把串口数据取走用作他用的指向。rxHead=0,标示串口接收数据新的起点,新的开始;而rxTail=0,标示把串口接收到的数据全部取走用作他用,-结束。体现了串口数据从接收到被使用的整个过程。4、uint8 rxMax;/接收最大长度这个我想没必要多做解释,这里只看看它究竟有多大,因为这个量的赋值非常隐蔽,俺找了好久才功夫不负有心人!首先在打开串口第函数中有:cfg-rxMax = config-rx.maxBufSize;其次在void SPIMgr_Init ()函数中有:uartConfig.rx.maxBufSize = SPI_MGR_DEFAULT_MAX_RX_BUFF;在次有如下定义:#define SPI_MGR_DEFAULT_MAX_RX_BUFF SPI_RX_BUFF_MAX最后才找到其最终的东西:#define SPI_RX_BUFF_MAX 128还是藏的很隐蔽就是了,呵呵!关于这个128我是做个实验的,在串口互发的实验也是定义的128.多了就会丢掉!这个下次有机会在说。5、uint8 rxCnt ;static void pollISR( uartCfg_t *cfg )uint8 cnt = UART_RX_AVAIL( cfg );if ( !(cfg-flag & UART_CFG_RXF) ) / If anything received, reset the Rx idle timer. if ( cfg-rxCnt != cnt ) cfg-rxTick = HAL_UART_RX_IDLE; cfg-rxCnt = cnt; /* It is necessary to stop Rx flow in advance of a full Rx buffer because * bytes can keep coming while sending H/W fifo flushes. */ if ( cfg-rxCnt = (cfg-rxMax - SAFE_RX_MIN) ) RX_STOP_FLOW( cfg ); 就这个函数使用这个参数最典型了。关心的第一句不if ( cfg-rxCnt != cnt )一开始就与cnt变量有关系,而且更加过分的是在里面直接cfg-rxCnt = cnt,所以不得不关系下cnt了。uint8 cnt = UART_RX_AVAIL( cfg );这个函数的第一句,而:#define UART_RX_AVAIL( cfg ) ( (cfg-rxHead = cfg-rxTail) ? (cfg-rxHead - cfg-rxTail) : (cfg-rxMax - cfg-rxTail + cfg-rxHead +1 ) )我的理解是UART_RX_AVAIL是指明串口缓存区rxBuf还剩多少有用的数据,也就是没有被取走的数据。首先从字面理解avail为“效用”的意思,那么扩展下为available,那么意思就是“有用的”“有空的”,呵呵!只有理解其实也很有意思哈。再从后面的判断语句,cfg-rxHead - cfg-rxTail,由于有上面的讲解,理解这个就很容易了,有的数据数量-已经取走的数据数量,那么就省还有多少各有用的数据量。而cfg-rxMax - cfg-rxTail + cfg-rxHead +1理解就需要转个弯了,因为此时cfg-rxHead cfg-rxTail,那么什么情况下才满足这种条件呢,只有一种情况,rxHead已经是第二轮接收计数了,而rxTail还在上一轮取数。cfg-rxMax - cfg-rxTail,也就是第一轮把rxBuf填满的数据取走cfg-rxTail,那么就是第一轮剩下又有的数据,那么在+ cfg-rxHead这个,就是加上cfg-rxHead第二轮接收的数据,至于后面+1的理解为cfg-rxBuf = osal_mem_alloc( cfg-rxMax+1),分配存储空间本来就比rxMax多分了一个。-这里我仍然有疑惑,谁有深刻的理解欢迎交流!而if ( cfg-rxCnt = (cfg-rxMax - SAFE_RX_MIN) )这里理解就更微妙了,表明接收缓存空间已经满了,所以下面就RX_STOP_FLOW( cfg ); #define RX_STOP_FLOW( cfg ) if ( !(cfg-flag & UART_CFG_U1F) ) RX0_FLOW_OFF; else RX1_FLOW_OFF; if ( cfg-flag & UART_CFG_DMA ) cfg-rxTick = DMA_RX_DLY; cfg-flag |= UART_CFG_RXF; 可以看出通过硬件流控制停止了接收,而置位cfg-flag为UART_CFG_RXF。至于cfg-rxMax - SAFE_RX_MIN的理解才是这里的精妙之处。#define SAFE_RX_MIN 48定义了每次串口操作处理间隔串口最多能接收多少字节数据。因为必须把这个空间预留充足,否则在非处理间隔期间就有可能覆盖以前的数据,关于这个的理解现在还比较困难,我想经过后面的叙述会豁然开朗。6、uint8 rxTick;/时间cfg-rxTick = HAL_UART_RX_IDLE;#define HAL_UART_RX_IDLE (6 * RX_MSECS_TO_TICKS)#define RX_MSECS_TO_TICKS 33所以cfg-rxTick=198,也就是差不多200ms才处理一次pollISR这个函数。这里我可以论证下上面提到的#define SAFE_RX_MIN 48因为CC2430串口波特率为38400bps下,一个字节需要事件约为:4.16ms,那么198/4.16等于47.6,约为48.所以这也就是上面定义这个48的原因。因为 cfg-rxTick定义了多久处理一次串口缓存区,而为了保证串口缓冲区不被新的数据覆盖,那么在这个间隔期间就必须保证大于48字节存储空间空闲。至于这个时间具体涉及到休眠定时器的使用,这个我就不大清楚了。7、uint8 rxHigh;cfg-rxHigh = config-rx.maxBufSize - config-flowControlThreshold;定义了rxHigh的大小。else if ( cfg-rxHigh & (cfg-rxHead = cfg-rxHigh) ) evt = HAL_UART_RX_ABOUT_FULL;指出了,rxHigh的用法,就是一旦接收的数据超过rxHigh就触发HAL_UART_RX_ABOUT_FULL事件。uartConfig.flowControlThreshold = SPI_MGR_DEFAULT_THRESHOLD;#define SPI_MGR_DEFAULT_THRESHOLD SPI_THRESHOLD#define SPI_THRESHOLD 48最终我们可以看到cfg-rxHigh=128-48=80.也就是说只要接收的数据超过80就触发HAL_UART_RX_ABOUT_FULL事件。那么来看看这个事件是干啥用的:if (event & (HAL_UART_RX_FULL | HAL_UART_RX_ABOUT_FULL | HAL_UART_RX_TIMEOUT) while (Hal_UART_RxBufLen(SPI_MGR_DEFAULT_PORT) HalUARTRead (SPI_MGR_DEFAULT_PORT, &ch, 1);.基本上就是说调用HalUARTRe
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年二建《水利水电》练习题及答案解析
- 云南养老护理员考试题库及答案解析
- 2025新版办公室装修合同范本
- 货运从业证考试口语及答案解析
- 保管箱协议书
- 防诈骗安全教育答题题库及答案解析
- 银行初级从业考试选科及答案解析
- 房产中介从业资格考试及答案解析
- 猪肉配送协议书
- 菠萝蜜协议书
- 2025年全国保密教育线上培训知识考试试题库有含答案
- 2025年上海科学考试题目及答案
- 试点先行人工智能+智能客服系统可行性分析
- 兵团面试题目及答案
- 2025-2030中国基建投资拉动下工程机械需求预测与市场分析
- 胰岛素泵专家共识课件
- 电梯自行检测合规指南
- 人教版(2024)八年级上册数学全册教案
- 2025年住院医师规培-新疆-新疆住院医师规培(胸心外科)历年参考题库典型考点含答案解析
- 2025年低压电工证考试题库及答案
- 足球大单元教学计划
评论
0/150
提交评论