-
2020-05-17 11:30:35
最近搞那个SIM800L,需要用到用串口发送十六进制,不想直接用例程的函数,然后就上网瞅瞅有啥别的发送十六进制的方法,从原子的论坛上个找到一个简单的方法——直接对寄存器进行操作。
发送0x1a,不换行,以十六进制发送USART1->DR=0x1a;
更多相关内容 -
STM32单片机发送十六进制数据包例程
2020-03-04 12:45:31单片机发送十六进组数据包例程,例程中未四个十六进制数据一组,可随意添加,MDK语言环境。 -
STM32串口发送16进制数据
2021-05-17 16:23:21//说明:用u8或unsigned char都能正常发送 //示例 1 u8 send1=0x55; printf("%c",send1); //示例 2 unsigned char send2=0x55; printf("%c",send2); 方法二(用固件库) 下面展示两个示例 // An highlighted block ...方法一(用printf函数)
下面演示
两个示例
//说明:用u8或unsigned char都能正常发送 //示例 1 u8 send1=0x55; printf("%c",send1); //示例 2 unsigned char send2=0x55; printf("%c",send2);
方法二(用固件库)
下面演示
两个示例
//说明:用u8或unsigned char都能正常发送 //示例 1 u8 send1=0x55; USART_SendData(USART1,send1); //示例 2 unsigned char send2=0x55; USART_SendData(USART1,send2);
错误的发送方法
下面展示一些
两种错误发送16进制数据的方法
。printf("%x",send1); printf("%d",send1);
这两种发送方式都会导致串口数据异常
总结与建议
建议使用ST官方的固件库来发送16进制数据,就不会存在ASCII码和数据之间存在的乱码情况,例如在比编写发送数组的函数时,就可以用USART_SendData()在自己编写的函数内循环调用
-
STM32串口实验+自定义协议接收16进制数据+发送1个(2个)字符+发送字符串函数.zip
2022-01-03 15:34:53STM32串口使用自定义协议接收一串十六进制数据并进行储存 提取十六进制数据的两个字节转化为十进制数据 发送一个字节函数 发送两个字节函数 发送字符串函数 重定向printf函数 重定向scanf函数 -
STM32F429串口通信程序中十六进制、字符串,格式发送和接收实现
2021-09-27 09:05:06STM32F429串口通信程序中十六进制、字符串,格式发送和接收实现 -
STM32F103ZET6 按键串口 发16进制[字符串 或者数据]
2018-08-21 09:38:12使用STM32F103ZET6芯片,编译器:KEIL5 ARM,代码文件是C语言,通过串口1,发送16进制的数据,或者字符。 -
stm32串口发送16进制字符和16进制数的区别和具体实现方法
2017-08-10 09:53:25经过单步调试,发现单片机发送的数据帧是字符串,并不是16进制数,而在线解包程序直接是对16进制数进行处理的,这就导致的比如16进制的数0xAA(170),下位机发送的是“AA"(字符串),上位机处理的16进制数是41 41...在调试一个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); }
-
STM32串口发送十六进制的数组
2018-07-24 21:43:15通过串口发送十六进制的数组的方法有很多种,这里我介绍一种最简单也最使用的一种方法。 我这里使用的板子是STM32F103RCT6,使用串口2,usart2.c的代码如下: #include "delay.h" #include "usart...通过串口发送十六进制的数组的方法有很多种,这里我介绍一种最简单也最使用的一种方法。
我这里使用的板子是STM32F103RCT6,使用串口2,usart2.c的代码如下:
#include "delay.h" #include "usart2.h" #include "stdarg.h" #include "stdio.h" #include "string.h" #include "timer.h" //串口接受缓存区 u8 USART2_RX_BUF[USART2_MAX_RECV_LEN]; //接受数据缓冲,最大为USART2_MAX_RECV_LEN个字节 u8 USART2_TX_BUF[USART2_MAX_SEND_LEN]; //发送数据缓冲,最大为USART2_MAX_SEND_LEN个字节 //接收到的数据状态,[15]:0,没有接收到数据;1,接收到了一批数据,[14:0]:接收到的数据长度 vu16 USART2_RX_STA=0; void USART2_IRQHandler(void) { u8 res; if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)//接收到数据 { res =USART_ReceiveData(USART2); if((USART2_RX_STA&(1<<15))==0)//接收完的一批数据,若还没有被处理,则不再接收其他数据 { if(USART2_RX_STA<USART2_MAX_RECV_LEN) //还可以接收数据 { TIM_SetCounter(TIM7,0);/计数器清空 if(USART2_RX_STA==0) //使能定时器7的中断 { TIM_Cmd(TIM7,ENABLE);//使能定时器7 } USART2_RX_BUF[USART2_RX_STA++]=res; /记录接收到的值 }else { USART2_RX_STA|=1<<15; //强制标志接收完成 } } } } //初始化IO 、串口2 void usart2_init(u32 bound) { NVIC_InitTypeDef NVIC_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // GPIOA时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE); //串口2时钟使能 USART_DeInit(USART2); //复位串口2 //USART2_TX PA2 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //PA2 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 GPIO_Init(GPIOA, &GPIO_InitStructure); /初始化PA2 //USART2_RX PA3 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入 GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA3 USART_InitStructure.USART_BaudRate = bound;//波特率的值,一般都是设置为9600, USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位的数据格式 USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位 USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //发送和接收模式 USART_Init(USART2, &USART_InitStructure); //初始化串口2 USART_Cmd(USART2, ENABLE); //使能串口 //使能接收中断 USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启中断 //设置中断优先级 NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2 ;//抢占优先级2 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能IRQ通道 NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化NVIC寄存器 TIM7_Int_Init(99,7199); //设置10ms中断 USART2_RX_STA=0; /清零 TIM_Cmd(TIM7,DISABLE); //关闭定时器7 } //串口2的printf函数 //确保一次发送数据不超过USART2_MAX_SEND_LEN个字节 void u2_printf(char* fmt,...) { u16 i,j; va_list ap; va_start(ap,fmt); vsprintf((char*)USART2_TX_BUF,fmt,ap); va_end(ap); i=strlen((const char*)USART2_TX_BUF); //此次发送数据的长度 for(j=0;j<i;j++) //循环发送数据 { while(USART_GetFlagStatus(USART2,USART_FLAG_TC)==RESET); //循环发送,直到发送完毕 USART_SendData(USART2,USART2_TX_BUF[j]); } }
接下来是usart2.h函数
#ifndef __USART3_H #define __USART3_H #include "sys.h" #define USART2_MAX_RECV_LEN 600 //最大接收缓存字节数 #define USART2_MAX_SEND_LEN 600 //最大发送缓存字节数 #define USART2_RX_EN 1 //0,不接收;1,接收 extern u8 USART2_RX_BUF[USART2_MAX_RECV_LEN]; extern u8 USART2_TX_BUF[USART2_MAX_SEND_LEN]; extern vu16 USART2_RX_STA; void usart2_init(u32 bound); void u2_printf(char* fmt,...); void USART2_SendByte(u8 byte); void USART2_SendStr(u8 *s); void USART2_SendArray(u8 send_array[],u8 num); #endif
因为这里还用到了定时器7中断,以下是定时器7 timer.c函数
#include "timer.h" #include "led.h" extern vu16 USART2_RX_STA; void TIM7_IRQHandler(void) { if (TIM_GetITStatus(TIM7, TIM_IT_Update) != RESET) { USART2_RX_STA|=1<<15; TIM_ClearITPendingBit(TIM7, TIM_IT_Update ); TIM_Cmd(TIM7, DISABLE); } } void TIM7_Int_Init(u16 arr,u16 psc) { NVIC_InitTypeDef NVIC_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, ENABLE); TIM_TimeBaseStructure.TIM_Period = arr; TIM_TimeBaseStructure.TIM_Prescaler =psc; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM7, &TIM_TimeBaseStructure); TIM_ITConfig(TIM7,TIM_IT_Update,ENABLE ); TIM_Cmd(TIM7,ENABLE); NVIC_InitStructure.NVIC_IRQChannel = TIM7_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0 ; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); }
timer.h文件就只需要将void TIM7_Int_Init(u16 arr,u16 psc);包含进去进行了。
下面就是最重要的了,就是发送一组十六进制的数组,我这里假设发送{0X00,0X01,0X02,0X03,0X04}这5位数据,那么只需要在主函数的while(1)按下面那样输入就行了:
int main(void) { u8 t=0; delay_init(); //延时函数 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位相应优先级 LED_Init(); //LED初始化 KEY_Init(); //按键初始化 usart2_init(9600);//设置串口2的波特率为9600 while(1) { t=KEY_Scan(0); switch(t) { case KEY0_PRES: USART_SendData(USART2,0X00); USART_ReceiveData(USART2); delay_ms(1); USART_SendData(USART2,0X01); USART_ReceiveData(USART2); delay_ms(1); USART_SendData(USART2,0X02); USART_ReceiveData(USART2); delay_ms(1); USART_SendData(USART2,0X03); USART_ReceiveData(USART2); delay_ms(1); USART_SendData(USART2,0X04); USART_ReceiveData(USART2); delay_ms(1); K0_flag=0; break; case KEY1_PRES: …… break; case WKUP_PRES: …… break; } }
我这里是用按键按下,然后串口2发送数据,上面的代码就是按键K0,串口2发送{0X00,0X01,0X02,0X03,0X04}这一组十六进制数。按键的初始化就不说了。
以上就实现了用串口2发送十六进制数组了,这个方法很简单,因此它也不是最好的发送方法。有其他好的方法还望路过的小哥哥小姐姐给点建议。
-
STM32串口通信——16进制数形式
2020-12-08 23:58:29首先,需要解释一下串口发送的数据都是unsigned char类型的,说成字符和16进制形式,只是我们采用何种方式展示这些数据。字符形式就是把16进制数通过ASCII表一个一个转成字符的。一开始接触到的串口程序,就是字符... -
STM32串口发送16位数组
2021-08-01 13:29:38写这个程序的主要目的就是实现通过STM32的串口1发送十六位数组至上位机。因为正点原子的例程中只能发送单个8位数据至上位机,网上关于这个方面的资料也非常的少,所以,如果有这方面的需求要自己封装函数来达到效果... -
stm32发送16进制的数组总结
2017-08-06 13:47:12关于STM32如何串口输出16进制的数值,然后在串口调试助手上显示,很多人是用printf(“%02x”,A)语句,但是在串口调试助手上显示的是ACSII码,不是我们要的HEX数据,在这里我们用另外一种方法来在这件事情。... -
STM32串口识别字符串和16进制数据
2022-01-23 09:38:55STM32 串口 -
stm32串口自定义协议接收一串十六进制数据(将其中两个字节转化为十进制数据)+部分串口基础知识
2022-01-02 19:11:242、串口自定义协议接收一串十六进制数据进行存储,并将其中的两个字节转化为十进制数据 3、串口助手发送字符控制LED的亮灭 4、发送一个字节函数 5、发送两个字节函数 6、重定向printf和getchar函数 -
STM32F103ZET6的printf重定向后%x输出16进制数的问题
2022-04-11 11:14:40STM32F103ZET6的printf重定向后%x输出16进制数的问题! 在stm32单片机上对printf进行重定向后,出现了打印16进制后,串口调试助手选择16进制显示后,会出现数值多进行一次16进制转换了! 在Codeblock编译环境下编译和... -
stm32串口接收十六进制数,并放进数组遇到的问题
2021-10-11 13:15:23这个问腿以前没遇到过,不知道是什么原因,问题如下: void USART6_IRQHandler(void) { u8 rec_data; if(USART_GetFlagStatus(USART6,USART_FLAG_TC)!=RESET) { rec_data=USART_ReceiveData(USART6);... -
visualGDB开发stm32——16进制转10进制代码
2019-11-30 16:23:33uint32_t Convert_16hex_to_10dec(uint8_t d1, uint8_t d2, uint8_t d3) { uint32_t num; num = d1 * 65536 + d2 * 256 + d3 * 1; return num; } d1,d2,d3是3个字节,从高位到低位。 e.g. 5_000_000 = 0x4C4B40;... -
STM32串口发16位数据
2021-02-07 19:22:45串口是单片机中常常使用的通信接口,通常我们发送的数据是8bit的数据,但是有些时候,需要发送16bit的数据,比如高精度ADC的采样数据,这时候需要高低八位分开传,不能简单的使用官方的原函数,否则会造成高八位的... -
串口收到16进制数据如何转化成10进制整数
2022-05-22 01:27:28我将通过stm32单片机串口接受到的16进制数据存入数组中,现在想将这些数据转换成10进制该怎么操作啊?求一段代码 -
串口调试 stm32 实现串口通信,可以直接运行,适合初学者,带有帧头帧尾的读取。
2019-07-24 13:51:21stm32 实现串口通信,可以直接运行,适合初学者,带有帧头帧尾的读取。 -
STM32开发基础知识——串口数据的收发基础
2021-12-21 21:07:31stm32学习笔记(物联网) -
STM32串口小考核 上位机发数转为16进制.rar
2021-08-12 12:46:30串口考核: 波特率要求:115200 内容要求:电脑上位机发送0-65535内任意数值,stm32返回该数值以及其十六进制表示,不能返回其他任何内容 例如:发送4000,返回4000,fa0 -
串口发送16进制数据函数.zip
2021-06-24 13:37:57stm32f103,串口发送16进制数据函数 -
C语言数字ASCII转换成16进制互转.c
2021-11-11 15:51:44/*int “5264”转换成 “0x52 0x64 ”*/ /*16进制“0x5264” 转换成 int “5264” */ 上位机 串口通信 -
stm32+nbiot 数字装字符串 数字转16进制 源码分享
2018-10-18 01:04:27AT+NMGS=8,32332E3136332E30 接下来这个8为的16进制的数据 应该是发送出去的信息然后再串口打印出来把 可以看到温湿度的情况 这里温湿度只能精确到整数的1 ,精度太差了 估计是dht11模块太菜了 接下来... -
python3串口通信——16进制数
2020-12-07 13:07:37python3串口通信——16进制数在调试STM32与PC进行串口通信时,二者之间需要发送各种类型的数据,如uint_8、int16_t、float等等,需要将所有类型的数据转换成uint_8类型发送,同时上位机要能转换回来。一.下位机uint_... -
STM32 串口中断 接收K210板子发送的ASCII码整数 转换为 多位整形数据
2021-05-17 08:19:24下面的代码K210发送的是一个不大于三位数的ASCII码数据,使用STM32串口中断服务函数进行接收并进行转化为int型。 void X_USART_IRQHandler(void) { uint8_t xieding=0; ```c if(USART_GetITStatus(X_USART,USART... -
stm32的串口接收字符串以十六进制数
2016-11-10 22:51:00串口接收字符串的原理和接收单字符的差不多,只是在接收的时候定义的缓冲区是一个数组,将接受到的数据存放到数组中,在从数组中读出想要的十六进制数在主程序中调用。 以上的主函数中定义个几个数组 uint8_t ... -
关于串口发送十六进制的问题
2015-12-13 00:50:24串口就发送字符串和hex...那么怎么会是1010呢,1010是10啊,他把A当成十六进制的数看了?那么发送的时候怎么看是十六进制的还是字符的呢 -
STM32 HAL库串口收发数据
2021-11-21 21:45:08STM32 HAL库串口收发数据 许多传感器的使用方法是:单片机给传感器发送一帧数据,然后传感器返回单片机一帧有用数据,所以串口的收发功能十分重要。 STM32cubeMX的配置 时钟和下载方式就不讲了 串口配置,因为要接收... -
STM32串口中断接收(HAL库)
2018-09-10 20:18:10简介:STM32与上位机之间用通信协议(自己定义)进行串口通信。怎么判断上位机发过来的指令是正确的,而不是一串乱码?怎么从正确的指令中提取出想要的命令代号,从而实现想要的功能? 方法:读取上位机发来的命令,...