基于STM32F103单片机的时间同步项目

一、前言

本项目为前一个时间同步项目的更迭版本,由于之前的G031开发板没有外部晶振,从机守时能力几乎没有,5秒以上不同步从机时间就开始飞了。在考虑成本选型后,选择了带有外部有缘晶振的STM32F103C8T6最小单片机,来作为本次项目的开发平台。

G031时间同步链接:

基于STM32G031LORA开发板的时间同步项目-CSDN博客https://blog.csdn.net/plmm__/article/details/136646460?spm=1001.2014.3001.5501 之前的物联网模块采用EByte的LORA模块,由于是串口控制与数据发送,波特率最高115200,对于发送数据有时间延迟,虽然在双向校时中可以计算在内,但除去一个干扰因素总是好的。

新的设备改用2.4G模块,接口为SPI,通信速率最大10M,能提高效率,再加上模块的地址扩展性,从机设备的数量可以大大提升。

二、主体框架

1、使用设备

本项目采用一主六从的实验环境,用逻辑分析仪抓取心跳灯的闪烁时间戳,从而获取每个设备间的相对时间间隔:

2、代码结构

相较于前一份工程,我尽可能的根据自己的理解,将驱动层和应用层分离,减少代码的耦合性,提高移植能力和复用性,尽可能作为一个模板工程,可以后续开发其他项目。

所有与硬件无关的应用层代码都由Time_SYNC.c文件调用与实现,主要是时间同步的主体逻辑与各个外设间的联动,具体代码可看gitee仓库。

其他驱动文件对应的调用函数,例如定时器中断溢出,外部中断,串口中断等,我通过宏定义的形式,在驱动对应的头文件中提供用户接口,将函数实现主体抽象到应用层函数中来:

TIM.h头文件:

TIM.c驱动:

Time_SYNC.c文件的实现:

宏定义是c的一大杀器,我本人很喜欢用,能显著提高代码的可阅读性,同时又不更改代码的执行逻辑。

3、时间同步原理

1.时基

每个设备都有一个时基定时器,精度为1us,也就是定时器每加1,时间加1us。

装载值设为1000,溢出中断为1ms计时,在溢出中断中将变量Time_Base加一,因此一个设备的本地时间轴就由两部分组成,小时间定时器计数值,单位us;大时间Time_Base变量,单位ms。所以在数据包中,就要同时读取和发送两个值。

与前一个项目的定时器级联不同,本次采用变量来作为第二级时间,一是方便调试,可以轻松查看变量的值,二是提高时间读取速度,比读定时器的寄存器应该要更快。

__IO就是volatile关键字,由HAL库封装。

2.主机轮询请求

主机通过100ms定时器,也即是上一节图中TIM3,超时则向一个从机发起同步请求,调用函数Single_Send_TIM_Callback,对从机号进行处理和保存,从机的同步为顺序逐个进行。从机号的处理放到请求开始前,是为了保持任意从机掉线,主机也能继续处理下一个从机。

设置本次从机号后,调用发送函数:

数据包内容如上图,带有两个时间和从机号,以及标志位。

3.从机接收做出应答

从机接收到数据后会做对时间数据进行保留,并立即做出回应,回应内容为自定格式,只需要确保从机号和标志位正确:

4.主机接收应答发送第二次时间

主机收到从机应答后,再次获取本地时间,立即发送至从机:

5.从机接收到第二次时间

至此,一次交互结束。

此时从机有两个主机发送的时间,两个时间的差值,便是主机第一次发送,到收到从机应答的时间,除2后便是单向传输耗时。这个过程需要尽量保持主机发送和从机发送的时间相同,因此传输的数据长度要保持一致。

对时间的差值我放到了最后集中处理。

6.计算均值

对于同一个从机,将同步过程连续进行10次,若从机收到有效数据大于6个,则进入数据计算函数:

这里的关中断原本是关闭所有,时基定时器也关闭,但是因为计算过程中如果有不规范数据,会放弃本次同步,所以本地时间轴就会偏移本次的计算时长。为了防止此问题,最后只关闭了外部中断。

Slave_Data_Process函数是时间同步的关键步骤,这部分是由从机自身来计算,主机不去干扰。上一个项目是主机对每个从机的时间偏移计算后下发至从机,会拖慢主机的执行效率。

这部分代码较长,主要作用就是将10次得到的数据做差值,并对边界问题做处理,最后将所有计算耗时记录下来,在得出时间差后补偿到最后的时间中。

将最后一次收到的时间作为修正基准:

补偿至最后的时间中,最后更新本地时间:

三、实验结果

第一行为主机时间轴,最大误差出现在黄色,39.8us。

经过多次同步,所有从机的时间误差的前后关系几乎保持与上图一致,也就是黄色一直都是最大,其他也都是保持这个位置。

由于从机代码的一致性,也更换过2.4G模块,这个问题大概率是单片机硬件导致,目前暂时不做深究。

四、总结

该时间同步项目有很多应用场景,可以单独作为一个时间同步器应用到实际场景中。

由于在新框架中加入了很多优化,对之前的冗余操作和时间同步方案做了大规模优化,所以工程的流程更加复杂。从代码来看,新旧版本已经没有太多关联性,可以说是两个独立的项目了。

有关代码的实现细节有很多都没有具体展开讲,本片博客主要在于分享框架,读者可以自行阅读代码,如有不清楚的地方可以私信我;同时也欢迎各位读者对本项目提出优化意见,我将更新后推送至仓库。

相关推荐
普中科技25 分钟前
【普中STM32精灵开发攻略】--第 10 章 STM32位带操作
stm32·单片机·嵌入式硬件·物联网·arm·普中科技·位带操作
HW-BASE41 分钟前
C语言的结构体与联合体
c语言·单片机·嵌入式·编程·c
谢工碎碎念2 小时前
PCB工艺-四层板制作流程(简单了解下)
嵌入式硬件·物联网·硬件工程·iot·pcb工艺
FightingFreedom2 小时前
GPIO交换矩阵和IO_MUX
单片机·嵌入式硬件·esp32·arduino·esp32s3
TDengine (老段)2 小时前
TDengine IDMP 背后的技术三问:目录、标准与情景
大数据·数据库·物联网·算法·时序数据库·iot·tdengine
文火冰糖的硅基工坊3 小时前
[硬件电路-150]:数字电路 - 数字电路与模拟电路的异同
嵌入式硬件·fpga开发·电路·运放·跨学科融合
HW-BASE3 小时前
C语言控制语句练习题1
c语言·开发语言·单片机·算法·嵌入式·c
echo_pen4 小时前
蓝桥杯----锁存器、LED、蜂鸣器、继电器、Motor
单片机·蓝桥杯
zhmc5 小时前
MCU程序段的分类
单片机
2501_913981786 小时前
2025年WiFi技术白皮书:全球物联网无线通信的关键创新
物联网·wifi模组·wifi技术