就是最近忙着做项目,忽然发现有3个项目都需要用到串口调试,这让我感觉到有一个方便快捷的调试工具是非常重要的。虽然类似的功能有很多现成的、功能强大的开源协议,比如MODBUS。但是我看过之后,总觉得不够简单。能理解那些功能概念的应该都不算是小白了,而我的目标是做出一个小白都会用的简单串口调试协议。于是在多个项目的压力下,我推出了FUR调试系统!
FUR全名Fast UART write/read Register,意思是快速串口读写寄存器。定位就是使用电脑和串口助手去调试单片机参数。因此FUR在参考MODBUS的“寄存器”概念后,又对其进行了极大的精简:
- 根据FUR的定位,规定了其通信协议是一对一通信,因此精简掉器件地址。
- 因为读寄存器和写寄存器有更直观的表达,所以精简掉了功能码。
- 因为主要用于电脑调试单片机参数,有人来参与调试过程,所以删掉CRC部分(后期应用于批量生产或其他无人看管的场景时,会加上校验部分)。
最后通信协议只保留了“寄存器地址”和“寄存器内容”两个关键参数。然后为了让我们能一眼看懂协议内容,设定了协议的格式为“[寄存器地址]=数值.”,你没有看错,就是这么简单。只要你看过一遍实例,就会立马明白。在举例之前,我们要了解到FUR调试系统的“寄存器”概念。从定义来说,FUR的寄存器就是一个u16型的数组而已。其元素的个数由宏定义ECBM_FUR_MAX决定,设定的范围是2~256个。也就是最大支持256*16位(512字节)数据。因为寄存器0存放了波特率,寄存器1是触发寄存器,所以最少得安排2个寄存器。
由于它就是个普通的数组,所以我们还需要把寄存器和要调试的功能联系上才行。比如我上周收到反馈,说delay_ms函数不准。那么我就需要对delay_ms函数进行调试。有了FUR系统,就很简单了,核心只有一句delay_ms(fur_reg[2]);这样就把FUR的寄存器2和delay_ms联系上了。联系上了之后,我只要用串口修改寄存器2的值,就可以调整延时的时间了。下面我们来看实例:
#include
编译,下载,上逻辑分析仪。
效果不错,非常非常接近50ms。看看STC-ISP的频率调节看看,果然这次下载调得很准。
接下来就是调试动作了,在往常我需要修改代码重新编译下载才能换参数。但是现在我只需要打开串口,发送字符就好了。先确认一下 ,发送个“[2]=?.”。按刚才的定义,这个就是查看寄存器2的意思。
串口助手返回50,确实是我们设置的值。接下来换成一个值试试。发送“[2]=233.”意思就是将数值233赋值给寄存器2。发送成功的话,单片机也会返回该寄存器的当前值。用于人眼验证本次传输是否成功。所以我发送233,单片机返回233,说明这次是传输成功了的。
结果是这样的。
如果是改成150的话:
多来几个试试:
可以看到如果延时比较短的话,就比较准。延时比较长的话就不准。这也确实说得通,因为延时是靠循环+空指令。每一次循环差一点时间,循环多了累计的误差就多了。这个误差就是没法消掉的。另外一个误差是STC单片机下载时调整RC的误差,同样的板子在下载之后即有可能是24.000MHz,也有可能是23.962MHz。如果是23.962MHz的话,即使延时时间短也有较大的误差。所以延时函数的误差来自方方面面。真要准确无误还是靠晶振+定时器。
那么,FUR系统如何搭建呢?首先确保ECBM库的版本在V2.1.5-2及以上。因为V2.1.5-2更新第一版的FUR系统。因为最近在不断的使用和改良中,写本文的时候已经更新到第二版(但还未发布,因为要跟着ECBM库的更新节奏)了。所以如果你拿到的库里面的FUR函数和本文演示的函数有不同之处,属于正常现象。更新到最新版即可。
首先,在KEIL工程的DEVICE文件夹里添加fast_uart_reg.c,该文件存放在device文件夹中。
接下来打开fast_uart_reg.h,进入图形化界面。这里可以设置寄存器的总数,搭载的串口号和保存功能使能。
- 寄存器总数根据实际需要来设定,设置为需求数量+2。比如上面的例子只调试了延时函数,那么设置成3就行。
- 搭载串口号,因为我的板子是串口1通过USB转串口连到电脑,所以我设置成串口1。可根据实际情况设置到其他串口。
- 保存功能是一个特色,由于大部分STC单片机都有内部eeprom,所以使能该功能就能让你设置的参数能够掉电保存。
如果要使用保存功能,请打开eeprom库的使能,同时确保单片机型号设置无误。如果是eeprom空间可调的型号,还需要注意“EEPROM选择”那里数值是实际的eeprom大小。
FUR库一共也就3个函数,将这3个函数放置在指定位置即可。
初始化函数fur_init肯定是放在while死循环前,确认和反馈的fur_check函数是要时时执行的,放在while死循环里。
而接收串口数据的fur_in函数自然就是放在串口的接收回调函数中。当然不要忘了在uart.h中使能串口接收回调函数。这样一来,FUR系统就搭建好了。
FUR的常规功能说完了,细心的朋友因为还记得上文说道寄存器0和寄存器1都已经被占用了。那么是用于什么功能呢?
- 寄存器0用于存放串口通信的波特率的百分之一值。也就是说波特率是9600的话,寄存器0里就是96。同理115200波特率下,里面的值就是1152。可以使用“[0]=96.”或“[0]=48.”来快速修改波特率。注意波特率修改是即时生效的。
- 寄存器1是触发寄存器,也就是说无论你写什么值,都不会写进寄存器1里面去。但是会根据你发送的值来触发各种效果:
- 发送“[1]=0xA55A.”是将当前fur_reg数组保存到EEPROM中,也就是保存当前的寄存器值。比如在设置波特率后保存,可以让单片机以后都用新的波特率工作。否则每次上电都会以设置成默认波特率。但要注意保存是保存所有寄存器的。
- 发送“[1]=0xF00F.”是从EEPROM读取值替换将当前的fur_reg数组,也就是读取之前保存的寄存器值。比如你在设置某个寄存器的值之后,觉得效果还不如原来的好,就可以用这个恢复原来的设置。但要注意恢复的话也是恢复所有寄存器的。
- 触发寄存器还有更多的玩法等待更新,尽情期待~~~