通过串口对STM32进行程序升级,采用Y-modem 协议进行升级。
1.协议中的宏定义:
SOH (0x01) //128字节数据包开始
STX (0x02) //1024字节的数据包开始
EOT (0x04) //结束传输
ACK (0x06) //回应
NAK (0x15) //没回应
C (0x43) //'C' == 0x4
2.传输过程:(一般都会设计某个指令,使下位机进入0x43状态)
1)下位机进入0x43状态,表示进入开始传输状态,等待上位机发送SOH状态;
2)上位机在等待中,接受到0x43后,就发送以SOH开头的数据包开始信号,发送序号为0x00,补码0xFF,文件名、0x00,、以及文件大小,除去序号外,需要补满128个字节,CRC校验2个字节,然后进入等待0x06应答;
数据包头 |
数据(128个字节) |
CRC校验 |
|||||
|
序号 |
补码 |
文件名 |
|
文件大小 |
用0x00 补齐128 |
2Byte |
SOH |
0x00 |
0xFF |
filename |
0x00 |
filesize |
高 |
3)下位机接收到SOH并且CRC校验通过后,开始发送0x06。上位机接收到0x06后,开始正文传输,形式如下:
序号定义 : char index_h = 0x00; 补码定义:char index_t = 0xFF;
数据包头 |
数据(1024个字节) |
CRC校验 |
||
|
序号 |
补码 |
从 bin 文件中读取的数据(读取的数据不满足1024 Byte 用0x00补齐) |
2Byte |
STX |
index_h++ |
0xFF-- |
高位在前 |
4)文件传输完成后,上位机需要发送0x04结束符,通知下位机,下位机在发送0x06告知上位机,最后上位机需要发送一个全0包,通知下位机本次通信结束;全0包如下:
数据包头 |
数据(128个字节) |
CRC校验 |
||
|
序号 |
补码 |
全0x00 |
2Byte |
SOH |
0x00 |
0xFF |
高位在前 |
下面就直接贴代码:比较粗糙
#define CONNECT_FLAG 0x43
#define PACKAGE_NULL 0x00
#define PACKAGE_SOH 0x01
#define PACKAGE_STX 0x02
#define PACKAGE_ETX 0x03
#define PACKAGE_EOT 0x04
#define PACKAGE_ACK 0x06
/*********************************************************************
*函数名称:ComputeCRC(byte[] bufDate)
*函数功能:CRC校验函数
*参 数:bufDate 传送的数据
*返 回 值:CRC校验值
**********************************************************************/
short ComputeCRC(unsigned char *bufDate, unsigned int len)
{
short cksum = 0;
int i, j = 0;
for(i = 0; i < len; i++)
{
cksum = cksum ^ bufDate[i] << 8;
for(j = 8; j != 0; j--)
{
if ((cksum & 0x8000) != 0)
cksum = (cksum << 1 ^ 0x1021);
else
cksum = (cksum << 1);
}
}
return cksum;
}
/*********************************************************************
*函数名称:DownLoad(const char *path, const char *name)
*函数功能:下载函数
*参 数:path 文件路径 name 文件名
*返 回 值:
**********************************************************************/
int DownLoad(const char *path, const char *name)
{
unsigned char rbuf[2];
unsigned char data[2048];
unsigned char WriteBuf[1200];
unsigned char readBuf[1200];
unsigned char NameBuf[100];
unsigned char buf[10];
unsigned char crc_dat[2];
unsigned long filesize = 0;
long cyc_res = 0;
long cyc_remain = 0;
int i = 0;
int crc;
FILE *fp;
char index_h = 0x00;
char index_t = 0xFF;
memcpy(NameBuf, name, strlen(name));
filesize = get_file_size(path);
fp = fopen(path, "rb");
if(NULL == fp)
{
return -1;
}
cyc_res = filesize / 1024; //文件大小,决定循环次数
cyc_remain = filesize % 1024; //决定是否不满1024,要补齐1024
memset(WriteBuf, 0x00, 1200);
memset(data, 0, 2048);
while(1) {
UhfUartDataRst();
for (i = 0; i < 1000; i++) { //是否超时
receive_serial_bytes(rbuf, 1, uhf_uart_fd); //从缓存中获取一个字节
if (CONNECT_FLAG == rbuf[0]) { //检验是否进入等待
flg++;
if (5 == flg) {
flg = 0;
break;
}
}
}
usleep(200000); //预留下位机的响应时间
receive_serial_bytes(rbuf, 1, uhf_uart_fd);
if (CONNECT_FLAG == rbuf[0]) //接收对接口令0x43
{
UhfUartDataRst();
//memcpy(WriteBuf, name, strlen(name)); //数据包的文件名
for (i = 0; i < strlen(name); i++) {
WriteBuf[i] = NameBuf[i];
}
WriteBuf[strlen(name)] = PACKAGE_NULL; //协议要求0x00
sprintf(&WriteBuf[strlen(name) + 1], "%d", filesize); //数据包的文件大小
crc = ComputeCRC(WriteBuf, 128);
crc_dat[1] = crc >> 8;
crc_dat[0] = crc & 0xFF;
data[0] = PACKAGE_SOH; //数据头
data[1] = index_h++;
data[2] = index_t--;
for (i = 0; i < 128; i++) {
data[3 + i] = WriteBuf[i];
}
for (i = 0; i < 2; i++) {
data[131 + i] = crc_dat[i];
}
SendCommand_R2000(data, 133); // 发送第一包数据包
while (res < cyc_res) {
usleep(200000);
if (receive_serial_bytes(rbuf, 1, uhf_uart_fd) != 0) {
memset(readBuf, 0, 1200);
memset(data, 0, 2048);
if (PACKAGE_ACK == rbuf[0]) //等待接收方0x06的应答
{
fread(readBuf, 1024, 1, fp);
crc = ComputeCRC(readBuf, 1024);
crc_dat[1] = crc >> 8;
crc_dat[0] = crc & 0xFF;
data[0] = PACKAGE_STX; //协议头
data[1] = index_h++;
data[2] = index_t--;
for (i = 0; i < 1024; i++) //组包
{
data[3 + i] = readBuf[i];
}
for (i = 0; i < 2; i++) {
data[1027 + i] = crc_dat[i];
}
SendCommand_R2000(data, 1029); //正文数据包开始发送
res++;
for(i = 0; i < 100; i++){}
}
}
}
//如果最后不够1024字节,后面补00,凑够1024个字节
if (cyc_remain > 0)
{
usleep(200000);
receive_serial_bytes(rbuf, 1, uhf_uart_fd);
if (PACKAGE_ACK == rbuf[0]) //等待接收方0x06的应答
{
memset(readBuf, 0, 1200);
memset(data, 0, 2048);
fread(readBuf, 1024, 1, fp);
crc = ComputeCRC(readBuf, 1024);
crc_dat[1] = crc >> 8;
crc_dat[0] = crc & 0xFF;
data[0] = PACKAGE_STX; //协议头
data[1] = index_h++;
data[2] = index_t--;
for (i = 0; i < 1024; i++) //组包
{
data[3 + i] = readBuf[i];
}
for (i = 0; i < 2; i++)
{
data[1027 + i] = crc_dat[i];
}
SendCommand_R2000(data, 1029); //数据包开始发送
}
buf[0] = PACKAGE_EOT;
SendCommand_R2000(buf, 1);
usleep(200000);
receive_serial_bytes(rbuf, 1, uhf_uart_fd);
if (PACKAGE_ACK == rbuf[0])
{
unsigned char endbuf[128];
memset(endbuf, 0x00, 128);
data[0] = PACKAGE_SOH; //协议头
data[1] = 0x00;
data[2] = 0xff;
for (i = 0; i < 128; i++) //组包
{
data[3 + i] = endbuf[i];
}
crc = ComputeCRC(WriteBuf, 128); //传输数据的CRC值
crc_dat[1] = crc >> 8;
crc_dat[0] = crc & 0xFF;
for (i = 0; i < 2; i++)
{
data[131 + i] = crc_dat[i];
}
SendCommand_R2000(data, 133); //数据包开始发送
buf[0] = PACKAGE_EOT;
SendCommand_R2000(buf, 1);
usleep(200000);
receive_serial_bytes(rbuf, 1, uhf_uart_fd);
if (PACKAGE_ACK == rbuf[0])
{
buf[0] = PACKAGE_EOT;
SendCommand_R2000(buf, 1);
}
res = 0;
fclose(fp);
break;
}
}
else
{
buf[0] = PACKAGE_EOT;
SendCommand_R2000(buf, 1);
usleep(200000);
receive_serial_bytes(rbuf, 1, uhf_uart_fd);
if(PACKAGE_ACK == rbuf[0])
{
unsigned char endbuf[128];
memset(endbuf, 0x00, 128);
data[0] = PACKAGE_SOH; //协议头
data[1] = 0x00;
data[2] = 0xff;
for (i = 0; i < 128; i++) //组包
{
data[3 + i] = endbuf[i];
}
crc = ComputeCRC(WriteBuf, 128); //传输数据的CRC值
crc_dat[1] = crc >> 8;
crc_dat[0] = crc & 0xFF;
for (i = 0; i < 2; i++) {
data[131 + i] = crc_dat[i];
}
SendCommand_R2000(data, 133); //第一包数据包开始发送
res = 0;
fclose(fp);
break;
}
}
}
}
return 1;
}