在调试一个stm32串口通信时,下位机设置好的发送方式采用串口助手接收后已经可以正常离线解包。但是由于需要实时解包并存储,因此写了一个实时解包存储的上位机,通信正常后接收的数据一直有误。经过单步调试,发现单片机发送的数据帧是字符串,并不是16进制数,而在线解包程序直接是对16进制数进行处理的,这就导致的比如16进制的数0xAA(170),下位机发送的是“AA"(字符串),上位机处理的16进制数是41 41(10进制为65*100+65)。查询‘A’的ASCII码可知,‘A’的ASCII码对应的10进制数为65,16进制数为41,也就是说上位机把接收到的16进制字符串当16进制数处理了,所以出错。
解决方法两个,一个是修改下位机发送方式,将其改为发送“16进制数”,而不是“16进制字符串“;另一个是修改上位机接收方式,收到后将”16进制字符串“先转换为”16进制数“。多次尝试后发现还是修改下位机发送方式较为简单,且比较实用,因为大部分下位机串口发送协议发送的是16进制数。
下面是在stm32中进行两种数据发送的具体方法:
一、发送16进制字符
例如我们要发送一个32位的数:uint32_t temp_send;
发送方式如下,将32位的16进制数转换为8个对应的字符分别输出,例如:0xF0123456,将发送“F0123456”字符串:
- [cpp] view plain copy
- uint32_t temp_send;
- //主函数
- int main(void)
- {
- while(1)
- {
- UART4_Putc_Hex(0xAA);//帧头
- UART4_Putdw_Hex(temp_send);
- }
- }
- //子函数
- /**************************实现函数********************************************
- *函数原型: void UART4_Putdw_Hex(uint32_t dw)
- *功 能: RS232以十六进制ASCII码的方式发送32位的数据.
- 如:0xF0123456 将发送 " F0123456 "
- *输入参数:uint32_t dw 要发送的32位数据值
- *输出参数:没有
- *******************************************************************************/
- void UART4_Putdw_Hex(uint32_t dw)
- {
- UART4_Putw_Hex((uint16_t) (dw >> 16));
- UART4_Putw_Hex((uint16_t) (dw & 0xffff));
- }
- /**************************实现函数********************************************
- *函数原型: void UART4_Putw_Hex(uint16_t w)
- *功 能: RS232以十六进制ASCII码的方式发送一个字的数据.就是发送一个int
- 如:0x3456 将发送 " 3456 "
- *输入参数:uint16_t w 要发送的字
- *输出参数:没有
- *******************************************************************************/
- void UART4_Putw_Hex(uint16_t w)
- {
- //发送高八位数据,当成一个字节发送
- UART4_Putc_Hex((uint8_t) (w >> 8));
- //发送低八位数据,当成一个字节发送
- UART4_Putc_Hex((uint8_t) (w & 0xff));
- }
- /**************************实现函数********************************************
- *函数原型: void UART4_Putc_Hex(uint8_t b)
- *功 能: RS232以十六进制ASCII码的方式发送一个字节数据
- 先将目标字节数据高4位转成ASCCII ,发送,再将低4位转成ASCII发送
- 如:0xF2 将发送 " F2 "
- *输入参数: uint8_t b 要发送的字节
- *输出参数: 没有
- *******************************************************************************/
- void UART4_Putc_Hex(uint8_t b)
- {
- /* 判断目标字节的高4位是否小于10 */
- if((b >> 4) < 0x0a)
- UART4_Put_Char((b >> 4) + '0'); //小于10 ,则相应发送0-9的ASCII
- else
- UART4_Put_Char((b >> 4) - 0x0a + 'A'); //大于等于10 则相应发送 A-F
-
- /* 判断目标字节的低4位 是否小于10*/
- if((b & 0x0f) < 0x0a)
- UART4_Put_Char((b & 0x0f) + '0');//小于10 ,则相应发送0-9的ASCII
- else
- UART4_Put_Char((b & 0x0f) - 0x0a + 'A');//大于等于10 则相应发送 A-F
- // UART4_Put_Char(' '); //发送一个空格,以区分开两个字节
- }
- /**************************实现函数********************************************
- *函数原型: void UART4_Put_Char(unsigned char DataToSend)
- *功 能: RS232发送一个字节
- *输入参数:unsigned char DataToSend 要发送的字节数据
- *输出参数:没有
- *******************************************************************************/
- void UART4_Put_Char(unsigned char DataToSend)
- {
- TxBuffer[count++] = DataToSend;
- USART_ITConfig(UART4, USART_IT_TXE, ENABLE);
- }
复制代码
二、发送16进制数
发送方式如下,需要先将32位的数移位分割为4个字节(1个字节8位)的8位数分别发送,例如:0xF0123456,将发送F0 12 34 56(4个16进制数):
- [cpp] view plain copy
- uint32_t temp_send;
- char ByteSend[5]={0};//发送的字节
- uint i;
- //主函数
- int main(void)
- {
- while(1)
- {
- ByteSend[0] = 0xAA;//帧头,ByteSend的类型为uchar或char均可
- ByteSend[1] = (temp_send>>24) & 0xFF;//
- ByteSend[2] = (temp_send>>16) & 0xFF;
- ByteSend[3] = (temp_send>>8) & 0xFF;
- ByteSend[4] = temp_send & 0xFF;
- for(i=0;i<5;i++)
- {
- UART4_Put_Char(ByteSend[i]);
- }
- }
-
- }
- //子函数
- /**************************实现函数********************************************
- *函数原型: void UART4_Put_Char(unsigned char DataToSend)
- *功 能: RS232发送一个字节
- 输入参数:
- unsigned char DataToSend 要发送的字节数据
- 输出参数:没有
- *******************************************************************************/
- void UART4_Put_Char(unsigned char DataToSend)
- {
- TxBuffer[count++] = DataToSend;
- USART_ITConfig(UART4, USART_IT_TXE, ENABLE);
- }
- [html] view plain copy
- <pre class="html" name="code"></pre>
- <pre></pre>
复制代码
|