前言
通信无疑是做项目最常用到的一部分内容,如Openmv、K210、树莓派等经常需要将其检测到的目标物体的坐标发送给单片机去处理,本文将记录几种最常见、最基础的通信方法。
数据类型和编码格式
数据类型
通信前,我们得先对各个数据类型有基础的了解。其中单片机常见的无非是u8/u16/int/float/char/str。通信的时候一定要注意char和str的区别,如’s’是char类型,但“s”确实str类型。两者的区别不止在于单引号和双引号,还有str类型会多出一个’/0’作为结束标志位,所以同样是发一个s,“s”会比‘s’多出一个字节。
编码格式
编码格式种类就很多了,但是单片机常用的无非是我们熟悉的ascll码格式,而python则是"uft-8"。两种当然有所区别,但是对于数字、英文的通信,我们可将其视为无区别。
发送单个字符
一、python端发,单片机接收
usart.write('s') #python直接发
u8 temp; //stm32每次只能接收八位,刚好一个字符
temp=USART_ReceiveData(USART1); //stm32直接接收
二、单片机发,python端收
USART_SendData(USART1,'s') //直接发
recieve=usart.read().decode("utf-8") #接收需要解码为“utf-8"格式
发送单个整形
一、将int拆分成4个u8类型的数据
int temp; #定义一个整形变量
unsigned char rec[4],i;
for(i=0;i<4;i++)
{
rec[i]=temp>>(i*8);
}
二、python端发,单片机接收
send1=5
send2=bytearray(rec[0],rec[1],rec[2],rec[3])
usart.write(send2)
字节数组顾名思义,每一个变量只有一个字节,而int拥有四个字节,所以得拆开来发。
三、单片机端接收
int temp;
for(i=0;i<4;i++)
{
temp=USART_ReceiveData(USART1); //这里以USART1为例
temp<<=(i*8);
}
由于串口每次也只能收一个字节,所以我们不妨连续接收四次,然后通过移位又重新组合成一个int型。**但,现实不建议这样操作,有加上帧头标识符和帧尾标识符才能够确保收到数据的准确率。**后面我会讲更好的办法,这里只是提供一个理论思路而已。
int的发送的时候会被压缩成u8类型,所以如果你发的数据在0~255之间,其实直接发和直接收就可以了,不必搞的如此麻烦。
发送字符+数字
一、python端发,单片机接收
int temp; #定义一个整形变量
unsigned char rec[4],i;
for(i=0;i<4;i++)
{
rec[i]=temp>>(i*8);
}
send2=bytearray(0x99,'a',rec[0],rec[1],rec[2],rec[3],'b') #发送了0x99,'a',5,'b'
usart.write(send2)
有了字节数组,你要发多少,发什么类型都不在话下。为了使数据能够准确的传输,这里用了0x99做为帧头,帧头帧尾各位自行发挥。
u8 temp[7]; //接收所有字节
int num; //存储接收的整形
temp[0]==USART_ReceiveData(USART1);
if(temp[0]==0x99) //判断帧头
{
for(i=1;i<=6;i++)
{
temp[i]=USART_ReceiveData(USART1);
}
}
for(i=2;i<=5;i++) //字节数组中的第二个到第五个字节是属于int的
{
num=temp[i];
num<<=(i*8);
}
总结
相信看到这里,你们依旧没办法直接把我代码copy过去。但我已经提供了一个发送接收的思路了,具体如何用,需要各位加以理解后再发挥你们的智慧了。
避坑
1、python字符、字符串只能用decode(解码),不能用encode编码。decode(“utf-8”)意为将其他编码格式(如ascll)发送过来的字符、字符串转化为python看得懂的"utf-8"格式。
如果还一知半解,可以去了解一下编码格式,和数据类型的区别。
2、串口的发送永远一次只能发一个字节,所以无论是你打包一起发,还是一个一个发,效果都是一样的。
3、int压缩成u8的时候,只取低八位,所以int转化成u8的时候,用要右移。