STM32串口通信——16进制数形式

一.为什么采用16进制数形式?

首先,需要解释一下串口发送的数据都是unsigned char类型的,说成字符和16进制形式,只是我们采用何种方式展示这些数据。字符形式就是把16进制数通过ASCII表一个一个转成字符的。

一开始接触到的串口程序,就是字符形式的,尤其是STM32中被重构的printf()函数,我就先入为主地选择了字符形式。这样比较人性化,因为啥数据都是平时看到的字符,很直观,但是大大降低了通信效率!比如要发送一个数85,字符形式需要发送’8’+‘5’,而16进制只需要发送0x55。还有一点是负数,字符形式多加了一个’-'号,16进制直接发送有符号数就行了。如果要传输大量的数据,应该采用16进制形式。

我在调试STM32与PC(采用Python3编写)串口通信过程中,二者之间需要发送各种类型的数据,uint_8、int16_t、float等等,要将所有类型的数据转换成uint_8类型发送,同时上位机要能转换回来。总之就是拆开发送,接收重组

二.下位机

  1. uint_8 型
    发送:直接利用USART_SendData函数,通常配合检测发送结束位使用,如下:
void usart1_send_data(uint8_t num){
	USART_SendData(USART1, num);
	while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
}

接收:很简单,直接赋值即可。

  1. int16_t型
    发送:int16_t型涉及到补码,但是可以留到上位机解决,只要分别发送高低8位数就可以。
void send_int16_t(int16_t num){
	uint8_t high_8, low_8;
	low_8 = num & 0x00FF;
	high_8 = (num>>8) & 0x00FF;
	usart1_send_data(high_8);
	usart1_send_data(low_8);
}

接收:定义一个int16_t类型的数,将接收到高低八位分别移位即可,贴的代码中的LOW和HIGH变量只是一个例子,参考这个代码改就行。

int16_t temp = 0;
temp |= (int16_t)LOW[4]&0x00FF;
temp |= ((int16_t)HIGH<<8)&0xFF00;
  1. float型
    发送:虽然float型比较复杂,但是由于我用到的数都比较小,而且精度不高,所以可以把float分整数、小数发送出去。如果需要发送大数,可以把下面代码中的interger和decimal改成16位类型。
void send_float(float num){
	uint8_t integer, decimal;  // 限制在uint8_t型
	integer = (uint8_t)num;
	decimal = (uint8_t)(( num-(uint8_t)num )*100); // 取两位小数
	usart1_send_data(integer);
	usart1_send_data(decimal);
}

接收:定义一个float型数,将小数部分*100加上整数部分即可,如下:

float num_f;
num_f = interger + decimal/100.0f;

三.上位机(Python)

  1. uint8_t型
    发送:比如要发送16进制的23(10进制35),直接通过pyserial的write函数,发送b"\x23"或者bytes([35])。
ser.write(b"\x23")  // ser.write(bytes([35]))

接收:调用pyserial的read读取的bytes型,直接取数即可,例如:

response = ser.read(1)
num = response[0]
  1. int16_t型
    发送:由于要考虑补码问题,但是可以通过ctypes的c_short(16位有符号整型)解决,不需要自己从补码解到原码,如下:
_num = c_short(num)
high_8 = (_num.value & 0xff00)>>8
low_8 = _num.value & 0x00ff
ser.write(bytes([high_8, low_8]))

接收:

num = c_short(0)
num.value |= high_8 << 8
num.value |= low_8
  1. float型
    发送:和下位机一样,分开发送整数和小数即可,如下:
my_byte = bytes([int(num_f), int(100 * (num_f - int(num_f)))])
ser_write(my_byte)

接收:同下位机,如下:

num_f = round(interger + decimal[2]/100, 1)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章