1.14.1. Serial(串口)总线介绍
Serial(串口)是单片机或者说嵌入式中使用最多、最简单的串行通讯接口,没有之一。
在同一Serial(串口)的协议层下,物理层有TTL电平、RS232电平、RS485电平等标准。也就是说协议层一样,但物理层有好几种。这里暂且不去管具体的电平逻辑,因协议层一样,那控制程序就可以采用同样的逻辑。
一般情况下,TTL电平用于单片机之间通讯,RS232电平是老PC机与单片机之间通讯的常用手段(现在PC机多采用USB转TTL电平串口与单片机直接通讯,教程中开发板将USB转TTL电平串口放在开发板上,就是用这种方式),RS485用于工业控制。
串口有25线制、9线制,最简单的是3线制,也是目前最常用的,物理连接如下图所示:
注意:发送端Tx与接受端Rx连接,发送端Rx与接受端Tx连接。
1.14.2. 程序设计
在前面的例程中,串口助手或putty中打印的信息实际上是通过串口完成的,也就是说micropython将数据流重新定向到串口,所以在micropython中可以通过print函数直接调用串口功能,但单片机没有办法针对性处理串口数据,这种模式成为Repl,即交互环境。Micropython默认使用Esp32的usart0做为交互环境。
Esp32共有uart0、uart1、uart2三个串口,micropython的Repl占用串口0,另有uart1、uart2可用,默认的端口如下:
要完整使用串口(接、发),micropython模式下有专门操作串口的模块,接下来的测试使用usart2模块(对应硬件接口Tx2、Tx2),如下:
1.14.3. 指定IO口
当串口使用的默认IO口被占用时,可以在初始化时指定新的IO口,如esp32-wroom-32中uart1的默认端口9/10用于spiflash,那么系统中一定要使用uart1可以指定IO口为18/19,如下所示:
1.14.4. 嵌入式热敏打印机
1.14.4.1. 介绍
采用串口通讯的嵌入式打印机非常多,技术相对成熟,配置后通过串口(TTL或RS233)向打印机输出数据,打印机自动处理并打印串口中的数据(字符串形式)。如下图是蚂蚁(东莞)科技发展有限公司推出的AG58C微型热敏打印机。
根据官方资料,接口如下:
1.14.4.2. 接线
给打印机供电(按说明书,注意功率),并按上节串口(Rx=18/Tx=19)连接打印机和单片机(注意:直连需选择TTL电平接口的打印机)。
1.14.4.3. 测试代码
1 from machine import UART 2 from time import sleep 3 4 ser = UART(1,baudrate=115200,rx=18,tx=19) 5 6 while True: 7 ser.write("hello world") 8 sleep(1)
下载到单片机并重启,可以看到打印机每1S打印一行”hello world”。
1.14.5. RFID模块
1.14.5.1.
介绍
图中是一款RFID模块,淘宝上搜索RFID模块可以找到很多(大同小异),选择TTL电平的任意模块购买(一般情况下买模块送卡)。
购买模块后,厂家提供资料(包括测试代码、API,工具等),如图中代码的资料包中包括PC端测试软件、单片机例程、c++ Api、通讯协议等。借助这些资料,可以很方便的在单片机系统中集成RFID模块,如图PC端测试软件:
使用模块读写IC卡,必须注意以下事项:
a. 一般IC卡有64个扇区、每个扇区有4个块、每个块可以存储16个字节(块是存储数据的最小单元)。
b. 写0块很容易失败,慎用;
c. 每个扇区的最后一个块(如3、7、11块)用作加密码,不可存储数据(误操作可能造成IC卡锁死)。
1.14.5.2. 接线
给RFID模块供电(3.3V或5.0V,电流约15mA),并按上节串口(Rx=18/Tx=19)连接打印机和单片机(注意:直连需选择TTL电平接口的打印机)。
1.14.5.3. 测试代码
使用USB转串口连接RDIF模块和PC机(注意TX-RX、RX-TX)配置IC卡的工作模式“自动读卡号->自动上传数据”,如下图:
将IC卡拿开,再次接近RFID模块,IC卡会自动上传卡号。
接下来按上节内容连接单片机和RFID模块,上传如下代码到单片机,重启单片机,当IC卡接近RFID模块时,系统自动打印接受到的IC卡号。
Main.py文件
1 from rfid import RFID 2 from time import sleep 3 4 module = RFID() 5 6 while True: 7 ic_type,ic_number = module.waitMsg() 8 if(ic_type): 9 print("Valid card(type:"+ic_type+";number:"+ic_number+")") 10 sleep(1)
Rfid.py模块
1 from machine import UART 2 from time import sleep 3 4 class RFID: 5 def __init__(self,port=1,baudrate=115200,rx=18,tx=19): 6 self.port = UART(port,baudrate=baudrate,rx=rx,tx=tx) 7 8 def waitMsg(self): 9 dat = [] 10 if(self.port.any()): 11 sleep(0.1) 12 moreBytes = self.port.any() 13 if moreBytes: 14 dat = self.port.read() 15 return("{:02x}{:02x}".format(dat[5],dat[6]),\ 16 "{:02x}{:02x}{:02x}{:02x}".format(dat[7],dat[8],dat[9],dat[10])) 17 return(False,0)
注意:这里仅实现了自动检测IC卡号功能,实际RFID模块功能远不止这些。
1.14.5.4. 无帧头帧尾不定长数据串口接受
串口通讯,一般情况下是按帧(特点的字节组合)处理,帧的组织形式称为串口通讯协议(逻辑协议,注意与串口物理协议区分)。
串口通讯协议有三种主要形式:
a. 固定帧长
固定帧长,最容易实现。但是帧长以实际命令中最长的为准,比如一个模块有10个命令帧,命令帧长度最短的位5,最长的为20,那么命令帧需要设置为20,这就造成总线浪费,总线使用率低。
b. 特定的帧头、帧尾
需要设置特定的帧头(如0xef)、帧尾(如0xff 0xff),上、下位机根据帧头、帧尾判断帧起始、结束,实现起来相对简单一点。但帧头帧尾会占用固定的数据,总线中不能传输和帧头、帧尾一样的数据(否则可能误判造成帧提前结束),比如帧头0xef、帧尾0xff 0xff情况下,数据中不允许出现0xef、0xff(一般将数据为拆分位0x80+dat&0x80),这也降低总线中数据有效位
c. 不固定帧头、帧尾、帧长
帧头、帧尾、帧长均不固定,总线得到充分利用,但上、下位机判断帧起始、结束较麻烦
RFID卡的通讯协议属于不固定帧头、帧尾、帧长的第三种模式。帧头、帧尾没有特定标识,且帧长不定的情况下,系统如何判断接受到的数据并进行处理呢?
这就用到串口实例的接受缓存,micropython串口有256bytes的接受缓存(其它实现方式也有缓存,如pyserial的缓存为4096bytes),物理接口接受到数据后填充到缓存中,等待系统读取(FIFO模式)。串口(baudrate=115200)在0.1S内能传输的数据总量,而一般情况下帧长不会超过50bytes,那么理论上讲,检测到缓存中有数据时再延时0.1s读缓存,就一定可以得到完整的数据帧(串口传输数据时连续的)。Micropython的uart实例,可以通过any函数判断缓存中是否有数据,参考实现如下:
dat = [] if(self.com.any()): sleep(0.1) moreBytes = self.port.any() if moreBytes: dat = self.port.read()
注意:micropython官网提醒“即使缓存区有多个数据,any函数依然有可能返回1”,如下:
----*----*----*----*----*----*----*----*----*----*----*----
史久超
email:shijiuchao1983@163.com
tel:15999550975 微信同号
qq:157185173 经常不在线,尽量微信
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具