基于STM8L的NB-IoT物联网燃气表远程升级系统设计
作者: 马一棉 王晨昊
摘要:针对NB-IoT物联网燃气表在入户使用后难以进行固件升级的问题,为了满足系统软件的升级需求,本文设计了一种基于NB-IoT网络的物联网燃气表远程升级系统。该系统以STM8L微控制器为核心,利用NB-IoT网络实现数据传输,通过对存储芯片内部空间进行合理划分,增加IAP功能,实现对NB-IoT物联网燃气表的远程升级功能。
关键词:NB-IoT;物联网;STM8L;燃气表
中图分类号:TP393 文献标识码:A
文章编号:1009-3044(2024)24-0107-03
开放科学(资源服务)标识码(OSID)
0 引言
随着近些年NB-IoT技术的不断普及,传统的设备终端变得越来越智能化。在传统燃气表上增加NB-IoT功能,不仅提高了燃气公司的效率,也大大方便了用户的使用[1],由于燃气表的特殊性,安装后被广泛分散到不同的用户家里,当出现设计缺陷或需要升级增加新功能时,加入了互联网之后的NB-IoT物联网燃气表使得这一切变得简单可行。本文基于NB-IoT技术设计了一种安全、简单、可靠的物联网燃气表远程升级方案。
1 系统设计
本文设计的NB-IoT物联网燃气表通过NB-IoT网络与后台系统联动,结合手机App、微信公众号等方式实现NB-IoT物联网燃气表的智能计量、远程监控、远程阀控、远程充值等功能。其中,NB-IoT物联网燃气表由STM8L微控制器、NB-IoT通信单元(Narrow-Band Internet of Things)、基本计量单元、阀门控制单元、LCD显示单元(Liquid Crystal Display)、按键单元、红外通信单元、存储单元等部分组成[2],NB-IoT物联网燃气表整体的系统结构如图1所示。其中,计量单元通过两个霍尔传感器实现基本计量功能,存储单元通过24LC512芯片实现,用于计量数据、历史用气情况的存储以及固件升级数据的存储。按键用于查询用气情况和启动数据的上报,短按按键LCD液晶将轮显用气情况等数据,长按按键三秒以上,NB-IoT物联网燃气表将启动主动上报功能,实现数据的远程上传。同时,NB-IoT物联网燃气表每天会在凌晨时间段错峰向云平台上传数据,用以实现数据的上报和云平台指令的接收等功能,而远程升级功能就是利用NB-IoT物联网燃气表与云平台的交互来实现更新NB-IoT物联网燃气表内部固件的功能,以达到弥补NB-IoT物联网燃气表固件缺陷或升级新功能的需求。
2 升级原理
STM8L MCU 是意法半导体公司推出的一款超低功耗的8位微控制器。该系列微控制器集高性能和超低功耗于一身,尤其适合电池供电的系统。因此,本文选择 STM8L052R8芯片作为NB-IoT物联网燃气表的主控芯片。
应用编程IAP(In Application Programming),是用户自己的程序在运行过程中对内部的Flash区域进行编程烧写,更新后可以执行刚刚烧写的新的应用程序[3],从而实现芯片内部的程序升级。这里把NB-IoT物联网燃气表程序设计成 Bootloader和App两个独立的代码,两个代码通过编译分别生成不同的hex文件,将两个hex文件合并后生成一个新的hex文件,出厂时将这个hex文件烧录到芯片内部[4],这样NB-IoT物联网燃气表就实现了计量、显示、通信、固件升级等功能。
固件升级的基本过程:每天凌晨NB-IoT物联网燃气表都会主动向云平台上报数据。云平台根据NB-IoT物联网燃气表上报的版本号,决定是否下发升级指令,如果需要升级,NB-IoT物联网燃气表就会主动从云平台分包接收升级的固件包,同时把接收到的数据包存储在存储芯片内部,直到所有包接收完毕,并经校验无误后,NB-IoT物联网燃气表将从App程序跳转到Bootloader程序,启动内部更新程序,实现固件的自动更新。更新完成后调用重启功能进入新的App程序,至此NB-IoT物联网燃气表升级完成。
3 IAP功能实现
3.1 BootLoader引导程序设计
为了实现STM8L单片机的固件升级功能,必须有一个BootLoader引导程序来实现程序的跳转和更新功能,这段程序要尽量做到代码精简,逻辑清晰,还需要有异常处理功能。Bootloader 程序主要完成数据包的校验、固件的更新和程序的跳转等功能,当固件更新完成后,Bootloader 程序会强制从Bootloader程序跳转到App程序,其中,NB-IoT物联网燃气表的基本计量、显示、控制和数据上报等功能都是在App程序中实现的。
当STM8L单片机上电或重启后程序会首先执行BootLoader这段引导程序,这段程序具体的工作流程如下:BootLoader程序首先会判断固件更新的标志位有没有置位,如果没有置位,就代表固件不需要更新,此时程序会直接跳转到App应用程序执行NB-IoT燃气表的计量、显示、阀控、数据上报等功能,而如果经判断固件更新的标志位置位了,就代表有最新的固件需要更新,这个时候BootLoader程序就会进入升级模式,此时STM8L就会从指定的存储地址开始分包读取固件数据,在每一包数据读取完成后会计算当前这一包数据的CRC16值,并将这一值与每包接收到的CRC16值进行比较,如果计算的CRC16值和读取的CRC16值一致,就代表当前这一包数据正确,如果这一包数据验证无误后便会进行下一包数据的读取和CRC16的校验,以此循环,直至所有的数据包都读取并校验无误以后,BootLoader程序才会认为之前存储的每一包数据单包都没有问题,在此,为了保证数据的进一步完整可靠,在进行分包校验完成后,同时增加了整个固件代码的整体CRC16校验,将整个固件的所有数据计算一个CRC16值,并与系统下发的整个固件的总的CRC16值进行比较,如果CRC16值一致,才会认为之前接收的整个数据包都没有问题。如果经过以上的双重校验确认数据完整无误后,系统便会进入固件更新模式,此时系统便会分包读取数据,并将读取的数据写入STM8L内部指定的Flash地址,直至所有的数据写入完成,并验证无误后,系统便会清除固件更新的标志位,并调用跳转指令将代码跳转到App应用程序,从而执行NB-IoT燃气表的计量、显示、阀控、数据上报等功能,至此固件更新的整个过程完成,其中,更新过程中的具体工作流程如图2所示,以下代码是Bootloader程序的部分代码,该部分代码主要实现了数据的校验、Flash的擦写等功能。
if((w_CRC[0] == w_CRC_rcv1) && (w_CRC[1] == w_CRC_rcv2))//总帧校验正确
{
for (i = 0; i < 3; i++)
{
for (n = 0; n < 3; n++)
{
m=0;
ProgramBlock(pAppSrcBlock, MAIN_USER_RESET_ADDR, pAppSrc+i*128);
while ((FLASH->IAPSR & (uint8_t)FLASH_FLAG_HVOFF) == RESET){}
for (pAppSrcIndex = 0; pAppSrcIndex < FLASH_BLOCK_BYTES; pAppSrcIndex++)
{ /*!< Read flash byte */
//pApp_Addr=pAppSrcBlock * FLASH_BLOCK_BYTES + MAIN_USER_RESET_ADDR;
pApp_Addr = pAppSrcBlock;
pApp_Addr *= FLASH_BLOCK_BYTES;
pApp_Addr+=MAIN_USER_RESET_ADDR;
if ((*(PointerAttr uint8_t *)(MemoryAddressCast)(pAppSrcIndex + pApp_Addr)) != pAppSrc[pAppSrcIndex+i*128])
{
if(n==2)
{
/*for (i = 0; i < 200; i++)
{
GPIO_SetBits(GPIOD, GPIO_Pin_7);//低电
delay_ms(5);
GPIO_ResetBits(GPIOD, GPIO_Pin_7);//低电
delay_ms(5);
}
while(((GPIOG->IDR) & GPIO_Pin_1) == 0);//按钮未按下*/
asm("LDW X, SP ");
asm("LD A, $FF");
asm("LD XL, A ");
asm("LDW SP, X ");
asm("JPF $9000");
}
m=1;
break;
}
}
if(m==0) break;
}
pAppSrcBlock += 1;
pAppLen -= FLASH_BLOCK_BYTES;
delay_ms(10);
pAppTry = 3;
if(pAppLen);
else break;
}
}
3.2 App程序设计
App程序是用来实现NB-IoT物联网燃气表计量、LCD显示、阀控、存储、数据上传、网络充值等功能的代码,远程升级功能也是通过NB-IoT技术实现数据的分包传输,具体的工作流程如下:应用程序每次与云平台交互的时候都会主动上报自己的表号和目前的固件版本号,云平台收到NB-IoT物联网燃气上报的表号和版本号并进行分析,如果需要更新便会在NB-IoT物联网燃气上报数据之后给NB-IoT物联网燃气下发一条远程升级的启动指令,NB-IoT物联网燃气收到升级指令后,会主动向售气系统发送请求获取第一包数据的指令,云平台收到请求数据指令后,会将预先生成的bin格式的固件包数据进行分包,并根据上传上来的包号将对应的数据打包后下发给NB-IoT燃气表,这里数据包的获取采用的是主动向云平台获取的方式,这样做的好处是升级过程可控,而且最大程度减小了云平台的压力,通信过程中每包数据的最后两个字节跟的是当前整个数据包的CRC16值[5],这样做的目的是在执行BootLoader引导程序时能够对预先存储的数据进行校验,进一步保证数据的准确可靠。而且当所有的数据包都传输完成后,云平台会再次将整个固件里的所有数据计算一个总的CRC16值下发给燃气表,燃气表收到后,会将这个值存起来,用于数据的二次校验,直到所有的包都接收完成后,固件数据的接收过程也就完成了。NB-IoT物联网燃气表在接收固件数据的过程中,由于NB-IoT信号不好或者服务器响应慢等问题,会造成NB-IoT物联网燃气表接收不到云平台下发的升级数据,或者出现接收数据不完整的情况,所以App应用程序在设计的时候如果长时间接收不到云平台的数据,就需要主动再次向云平台请求当前数据包,但是如果多次请求后,仍然接收不到数据,则认为此次升级失败,这时便将目前升级的进度存储在存储芯片内部,待下次再次连接后继续完成升级过程。其中,通信过程中每一帧数据包的数据格式如表1所示:
首先,数据包的第1个字节是帧头,也就是帧起始符,这里使用十六进制的0xFE表示,帧头表示这一帧数据的开始,第2个字节是这一帧数据的总长度,这个长度是从帧长度到帧尾的帧数据的长度,第3个字节是这一帧数据的功能码,这里我们将数据升级指令的功能码定义为十六进制的0x55,接下来,从第4个字节到第9个字节表示的是当前NB-IoT物联网燃气表的表号,这个是用来区分不同的NB-IoT燃气表上传的数据的,从第10个字节开始为这一帧数据的数据域,数据域包含了NB-IoT燃气表当前的固件版本号、当前的包数和总包数,以及传输的固件数据等内容,接下来跟在数据域后面的两个字节是CRC16的校验码,用于数据的校验,进一步确保数据的准确可靠,紧接着跟在校验位后面的一个字节是这一帧数据的结束符,这里使用十六进制的0x16表示,代表这一帧数据的结束。这就是固件升级过程中,数据通信的格式,NB-IoT燃气表升级过程中应严格遵循这样的数据格式进行数据的传输。
4 系统测试
通过对国内某燃气公司已使用的100台NB-IoT物联网燃气表进行验证测试,在凌晨NB-IoT物联网燃气表数据错峰上报的同时,通过云平台给NB-IoT物联网燃气表下发启动升级功能,经测试,100台NB-IoT物联网燃气表中一次升级成功的有96台,升级失败的有4台,经过第二次的升级,剩下的4台设备也全部升级成功。
5 结论
本文针对NB-IoT物联网燃气表固件升级难的问题,提出了一种基于NB-IoT网络的远程升级方法,并完成了代码的设计,远程升级功能也已经在实际应用中得到了验证,同时,该方案对于基于NB-IoT网络的嵌入式设备的远程升级也具有一定的参考价值。
参考文献:
[1] 郑红立,刘航,胡洋.NB-IoT技术在物联网智能燃气表领域的应用与推广[J].城市燃气,2021,558(8):6-11.
[2] 高柱荣,蒋昌茂,刘洪林.物联网燃气表远程升级的研究与实现[J].自动化仪表,2021,42(5):27-31.
[3] 文丰,温倩,武慧军.基于IAP的嵌入式系统在线编程设计[J].单片机与嵌入式系统应用,2022,22(12):37-41.
[4] 陈以安,李鹏,车慢行.基于Wi-Fi的STM32固件远程升级系统[J].单片机与嵌入式系统应用,2022,22(7):46-50.
[5] 赵二刚,张红宾,王志红,等.基于LoRa技术的STM32处理器无线程序升级系统设计[J].南开大学学报(自然科学版),2020,53(6):18-21.
【通联编辑:梁书】