ymodem协议c语言,STC单片机ISP-Demo-使用Y-Modem协议源码与库函数分享
#define MAIN_Fosc 22118400L //定义主时钟
#define Baudrate0 115200UL //串口0波特率600~115200
#include "STC15Fxxxx.H"
#include "ymodem.h"
#define WDT_Enable 0 //1: 允许内部看门狗, 0: 禁止
#define D_BRT0_1T_8bit (256 - MAIN_Fosc / 32 / Baudrate0) //计算波特率 1T 8bit
#define ISP_ADDRESS 0xE400 //ISP开始地址, 高地址必须是偶数, 注意要预留ISP空间,本例程留3K
#define UserflashLenth (ISP_ADDRESS-3) //用户FLASH长度, 保留个字节存放用户地址程序的跳转地址
/************* 本地变量声明 **************/
typedef void (*pFunction)(void);
pFunction Jump_To_Application;
u16 JumpAddress;
u16 FileLength;
u16 Y_TimeOut,WaitTime;
u8 packets_received, session_begin;
u8 idata file_name[FILE_NAME_LENGTH];
u8 idata file_size[FILE_SIZE_LENGTH];
u8 StartCode[3];
u16 FlashDestination;
u16 RxCnt;
u8 HandCnt;
u8 xdata RxBuff[1024];
u8 idata RxBuff_10[10];
u32 DownCheckSum,FlashCheckSum;
/************* 本地函数声明 **************/
u8 Hex2Ascii(u8 dat);
u8 UART_Download(void);
u16 Str2Int(u8 *inputstr);
void ISP_WriteByte(u16 addr, u8 dat);
void ISP_EraseSector(u16 addr);
u8 ISP_ReadByte(u16 addr);
//========================================================================
// 函数: void TX1_write2buff(u8 dat)
// 描述: 串口发送一个字节.
// 参数: dat: 要发送的字节.
// 返回: none.
// 版本: V1.0, 2013-4-29
//========================================================================
void TX1_write2buff(u8 dat)
{
TI = 0;
SBUF = dat;
while(!TI);
}
//========================================================================
// 函数: void PrintString1(u8 *p)
// 描述: 串口发送一个字符串.
// 参数: *p: 要发送的字符串指针.
// 返回: none.
// 版本: V1.0, 2013-4-29
//========================================================================
void PrintString1(u8 *p)
{
for(; *p > 0; p++) TX1_write2buff(*p);
}
//========================================================================
// 函数: void Tx_DEC_U16(u16 j)
// 描述: 把一个16位整型数转成十进制送串口发送.
// 参数: j: 要处理的16位整型数.
// 返回: none.
// 版本: V1.0, 2013-4-29
//========================================================================
void Tx_DEC_U16(u16 j)
{
u8 i;
u8 tmp[10];
for(i=4; i<5; i--) tmp[i] = j % 10 + '0', j = j / 10;
for(i=0; i<4; i++)
{
if(tmp[i] != '0') break;
tmp[i] = ' ';
}
for(i=0; i<5; i++) TX1_write2buff(tmp[i]);
}
//========================================================================
// 函数: void Tx_HEX_U32(u32 j)
// 描述: 把一个32位长整型数转成十进制送串口发送.
// 参数: j: 要处理的32位整型数.
// 返回: none.
// 版本: V1.0, 2013-4-29
//========================================================================
void Tx_HEX_U32(u32 j)
{
u8 i,k;
u8 tmp[10];
for(i=8; i>0; i--)
{
k = ((u8)j) & 0x0f;
if(k <= 9) tmp[i] = k+'0';
else tmp[i] = k-10+'A';
j >>= 4;
}
for(i=1; i<9; i++) TX1_write2buff(tmp[i]);
}
//========================================================================
// 函数: void ReturnNameAndLength(void)
// 描述: 返回程序的文件名和长度, 和累加校验和.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2013-4-29
//========================================================================
void ReturnNameAndLength(void)
{
u16 i;
PrintString1("================================\r\n File name: ");
for(i=0; i
{
if(file_name[i] == 0) break;
TX1_write2buff(file_name[i]);
}
PrintString1("\r\n File length: ");
Tx_DEC_U16(FileLength);
PrintString1(" Bytes\r\n DownChexkSum: ");
Tx_HEX_U32(DownCheckSum);
PrintString1("\r\n ISP Versiom: 2013-4-30 by Coody");
PrintString1("\r\n================================\r\n\r\n");
}
//========================================================================
// 函数: void UART1_RxPackage(void)
// 描述: 串口接收一个数据块.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2013-4-29
//========================================================================
void UART1_RxPackage(void)
{
u16 j; //5ms超时
// RI = 0;
RxCnt = 0;
for(j = 0; j < 5000; j++) //最后收到一个字节5ms后,超时退出
{
if(RI)
{
RI = 0;
if(RxCnt < 1024) RxBuff[RxCnt] = SBUF;
else
{
RxBuff_10[RxCnt-1024] = SBUF;
}
if(++RxCnt >= 1034) RxCnt = 1033;
j = 0; //重新定时5ms
}
}
#if (WDT_Enable > 0)
WDT_reset(D_WDT_SCALE_256);
#endif
}
//========================================================================
// 函数: void main(void)
// 描述: 主函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2013-4-29
//========================================================================
void main(void)
{
u8 i;
EA = 0;
Timer0_Stop();
Timer1_Stop();
#if (WDT_Enable > 0)
WDT_reset(D_WDT_SCALE_256);
#endif
S1_8bit();
S1_RX_Enable();
S1_BRT_UseTimer1();
Timer1_AsTimer();
Timer1_1T();
Timer1_8bitAutoReload();
Timer1_InterruptDisable();
TH1 = D_BRT0_1T_8bit;
Timer1_Run();
// PrintString1("\r\n STC ISP Demo\r\n");
while(1)
{
// TX1_write2buff('A');
HandCnt = 0;
for(WaitTime = 0; WaitTime < 300; WaitTime++) //1.5秒超时
{
UART1_RxPackage();
if((RxCnt == 1) && (RxBuff[0] == 'd'))
{
if(++HandCnt >= 10)
{
i = UART_Download();
WaitTime = 250;
if(i == 1) PrintString1("\r\n User abort!\r\n");
else if(i == 2) PrintString1("\r\n PC Cancel!\r\n");
else if(i == 4) PrintString1("\r\n Programming Error!\r\n");
else if(i == 0)
{
PrintString1("\r\n\r\n Programming Completed Successfully!\r\n");
ReturnNameAndLength();
}
}
}
// else HandCnt = 0;
}
if(ISP_ReadByte(ISP_ADDRESS-3) == 0x02)
{
SCON = 0;
AUXR = 0;
TMOD = 0;
TL0 = 0;
TH0 = 0;
TH1 = 0;
TL1 = 0;
TCON = 0;
IAP_CMD = 0;
JumpAddress = ISP_ReadByte(ISP_ADDRESS-2);
JumpAddress = (JumpAddress << 8) | ISP_ReadByte(ISP_ADDRESS-1); //Jump to user application
Jump_To_Application = (pFunction) JumpAddress;
Jump_To_Application();
}
PrintString1(" No AP\r\n");
}
}
//========================================================================
// 函数: u16 Str2Int(u8 *inputstr)
// 描述: 字符串转整型.
// 参数: *inputstr: 字符串指针.
// 返回: 16位整型数.
// 版本: V1.0, 2013-4-29
//========================================================================
u16 Str2Int(u8 *inputstr)
{
u16 val;
u8 i;
val = 0;
for (i = 0; i < 5; i++)
{
if((inputstr[i] < '0') || (inputstr[i] > '9')) break;
val = val * 10 + inputstr[i] - '0';
}
return val;
}
//========================================================================
// 函数: void ISP_WriteByte(u16 addr, u8 dat)
// 描述: 对一个地址写FLASH一个字节.
// 参数: addr: 16位FLASH地址.
// dat: 要写入的一字节数据.
// 返回: none.
// 版本: V1.0, 2013-4-29
//========================================================================
void ISP_WriteByte(u16 addr, u8 dat)
{
IAP_CONTR = ISP_CONTR = (ISP_EN + ISP_WAIT_FREQUENCY); //使能IAP功能
ISP_WRITE(); //编程命令
IAP_ADDRL = addr;
IAP_ADDRH = addr >> 8;
IAP_DATA = dat; //将当前数据送IAP数据寄存器
ISP_TRIG(); //触发ISP命令
}
//========================================================================
// 函数: u8 ISP_ReadByte(u16 addr)
// 描述: 从一个地址读FLASH一个字节.
// 参数: addr: 16位FLASH地址.
// 返回: 读出的一字节数据.
// 版本: V1.0, 2013-4-29
//========================================================================
u8 ISP_ReadByte(u16 addr)
{
IAP_CONTR = ISP_CONTR = (ISP_EN + ISP_WAIT_FREQUENCY); //使能IAP功能
ISP_READ(); //编程命令
IAP_ADDRL = addr;
IAP_ADDRH = addr >> 8;
ISP_TRIG(); //触发ISP命令
return(IAP_DATA);
}
//========================================================================
// 函数: void ISP_EraseSector(u16 addr)
// 描述: 对FLASH擦除一个扇区.
// 参数: addr: 16位FLASH地址.
// 返回: none.
// 版本: V1.0, 2013-4-29
//========================================================================
void ISP_EraseSector(u16 addr)
{
IAP_CONTR = ISP_CONTR = (ISP_EN + ISP_WAIT_FREQUENCY); //使能IAP功能
ISP_ERASE(); //擦除命令
IAP_ADDRL = addr;
IAP_ADDRH = addr >> 8;
ISP_TRIG(); //触发ISP命令
}
//========================================================================
// 函数: u8 UART_Download(void)
// 描述: 按Ymodem接收文件数据并写入用户FLASH.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2013-4-29
//========================================================================
u8 UART_Download(void)
{
u16 i;
u8 j;
PrintString1("\r\n\r\n Waiting for the file to be sent ... (press 'a' to abort)\r\n");
Y_TimeOut = 0;
packets_received = 0;
session_begin = 0;
WaitTime = 40;
DownCheckSum = 0;
while(WaitTime > 0)
{
if(Y_TimeOut == 0)
{
TX1_write2buff(CRC16);
Y_TimeOut = 300;
if(WaitTime > 0) WaitTime--;
}
while(Y_TimeOut > 0)
{
UART1_RxPackage();
if(RxCnt == 0) Y_TimeOut--;
else
{
if(RxCnt == 1)
{
if(RxBuff[0] == EOT)
{
TX1_write2buff(ACK);
Y_TimeOut = 40;
}
else if((RxBuff[0] == ABORT1) || (RxBuff[0] == ABORT2))
{
return 1;
}
}
else if(RxCnt <= 5)
{
if((RxBuff[0] == CANCEL) && (RxBuff[1] == CANCEL))
{
return 2;
}
}
else if((RxCnt == 133) || (RxCnt == 1029))
{
if (RxBuff[PACKET_SEQNO_INDEX] != (RxBuff[PACKET_SEQNO_COMP_INDEX] ^ 0xff))
{
TX1_write2buff(NAK); //错误, 请求重发
Y_TimeOut = 300;
}
else
{
WaitTime = 5;
if (packets_received == 0) //发送序号为0, 为文件名数据包
{
if (RxBuff[PACKET_HEADER] != 0) //文件名不为空
{
for (i = 0; i < FILE_NAME_LENGTH; i++) file_name[i] = 0;
for (i = 0; i < FILE_SIZE_LENGTH; i++) file_size[i] = 0;
j = PACKET_HEADER;
for (i = 0; (i < FILE_NAME_LENGTH) && (RxBuff[j] != 0); i++)
file_name[i] = RxBuff[j++]; //保存文件名
for (i=0, j++; (RxBuff[j] != ' ') && (i < FILE_SIZE_LENGTH); i++)
file_size[i] = RxBuff[j++]; //保存文件长度
FileLength = Str2Int(file_size); //文件长度由字符串转成十六进制数据
if (FileLength >= UserflashLenth) //长度过长错误
{
TX1_write2buff(CANCEL); //错误返回2个 CA
TX1_write2buff(CANCEL);
return 3; //长度过长
}
StartCode[0] = ISP_ReadByte(0); //保存ISP跳转地址
StartCode[1] = ISP_ReadByte(1);
StartCode[2] = ISP_ReadByte(2);
ISP_EraseSector(0);
ISP_WriteByte(0,StartCode[0]); //回写ISP跳转地址
ISP_WriteByte(1,StartCode[1]);
ISP_WriteByte(2,StartCode[2]);
for(i=0x200; i < UserflashLenth; i+=0x200) //擦除N页
ISP_EraseSector(i);
TX1_write2buff(ACK); //擦除完成, 返回应答
Y_TimeOut = 40;
packets_received ++;
session_begin = 1;
FlashDestination = 0;
DownCheckSum = 0;
}
}
else if(session_begin == 1) //收过文件名
{
if(RxBuff[PACKET_SEQNO_INDEX] == 0) //全0数据帧
{
ISP_WriteByte(ISP_ADDRESS-3,StartCode[0]); //全部下载结束,最后写用户入口地址
ISP_WriteByte(ISP_ADDRESS-2,StartCode[1]);
ISP_WriteByte(ISP_ADDRESS-1,StartCode[2]);
TX1_write2buff(ACK);
FlashCheckSum = ISP_ReadByte(ISP_ADDRESS-3);
FlashCheckSum += ISP_ReadByte(ISP_ADDRESS-2);
FlashCheckSum += ISP_ReadByte(ISP_ADDRESS-1);
for(i = 3; i < FileLength; i++) FlashCheckSum += ISP_ReadByte(i); //计算FLASH累加和
if(FlashCheckSum == DownCheckSum) return 0; //正确
else
{
ISP_EraseSector(ISP_ADDRESS-0x200);
return 4; //写入错误
}
}
else //数据帧
{
for(i=0; i<1024; i++) RxBuff[i] = RxBuff[i+3];
RxBuff[1021] = RxBuff_10[0];
RxBuff[1022] = RxBuff_10[1];
RxBuff[1023] = RxBuff_10[2];
RxCnt -= 5;
for(i = 0; (i < RxCnt) && (FlashDestination < FileLength); i++)
{
if(FlashDestination == 0)
{
StartCode[0] = RxBuff[0];
StartCode[1] = RxBuff[1];
StartCode[2] = RxBuff[2];
FlashDestination = 3;
i += 3;
DownCheckSum += RxBuff[0]; DownCheckSum += RxBuff[1]; DownCheckSum += RxBuff[2];
}
ISP_WriteByte(FlashDestination,RxBuff[i]);
DownCheckSum += RxBuff[i];
FlashDestination ++;
}
TX1_write2buff(ACK); //保存完成, 返回应答
Y_TimeOut = 300;
packets_received ++;
}
}
}
}
}
}
}
return 100; //其他错误
}
ymodem协议c语言,STC单片机ISP-Demo-使用Y-Modem协议源码与库函数分享相关推荐
- 串口 单片机 文件_STC单片机ISP下载编程软件下载|STC单片机ISP下载编程软件 6.87 官方版...
别看了,这款软件免费!没有额外的收费,如果你囊肿羞涩,这一款软件一定是你可以选择的比较重要的软件之一.小编亲测,在多个功能上都有着自己比较鲜明的特点,首先第一眼就是界面了,不知道你有什么感受. STC ...
- C语言期末大作业-学生成绩管理系统(完整源码+设计报告)
C语言-学生成绩管理系统 一.学生成绩管理系统源码(完整) 二.程序设计报告 1.课程设计目的 2.课程设计任务与要求: 4.课程设计成果(运行截图) 5.课程设计心得 一.学生成绩管理系统源码(完整 ...
- C语言打印字符串的所有排列组合(附完整源码)
C语言打印字符串的所有排列组合 字符串的所有排列问题 C语言打印字符串的所有排列组合的完整源码(定义,实现,main函数测试) 字符串的所有排列问题 示例:ABC的排列是ABC,ACB,BCA,BAC ...
- GK309协议电子工牌数据模拟器+Socket数据发送 JAVA版-源码
GK309协议电子工牌数据模拟器+Socket数据发送 JAVA版-源码 说明 源码 EXE执行文件 说明 单JAVA文件,直接运行main方法即可. 只做了GK309的基础位置数据模拟: 0x01 ...
- 单片机 stm32 差分升级 增量升级算法源码, 纯c编写跨平因为是程序源码
单片机 stm32 差分升级 增量升级算法源码, 纯c编写跨平因为是程序源码 IAP升级 OTA升级 物联网 车联网 适用 YID:83500653978935134Deflag
- 单片机 stm32 差分升级 增量升级算法源码,纯c编写跨平因为是程序源码
单片机 stm32 差分升级 增量升级算法源码,纯c编写跨平因为是程序源码 IAP升级 OTA升级 物联网 车联网 适用 现有:69500653978935134Deflag
- 单片机 stm32 差分升级 增量升级算法源码,提供移植 纯c编写跨平因为是程序源码
单片机 stm32 差分升级 增量升级算法源码,提供移植 纯c编写跨平因为是程序源码 IAP升级 OTA升级 物联网 车联网 适用 YID:83500653978935134Deflag
- 单片机 stm32 差分升级 增量升级算法源码
单片机 stm32 差分升级 增量升级算法源码,提供移植 纯c编写跨平因为是程序源码 IAP升级 OTA升级 物联网 车联网 适用 YID:83500653978935134Deflag
- 国际多语言出海商城返佣产品自动匹配订单源码
国际多语言出海商城返佣产品自动匹配订单源码 8国多语言出海拼单商城 此网站是很多巴西客户定制的原型,已投放运营符合当地本地化 多语言商城返利返佣投资理财派单自带余额宝, 采取全新支付端口,后台语音提醒 ...
最新文章
- OpenCV Hough Line变换
- 点分治问题 ----------- 	luoguP2942 [WC2010]重建计划 [点分治 + bfs + 单调队列 + 预处理建树 + 二分 + 01分数规划]
- 阿里云盘又送福利啦?空间大时间长,不要犹豫快上车!
- 优信php笔试题_PHP应聘笔试题
- [置顶] “非主流”Web容器之TomJetty之让服务动起来
- 深度卷积神经网络的水稻穗瘟病检测方法
- SQL variable type
- 一个方便快捷gif在线水印制作(支持文字和图片)
- iPad远程控制windows主机及内网穿透原理
- Github解除账号被封的方法
- Spark程序性能优化之persist()
- python代码练习,微信登入并生成头像大图
- Excel-VBA操作文件四大方法之一(转)
- Rational Rose 2007的详细安装步骤
- 【Vue项目笔记心得】Swiper插件用于轮播图
- Microchip PIC系列8位单片机入门教程(一)开发环境建立
- 皇家贝贝骗子佟大为赴内蒙出席活动 影迷冒严寒守候支持
- C++11 - 构建一个符合实际应用要求的线程池
- 2.1.6.6 漏洞利用-SSH安全防御
- 【Test】GacUI 1.0 眼看着就要写完了 (4)
热门文章
- 宝塔面板搭载ThinkPHP5.0项目关于open_basedir报错解决办法
- PHP中的include和require
- jpa 多层嵌套一对多_OpenJPA-嵌套的一对多关系合并问题
- 新手python爬虫代码_新手小白必看 Python爬虫学习路线全面指导
- 求两个集合是否有交集 c语言_高中数学:集合与函数概念知识点总结
- android tv 开发布局,Android TV开发总结(七)构建一个TV app中的剧集列表控件
- java的c import_关于编译(javac),import,package的再理解
- linux中的ftp是什么意思,什么是linux的ftp
- php js 正则表达式,【PHP】用正则表达式过滤js代码(注意这个分析过程)
- unity 下一帧执行_理解Unity中的优化(三):协程(Coroutines)