#ifndef _XMODEM_H_
#define _XMODEM_H_
#include <stdint.h>
int xmodemReceive(unsigned char *dest, int destsz) ;
#endif
#include "main.h"
#include "gkbaseusart.h"
#include "xmodem.h"
#include <string.h>
#define SOH 0x01
#define STX 0x02
#define EOT 0x04
#define ACK 0x06
#define NAK 0x15
#define CANX 0x18
#define CTRLZ 0x1A
#define DLY_1S 1000
#define MAXRETRANS 25
static int last_error = 0;
//完成输出
//类似printf搬运过来串口1的函数
//最一个准备工作 把接受区清空
void out_buff(unsigned char *buff, int size)
{
GK_usart_clear(&GKU1);
HAL_UART_Transmit(&huart1 , buff, size , 0xffff);
}
//发送出去以后 我们在收到的数据
//这个函数风格是 我TX以后 过一会儿 就去接受缓存区拿数据 有的话 就是成功
//拿到受到的数据buff 返回数据的长度
int in_buff(unsigned char *buff, int time_out)
{
int qSize = 0;
int readSize = 0;
last_error = 0;
HAL_Delay(time_out);
if(GKU1.rx_len)
{
qSize = GKU1.rx_len;
if(qSize > 0)
{
readSize = GKU1.rx_len;
memcpy(buff,GKU1.rxBuf,GKU1.rx_len);
}
}
if(readSize == 0)
last_error = 1;
return (readSize);
}
//完成数据CRC计算
int calcrc(const unsigned char *ptr, int count)
{
int crc;
char i;
crc = 0;
while (--count >= 0)
{
crc = crc ^ (int) *ptr++ << 8;
i = 8;
do
{
if (crc & 0x8000)
crc = crc << 1 ^ 0x1021;
else
crc = crc << 1;
} while (--i);
}
return (crc);
}
//完成数据和本地比较 1一样 0不同
int check(int crc, const unsigned char *buf, int sz)
{
if(crc)
{
unsigned short crc = calcrc(buf, sz);
unsigned short tcrc = (buf[sz]<<8)+buf[sz+1];
if (crc == tcrc)
return 1;
}
else
{
int i = 0;
unsigned char cks = 0;
for(i = 0; i < sz; i ++)
{
cks += buf[i];
}
if (cks == buf[sz])
return 1;
}
return 0;
}
//接受函数
int xmodemReceive(unsigned char *dest, int destsz)
{
unsigned char xbuff[140];
int bufsz = 0;
int crc = 0;
unsigned char trychar = 'C';
unsigned char packetno = 1;
int c = 0;
int len = 0;
int retry = 0;
int retrans = MAXRETRANS;
int recvSize = 0;
for(;;)
{
for(retry = 0; retry < 16; retry ++)
{
if(trychar)
{
xbuff[0] = trychar;
out_buff(xbuff, 1); //发送'C'出去 作为接受者 先发送C 去启动
}
recvSize = in_buff(xbuff, (DLY_1S)<<1); //相当于TXRX 这里收到的数据 去分析
c = xbuff[0];
if (last_error == 0)
{
switch(c)
{
case SOH:
bufsz = 128;
goto start_recv;
case STX:
{
xbuff[0] = CANX;
out_buff(xbuff, 1);
}
return -1;
case EOT:
{
xbuff[0] = ACK;
out_buff(xbuff, 1);
}
return len;
case CANX:
in_buff(xbuff, DLY_1S);
c = xbuff[0];
if(c == CANX)
{
{
xbuff[0] = ACK;
out_buff(xbuff, 1);
}
return -1;
}
break;
default:
break;
}
}
}
if (trychar == 'C')
{
trychar = NAK;
continue;
}
{
xbuff[0] = CANX;
out_buff(xbuff, 1);
out_buff(xbuff, 1);
out_buff(xbuff, 1);
}
return -2;
start_recv:
if(trychar == 'C')
crc = 1;
trychar = 0;
if(recvSize != (bufsz + (crc ? 1 : 0) + 4))
goto reject;
if(xbuff[1] == (unsigned char)(~xbuff[2]) &&
(xbuff[1] == packetno || xbuff[1] == (unsigned char)packetno - 1) &&
check(crc, &xbuff[3], bufsz))
{
if(xbuff[1] == packetno)
{
int count = destsz - len;
if (count > bufsz)
count = bufsz;
if (count > 0)
{
memcpy(&dest[len], &xbuff[3], count);
len += count;
}
packetno ++;
retrans = MAXRETRANS+1;
}
if(-- retrans <= 0)
{
{
xbuff[0] = CANX;
out_buff(xbuff, 1);
out_buff(xbuff, 1);
out_buff(xbuff, 1);
}
return -3;
}
{
xbuff[0] = ACK;
out_buff(xbuff, 1);
}
continue;
}
reject:
{
xbuff[0] = NAK;
out_buff(xbuff, 1);
}
}
}
//send_buff_size == 140
int xmodemTransmit(unsigned char *src, int srcsz)
{
unsigned char xbuff[140];
int bufsz = 0;
int crc = -1;
unsigned char packetno = 1;
int i = 0;
int c = 0;
int len = 0;
int retry = 0;
for(;;)
{
for( retry = 0; retry < 16; ++retry)
{
in_buff(xbuff, (DLY_1S)<<1);
c = xbuff[0];
if(last_error == 0)
{
switch(c)
{
case 'C':
crc = 1;
goto start_trans;
case NAK:
crc = 0;
goto start_trans;
case CANX:
in_buff(xbuff, DLY_1S);
c = xbuff[0];
if(c == CANX)
{
{
xbuff[0] = ACK;
out_buff(xbuff, 1);
}
return -1;
}
break;
default:
break;
}
}
}
{
xbuff[0] = CANX;
out_buff(xbuff, 1);
out_buff(xbuff, 1);
out_buff(xbuff, 1);
}
return -2;
for(;;)
{
start_trans:
xbuff[0] = SOH;
bufsz = 128;
xbuff[1] = packetno;
xbuff[2] = ~packetno;
c = srcsz - len;
if(c > bufsz)
c = bufsz;
if(c >= 0)
{
memset(&xbuff[3], 0, bufsz);
if (c == 0)
{
xbuff[3] = CTRLZ;
}
else
{
memcpy(&xbuff[3], &src[len], c);
if (c < bufsz)
xbuff[3 + c] = CTRLZ;
}
if(crc)
{
unsigned short ccrc = calcrc(&xbuff[3], bufsz);
xbuff[bufsz + 3] = (ccrc>>8) & 0xFF;
xbuff[bufsz + 4] = ccrc & 0xFF;
}
else
{
unsigned char ccks = 0;
for(i = 3; i < bufsz + 3; i ++)
{
ccks += xbuff[i];
}
xbuff[bufsz + 3] = ccks;
}
for(retry = 0; retry < MAXRETRANS; retry ++)
{
out_buff(xbuff, bufsz + 4 + (crc ? 1 : 0));
in_buff(xbuff, DLY_1S);
c = xbuff[0];
if(last_error == 0)
{
switch(c)
{
case ACK:
packetno ++;
len += bufsz;
goto start_trans;
case CANX:
in_buff(xbuff, DLY_1S);
c = xbuff[0];
if(c == CANX)
{
{
xbuff[0] = ACK;
out_buff(xbuff, 1);
}
return -1;
}
break;
case NAK:
break;
default:
break;
}
}
}
{
xbuff[0] = CANX;
out_buff(xbuff, 1);
out_buff(xbuff, 1);
out_buff(xbuff, 1);
}
return -4;
}
else
{
for(retry = 0; retry < 10; retry ++)
{
{
xbuff[0] = EOT;
out_buff(xbuff, 1);
}
in_buff(xbuff, (DLY_1S)<<1);
c = xbuff[0];
if(c == ACK)
break;
}
return ((c == ACK) ? len : -5);
}
}
}
}
此时写一文件
启动发送
在运行代码即可
STM32收到了数据到buf而且不够的全部是0X1A