肝 | 一种串口高效收发思路及方案
内容提要
本文介绍了如何利用FIFO串口减少接收中断次数,提高系统响应速度。通过自定义通讯协议和帧打包方法,以及特殊的串口数据发送方式,减少中断次数,提高数据发送效率。同时,介绍了利用定时器中断和硬件FIFO进行数据发送,减少CPU资源浪费。
延伸解读
硬件FIFO的触发机制与中断优化
文章指出,串口FIFO在数据达到触发值(如8或14字节)或超时(3.5个字符时间)时才产生接收中断,从而大幅减少中断次数。以LPC1778为例,通过设置UART FIFO控制寄存器即可调整触发级别。这种机制适合数据量较大的场景,但需注意不同芯片的FIFO深度和触发值可能不同,使用前应查阅数据手册。
自定义协议帧的打包与校验
文章设计了一种包含帧首、地址号、命令号、长度、数据和CRC16校验的协议帧,并提供了基于状态机的打包函数。该函数能处理帧首识别、长度计算和缓存溢出保护。这种打包方式将数据组织成完整帧后再交上层处理,提高了协议解析的可靠性。但帧长度限制在256字节以内,且校验方式可选,实际应用需根据需求调整。
定时器中断驱动发送的适用条件
文章提出利用定时器中断和硬件发送FIFO来发送数据,避免等待发送浪费CPU,也不增加发送中断源。但该方法并非通用:若应用未开启定时器中断,或定时器间隔较长而波特率很高,则不适合。文章举例,在1200bps、2400bps下,定时器间隔10ms以内即可;若间隔1ms以内,可支持115200bps。因此,需根据实际波特率和定时器配置权衡。
RS485方向控制的实现细节
在发送数据前,需将RS485设置为发送模式,发送完成后切回接收模式。文章提供的发送函数在定时器中断中检查发送标志,并操作RS485方向控制引脚。由于涉及具体硬件寄存器,代码与硬件密切相关,但思想通用。开发者需根据自身硬件调整宏定义和寄存器操作,确保方向切换时机正确,避免总线冲突。
Q&A
传统串口数据收发存在哪些主要问题?
传统串口数据收发存在三个主要问题:1. 每接收一个字节数据都会触发一次接收中断,不能充分利用串口硬件FIFO,无法减少中断次数;2. 采用等待发送方式时,由于串行数据传输速度远低于CPU处理速度,等待发送完当前字节再发送下一个字节会造成CPU资源浪费;3. 采用中断发送方式虽然避免了等待发送的CPU资源浪费,但增加了系统的中断次数,可能影响系统整体的稳定性。
串口FIFO是如何减少接收中断次数的?
串口FIFO是串口专用的先进先出缓存。接收到的数据首先放入接收FIFO中,当FIFO中的数据达到触发值(通常为1、2、4、8、14字节),或者虽未达到设定值但一段时间内没有再接收到新数据(通常为3.5个字符传输时间),才通知CPU产生接收中断。这样,当接收到大量数据时,每8个或14个字节才会产生一次中断,相比每接收一个字节就产生一次中断,接收中断次数大大减少。
如何设置串口FIFO的触发级别?
以NXP的lpc1778芯片为例,接收FIFO的触发级别可以设置为1、2、4、8、14字节,推荐使用8字节或者14字节,这也是PC串口接收FIFO的默认值。设置方法很简单,只需要设置UART FIFO控制寄存器UnFCR即可。具体数据和特性会因硬件和CPU类型而有所不同,使用时应参考相应的数据手册。
自定义通讯协议帧的格式是怎样的?
自定义协议帧格式包括:帧首(通常是3~5个0xFF或者0xEE)、地址号(1字节,要进行通讯的设备的地址编号)、命令号(1字节,对应不同的功能)、长度(1字节,数据区域的字节个数)、数据(与具体的命令号有关,数据区长度可以为0,整个帧的长度不应超过256字节)、校验(异或和校验1字节或者CRC16校验2字节,本例使用CRC16校验)。
如何利用定时器中断和硬件FIFO进行串口数据发送?
主要思想是:定时器中断触发后,判断是否有数据要发送,如果有数据要发送并且满足发送条件,则将数据放入发送FIFO中(对于lpc1778,一次最多可以放16字节数据),之后硬件会自动启动发送,无需CPU参与。具体实现需要定义串口帧发送结构体,编写定时处理函数,在定时器中断中调用该函数,并在需要发送数据的地方设置发送结构体变量。这种方法不会造成CPU资源浪费,也不会多增加中断源和中断事件。
利用定时器中断发送串口数据有哪些适用限制?
该方法并不是对所有应用都合适。对于那些没有开定时器中断的应用,本方法当然是不支持的。另外,如果定时器中断间隔较长而通讯波特率又特别高的话,本方法也不太适用。公司目前使用的通讯波特率一般比较小(1200bps、2400bps),在这些波特率下,定时器间隔为10ms以下(含10ms)就能满足。如果定时器间隔为1ms以下(含1ms),是可以使用115200bps的。