STM32与上位机串口通讯的学习笔记(简明的数据帧设计方法)

最近因为项目需要,需要做一个STM32和Windows的串口通讯协议来交换数据,本着追求极致的心态,来讨论一下简明的数据帧的设计方法。

数据的传输方式

对于很多单片机初学者而言,可能他们接触到串口 首先想到的就是通过串口打印字符串,然后就会很理所当然的想到了用“打印”的方式来传输数据。
比如我们需要传输一个float型的数据value,可能小白们首先会想到的方式就是串口重定向printf然后像下面这样把数据传输过去

printf("%f",&value);

但是实际上,对于程序之间的交流,使用字符串打印这样的方式是非常浪费传输数据的,因为假设这个浮点数据为1234.567占了8个字符(小数点也占一位) 所以用字符串传输的方式就需要通过串口传输8个字节,但是实际上float类型在内存里面永远都是占用4个字节,所以使用字符串的传输效率是非常低的,并且这样传输 上位机收到的也是字符串,还得把字符串的数据读出来重新放到一个float类型的数据里面,才可以进行运算。

因此,通过串口传输的数据基本上都是通过直接传输内存数据来实现的。
它的原理大概是这样 同样以float类型作例子
当你在程序里面声明了一个float类型的变量的时候,程序会为这个变量开辟一个4字节的内存空间,然后这4个字节的内存数据唯一决定了这个float类型的数据(具体实现方式可以百度float类型的存储方式)。因此,我们的串口只要把这4个字节的数据通过串口传输到上位机,然后上位机根据传输协议直接把这4个字节写入到一个float类型的内存空间中,然后这个float类型的数据也就随之完成了。
为了方便这个过程的实现 我们可以定义一个联合体

typedef union{
	float value;
	unsigned char sendbuf[4];
}send_type;

这样定义的好处就是:联合体内的所有成员共用一片内存空间
然后我们需要传输数据float型数据的时候,我们只需要声明一个send_type类型,然后对send_type的value直接赋值,然后与此同时sendbuf的数据也会因此改变,我们就可以直接发送sendbuf[4]这四个字节了。建议在上位机的程序里面也使用同样的联合体,然后当上位机的snedbuf[4]放入接收的4个字节之后,value就可以直接读出所需要的数据了。然后对于其他各种数据类型,如double,long int之类的类型同样也可以使用这种方式来传输,只需要注意好各种数据类型需要占用的内存空间就可以了

组合数据的传输方式的注意事项

通过上面的方式,我们通过传输内存数据的方式来传输单个数据了,那么当我们需要传输多个数据呢?
或者说,传输的并不是直接的数据,而是带有一定的开头,结尾的数据,假如协议规定数据起始要先发一个字节的标志0x0d,然后传输两个float型数据,再以结束标识符0x0d结尾
(此处0x0d是人为规定,协议可以要求为其他值)
这时候只考虑联合体的话并不能解决我们的问题
这时候结构体就派上用场了

typedef struct{
unsigned char   head;
float	 		send1;
float	 		sned2;
unsigned char	end;
}sned_frame;

像这样我们就可以按照顺序把协议整合成一个结构体的形式,编译器会根据结构体内成员顺序在内存里按顺序分配内存空间,上位机和单片机共用同一种结构体形式,然后只需要设定好帧内各成员内容之后,把结构体直接发过去,好像就可以了??

其实问题并没有想的这么简单。结构体虽然会占用一片连续的内存空间,但是实际上结构体内的成员并不一定是连续分配内存空间的。可以实践,刚刚声明的结构体,它并不是只占用1+4+4+1=10个字节的内存空间。为什么会这样呢?因为编译器在分配内存时会按照内存对齐的方式来分配内存,因此前面的unsigned char变量为了和float对齐,编译器为其分配了4个字节的空间。这会导致我们协议的帧长度增加一些没有意义的空的数据,并且判断帧长度将变得复杂
(当然,其实如果上位机和stm32的内存对齐的方式恰好是一样的话,只要保证把整个结构体传输过去,整个通信应该还是可以完成的)
那么如何取消编译器的内存自动对齐呢?
我们可以在结构体定义后紧跟一句
attribute ((packed))

这一句的意义是将该定义的内存分配强行按最小位对齐(也就是按字节对齐)。
那么我们修改后的结构体定义是这样的:

typedef struct{
unsigned char   head;
float	 		send1;
float	 		sned2;
unsigned char	end;
}_attribute__ ((__packed__)) sned_frame;

可以实践,对现在的结构体使用sizeof关键字,得到的的长度为10。这样就可以压缩帧的长度,避免数据浪费了。在需要改动协议的时候,也只需要简单的增加结构体的成员即可。
/-----------------------------------------------------------------------------------------------------------
2018年6月4日11:26:30后记:

在STM32的开发中,如果使用了硬件浮点数解算的话,同时又存在串口发送浮点型数据的话,此时最好不要压缩数据帧,按照编译器的自动补充空字节来发送,上位机也保持一样的数据包.因为硬件浮点解算涉及到了内部的专用电路,而此时如果浮点数没有内存对齐的话是无法使用硬件解算从而出现错误的.这时候会带来不必要的麻烦. 当然 如果需要和性能受限制的设备进行通信,不舍得填充空数据的话,在涉及内存不对齐的浮点数据可以先开一个临时变量进行操作,在进行发送的前一刻使用memcpy函数将浮点数放进数据帧内也是可以的

  • 6
    点赞
  • 116
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
### 回答1: STM32与上位之间的串口通信可以实现数据的双向传输和交互。通过串口通信,STM32可以与上位进行数据的发送和接收,实现双向通信。 首先,在STM32中,我们可以使用USART模块进行串口通信。使用HAL库提供的相关函数,我们可以轻松地配置串口通信的波特率、数据位、停止位、奇偶校验等参数。通过将数据写入USART的发送缓冲区,STM32可以向上位发送要传输的数据。同时,STM32可以通过中断或轮询的方式监测USART的接收缓冲区,从而实现对上位发送的数据进行接收。 而在上位方面,我们可以使用串口助手等软件,通过选择对应的串口号和波特率,与STM32进行通信。通过向串口发送数据,上位可以将数据传输给STM32。同时,通过监听串口的接收缓冲区,上位可以获取STM32发送的数据。 在数据传输过程中,需要注意数据的格式和协议的制定。可以定义一种简单的数据帧格式,如起始字节、数据字节、校验字节等,以确保数据的正确传输和解析。 除了基本的数据传输,串口通信还可以实现更复杂的功能,如传输文件、调试程序等。通过定义不同的指令或协议,可以实现更多的功能需求。 总结起来,STM32与上位串口通信可以实现双向的数据传输和交互。通过合理配置和处理串口相关参数和中断,可以实现稳定、可靠的通信。同时,需要定义明确的数据格式和协议,以确保数据的正确传输。 ### 回答2: 将STM32与上位实现串口互通可以使用串口通信协议来进行数据的传输。一般情况下,STM32与上位都会使用UART串口作为物理层连接。下面是一个简单的步骤来实现串口通信: 1. 配置STM32的串口:首先,需要在STM32的微控制器上配置串口的通信参数,如波特率、数据位、停止位等。可以使用STM32的开发环境(如Keil、STM32CubeIDE等)对串口进行配置,或者使用STM32 HAL库来设置串口参数。 2. 编写STM32的串口接收与发送代码:接下来,需要编写STM32的代码来实现串口数据的接收和发送。使用适当的函数来接收和发送数据,并设置相应的中断使能,以便在接收到数据或发送完成时触发中断。 3. 配置上位串口:同样地,需要在上位串口设置中配置相同的通信参数,以确保STM32和上位串口参数一致。 4. 编写上位串口通信代码:在上位上,可以使用相应的编程语言(如C/C++、Python等)来编写串口通信代码。打开相应的串口设备,并按照串口通信协议来发送和接收数据。 5. 通过串口进行数据传输:将STM32与上位连接并上电,然后运行上位串口通信代码。通过串口发送数据STM32,STM32在接收到数据时会触发中断并进行数据处理。同样地,STM32可以通过串口数据发送给上位,上位在接收到数据时进行相应的处理。 总结:通过上述步骤,我们可以实现STM32与上位串口互通。在实际应用中,可以根据具体需求设计相应的串口通信协议,以满足数据传输的要求。同时,需要根据硬件资源和性能来选择合适的串口通信参数,以确保稳定可靠地进行数据传输。 ### 回答3: stm32与上位进行串口互传输可以通过以下步骤来实现。 首先,需要在stm32上配置串口通信的参数,包括波特率、数据位、停止位和校验位等。可以使用stm32提供的库函数来实现串口的初始化和配置。 接下来,在stm32的代码中,可以使用串口发送函数将需要传输的数据发送给上位。可以使用库函数中提供的发送函数,将数据按指定格式发送出去。同时,还可以通过库函数提供的接收函数,接收上位发送过来的数据。 在上位的代码中,同样需要进行串口的初始化配置。可以使用上位串口库或者相关函数来实现。 通过上位的代码,可以发送数据stm32。通过发送函数将需要传输的数据发送给stm32,然后,在stm32的代码中,通过接收函数来接收上位发送过来的数据。 需要注意的是,在进行串口通信时,需要保持stm32和上位串口参数一致,包括波特率、数据位、停止位和校验位等。如果这些参数不一致,可能会导致数据传输错误。 此外,还需要合理设计数据包的格式,以便stm32和上位能够正确地解析数据。可以通过定义固定长度的数据包,或者使用特定的标志符来标识数据包的开始和结束。 总的来说,stm32与上位串口互传输需要配置串口参数、使用发送和接收函数以及合理设计数据包格式来实现数据的传输。通过合作,可以实现双向的串口通信。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值