1、首先进行库的调用
import sensor, image, time
from pyb import UART
import json
2、进行UART的初始化定义
uart = UART(3,3000000,timeout_char=1000) #定义串口3变量
uart.init(3000000, bits=8, parity=None, stop=1) # init with given parameters
3、定义发送数据帧的函数
def send_data(x,a):
global uart
data =ustruct.pack("<bbhhb",
0x2c,
0x12,
int(x),
int(a),
0x5b
)
uart.write(data)
注意项:
①global函数的作用为使自定义的函数可以改变全局变量的值
②ustruct.pack(fmt,v1,v2,..)函数的作用为根据格式字符串fmt,打包 v1, v2, … 值。返回值为一个解码该值的字节对象
其中对应数据格式有以下情况:(首位符号表示格式声明符号,最后一位表示字节数)
x pad byte no value 1
c char string of length 1 1
b signed char integer 1
B unsigned char integer 1
? _Bool bool 1
h short integer 2
H unsigned short integer 2
i int integer 4
I unsigned int integer or long 4
l long integer 4
L unsigned long long 4
q long long long 8
Q unsigned long long long 8
f float float 4
d double float 8
s char[] string 1
p char[] string 1
P void * long
例如在上面发送程序可以看见依次为b对应0x2c,b对应0x12,h对应int(x),h对应int(a),b对应0x5b。
当接收端进行数据接收时,一字节数据可以直接进行接收显示,但是两字节的数据需要进行处理,需要先明白发送数据时是先发送数据的高位还是数据的地位,然后根据此对接收到的高位数据进行移位操作移动至高位在与低位数据进行相加即可。
例如我用STM32进行接收,当接收到来自openmv端发送来的h型数据,将数据存放至自己定义的Serial_RxPacket[]数组缓冲区中的第一位和第二位则进行如下操作(已经假定先被接收的为数据的低位),方可获得想要的数据。
data = ((Serial_RxPacket[1]<<8)+Serial_RxPacket[0])
③uart.write(data)函数的作用为将data数据进行串口发送
4、定义接收数据帧的函数
state=0 #状态标识
rx_buff=[0]*2 #数据接收缓存区
id_tixu=0x0000 #定义ID号接收缓存区
def read_data():
global id_tixu;
global state;
if uart.any(): #进行串口数据的接收
#res=uart.read(1) #表示为读取一个十六进制数,这里的uart必须是例化的
#state表示处理接收到的第几位数据
for i in range(5):
if state == 0:
res=uart.read(1)
res = ustruct.unpack("B", res) #表示将res数据按照B格式进行解包
res = hex(res)
data = res[0:4]
if data == '0x2c': #帧头1
state = 1
elif state == 1:
res=uart.read(1)
res = ustruct.unpack("B", res)
res = hex(res)
for i in range(4):
data = res[0:4]
id_tixu=data
#print(id_tixu)
state = 2
elif state == 2:
res=uart.read(2)
res = ustruct.unpack("B", res)
res = hex(res)
res = int(res)
rx_buff[0]=res #数据1
#print(res)
state = 3
elif state == 3:
#res=uart.read(1)
res=uart.read(2)
res = ustruct.unpack("B", res)
res = hex(res) #str
res = int(res)
rx_buff[1]=res #数据2
#print(res)
state = 4
elif state == 4:
res=uart.read(1)
res = ustruct.unpack("B", res)
res = hex(res)
data = res[0:4]
if data == '0x5b': #帧尾
state = 0
#数据处理处
#print(rx_buff)
else:
state = 0
上述代码采用的是状态机的思维方式进行数据帧的接收与解析。
①uart.any()返回等待的字节数量,表示接收到了数据
②uart.read(n)表示读取了n个字节的数据,1就表示读取了一个字节,2就表示读取了两个字节
③ustruct.unpack(fmt,data)表示根据格式字符串 fmt 对数据进行解压。返回值为一个解压值元组。
④对数据解压后就可以进行数据的处理。res = hex(res)表示将res数据转换成hex形式,即16进制的形式。数据帧已经接收完毕,对于数据的处理方式不再过多进行阐述。
5、关于函数的调用
可以用下面的代码自行参悟
while(True):
clock.tick()
img = sensor.snapshot()
read_data()
send_da(1,55,11)
print(id_tixu)
print(rx_buff)
6、关于数据发送接收异常的处理办法
①首先检查UART的初始化设置,例如波特率等是否设置正确
②检查硬件串口接线是否连接正确,是否有共地
③使用串口模块与串口助手进行数据链路层的数据上的发送与接收,查看是否数据发送和接收有异常,若无异常显示不正确的数据,则可能是数据处理逻辑代码有问题,若异常则可能是①、②的原因,可以仔细检查,当然也有可能是时钟晶振本身存在的误差导致,若如此可以采取换一个高精度符合要求的晶振。
④若以上原因都不符合还是会出现异常数据,可能是电气特性导致,可以用示波器或者逻辑分析仪检查传输信息是波形及电平的多少,发送端和接收端电平是否一致,若不一致可以参考RS232或者RS485协议。