历史上的今天
今天是:2025年07月27日(星期日)
2019年07月27日 | stm32串口发送16进制字符和16进制数的区别和具体实现方法
2019-07-27 来源:eefocus
在调试一个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进制数。
关于发送”16进制数“和”16进制字符“这两种数据发送方式原理的不同之处可见这篇文章http://blog.csdn.net/yibu_refresh/article/details/22695063。
下面是在stm32中进行两种数据发送的具体方法:
一、发送16进制字符
例如我们要发送一个32位的数:uint32_t temp_send;
发送方式如下,将32位的16进制数转换为8个对应的字符分别输出,例如:0xF0123456,将发送“F0123456”字符串:
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进制数):
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);
}
史海拾趣
|
我们现在在做循线小车,需要用到激光传感器来判断黑线的位置。发射管用得是红色激光。 1. 不过接收管就不知道用什么了。 网上看到很多接收管的功率都很大,我们的电源只有7.2V的电池,而且还要用8个接收管,不知道有没有小功率的接收管呢?最好 ...… 查看全部问答> |
|
寻求做过机床控制软件的人一起合作,兼职也可以!要求做个机床控制软件,特别是激光切割机器类软件的```` 有意者联系QQ:183273519 或者hefei_cn@163.com 2010.6.20… 查看全部问答> |
|
请问这里为什么要除256,取模,谢谢大家 TH0=(65536-46080)/256; TL0=(65536-46080)%256; //定义定时器初值 以下是全部代码 #include #define uchar unsigned char uchar count; //全局变量 void time0() interrupt 1 using 0 //定时器0 { ...… 查看全部问答> |
|
有问题想请教一下各位老大,是关于工控方面的-------NPM(PCD4521) 我正在做有关工业控制的项目,但我是一个新人,那个项目要用到PCD4521,可是我还不会用那个IC,所以想问一下有谁可以帮忙的,谢谢大家!… 查看全部问答> |
|
SofTecFlashRunnerproductionprogrammerforSTR7andST7 http://mcu.st.com/mcu/modules.php?name=Content&pa=showpage&pid=97我们很高兴地告诉您,浦洛电子正在热销一款来自SofTec Microsystems的新一代ISP万用量产型烧录器---FlashRunner.该款产品除了延续Softec一惯推崇的高速、稳定、灵活等 ...… 查看全部问答> |




