上一篇文章,详解嵌入式设备的文件传输协议 详细介绍了文件传输协议 Xmodem 协议族。
Xmodem 协议族通常都是通过串口来进行较近距离的文件传输,但实际上很多文件传输的需求远比这要复杂,需要我们灵活的针对特定场景设计通信协议来实现更加多样化的文件传输。
这篇文章对文件传输协议的内容进行扩展,并结合几个项目对其进行发挥拓展。
通过 CAN 来进行文件传输源自于振南的“电动车共享充电柜”项目,如图为共享充电柜实物外观及内部电路
共享充电箱的整体示意图
主控具有 4G 通信功能,可接收云端下发的命令,比如打开柜、开始充电、结束充电等,也可以向云端上传状态信息,如柜门开关状态、电流功率等。
对于主控及从机的固件升级,也都实现了远程更新。主控我们暂且不提,先来说一下从机的固件烧录:
主控从云端下载或者从上位机获取从机固件文件,然后通过 CAN 总线将此固件再进一步传给某个从机(通过CAN ID进行区分),最终通过从机的 Bootloader 完成烧录。
在这个过程中,CAN文件传输协议是关键,如图,通过CAN进行文件传输的协议示意
其实 CAN 总线并不适合于批量的数据传输,它每一帧数据仅能传输8个字节。但为了实现高度自动化的批量烧录,我还是基于 CAN 总线实现了文件传输(这实在是有点为难自己的感觉)。
仔细看上图的传输过程,你就会发现它与 Xmodem 其实大同小异,实现思路是一样的。
有小伙伴会问:“相比于CAN文件传输,我更想知道你这个主控是如何实现从云端下载固件的,也就是嵌入式网络文件传输是如何实现的?”
别急,下一节就会涉及到这方面的内容。以“智能充电柜”这个项目为例,也是为了引出这个问题。
振南在项目中使用的是 SIM800 这个模块,如图所示,“智能充电柜”项目实际主控板和SIM800模块
SIM800 本身内置了 HTTP 协议,所以就可以直接向服务器 GET 固件数据了。具体的实现代码如下:
int WEBDOWN(void)
{
char bin_name[30];
if(SIM800_Check_GPRS())
{
return 1; //**无网络
}
if(SIM800_Config_Bearer1())
{
return 2;
} //**设置网络参数失败
if(SIM800_Config_Bearer2())
{
return 3;
} //**设置网络参数失败
if(SIM800_Open_GPRS_Context())
{
return 4;
} //**打开GPRS**场景
if(SIM800_Query_GPRS_Context())
{
return 5;
} //**索取GPRS**场景信息
if(SIM800_HTTP_INIT())
{
return 6;
} //**初始化HTTP**协议失败
if(SIM800_HTTP_SET_PARA1())
{
return 7;
} //**设置HTTP**参数1
strcpy(bin_name,"master.bin");
if(SIM800_HTTP_SET_PARA2("www.znmcu.com",bin_name))
{
return 8;
};//**设置HTTP**参数2
if(SIM800_HTTP_GET())
{
return 9;
}; //GET**方法,可获取要下载文件的大小
{
unsigned int temp=(web_download_file_len/1024);
unsigned int i=0,prog_addr=0;
unsigned char total_chksum=0;
unsigned char \*p;
DEBUG_OUT("T Ts:%d\r\n",temp);
for(i=0;i
{
SIM800_HTTP_READDATA(i\*1024L,1024);
}
if(web_download_file_len%1024)
{
SIM800_HTTP_READDATA(i\*1024L,(web_download_file_len%1024));
i++;
}
}
//**对固件进行校验、重启后BL**将固件烧写到APP**区
}
实际的代码非常冗长,很多无关的东西。上面的代码是精简之后的,主要用于说明 HTTP 从服务器上拉取固件文件的主要过程。
http://www.znmcu.com/tg/519.html
有经验的嵌入式工程师对 Json 并不陌生,我们可以用它来实现不同平台之间的结构化数据的交换。
所以,在有些应用中 Json 会被用来进行文件数据的传输,比如我曾经研发过的一些 WIFI 设备,请看图,通过Json传输固件数据。
我们知道 Json 本身是一个字符串,所以它是不能直接传输二进制数据的,那固件的二进制数据如何通过 Json 来传输呢?
这不光是 Json 的问题,也是所有文本协议所面临的问题,比如我们经常使用的电子邮件 Email 的通信协议,再比如我们最常用的HTTP协议。
HTTP本身就是超文本传输协议,其实它只传文本,也就是ASCII,但是我们上网的时候经常会使用HTTP来下载文件,那它的二进制数据是怎么传的呢?不知道大家有没有考虑过这个问题?
为了解决这个问题,人们提出了 Base64 编码,请看图,通过 Base64 编码来表达二进制数据。希望大家可以体会到它的巧妙。
Base64 的基本思想是:将数据的二进制序列按 6 位进行分隔,然后用 64 个可打印字符进行表达。所以,每3个字节可以转化为 4 个字符。如果不足 3 个字节,则用 = 来进行占位。
本系列文章介绍了一些文件传输的相关协议,并结合几个项目对其进行了发挥拓展。
这里所涉及的内容,在实际应用时可能会有更大的外延,比如 Xmodem 协议经过改良,可用于卫星数据传输。
再复杂的技术也是由简单的元素构成的,了解和掌握了基础,才能让我们在技术上走得更远。希望大家从文章内容能够得到启发,并最终应用到自己的实际开发之中,让知识产生价值。
http://www.znmcu.com/tg/519.html
觉得文章不错,点击“分享”、“赞”、“在看” 呗!