完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
我自己做了一个 针对stm32的isp 离线编程器,
设计时候 采用了 W25Q64 作为要烧录文件的存储, 直接使用 Ymodem 协议,将文件下载到 flash中,免得再写一个上位机软件, 在ucos2的加持下,整个代码的逻辑比较简单易懂 Ymodem 协议 参考 https://www.cnblogs.com/dwj411024/p/7717084.html 贴上我的代码 头文件: #ifndef __Y_MODEM_H__ #define __Y_MODEM_H__ enum{ eYmSOH=0x01, eYmSTX=0x02, eYmEOT=0x04, eYmACK=0x06, eYmNAK=0x15, eYmCANCEL=0x18, eYmC=0x43, }; enum{ eYmFileBegin, eYmFileData, eYmFileEnd0, eYmFileEnd1, }; typedef unsigned char (*pYmdCb)(unsigned char *pdata,unsigned char state); unsigned char RecYModem(pYmdCb cb,unsigned char *recbuf); #endif 代码: #include "includes.h" /******************************************************************************************* 符号 数值 含义 SOH 0x01 128字节数据帧,协议类型 STX 0x02 1024字节数据帧,协议类型 EOT 0x04 结束传输,发送者发送 ACK 0x06 接收者处理成功回应,发送者发现下一包数据(1024或者128) NAK 0x15 接收者处理失败回应,发送者需要重发此1024或者128数据,或者接收到第一个EOT的回复包 CA 0x18 传输中止 C 0x43 接收者准备接收时会发连续的C,发送者接收到C开始发送 **********************************************************************************************************************/ //这两个代码要重写,放到应用端 extern unsigned char RecYModemData(unsigned char *timeout); extern void SendYModemData(unsigned char data); /*---- Y _ M O D E M _ C R C ---- 【功能】:crc校验 【参数】: **** 【返回】:**** 【说明】:**** --------------作者:卢杰西 2020年12月1日17:15:24--------------------------------*/ unsigned short int Y_Modem_CRC(unsigned char * buf, unsigned short int len) { unsigned short int chsum; unsigned short int stat; unsigned short int i; unsigned char * in_ptr; //指向要计算CRC的缓冲区开头 in_ptr = buf; chsum = 0; for (stat = len ; stat > 0; stat--) //len是所要计算的长度 { chsum = chsum^(unsigned short int)(*in_ptr++) << 8; for (i=8; i!=0; i--) { if (chsum & 0x8000){ chsum = chsum << 1 ^ 0x1021; } else { chsum = chsum << 1; } } } return chsum; } /*---- R E C Y M P A C K E T ---- 【功能】:接收一个包 【参数】:**** 【返回】:**** 【说明】:**** --------------作者:卢杰西 2020年12月1日17:15:39--------------------------------*/ signed char RecYmPacket(unsigned char *pdata) { unsigned char err; unsigned short int cnt,len,crcrec,crc; pdata[0]=RecYModemData(&err); if(err==OS_TIMEOUT) return -1; if(pdata[0]==eYmEOT) return 0; pdata[1]=RecYModemData(&err); if(err==OS_TIMEOUT) return -1; pdata[2]=RecYModemData(&err); if(err==OS_TIMEOUT) return -1; if((pdata[1]^pdata[2])!=0xff) return -2; if(pdata[0]==eYmSOH) len=128; else len=1024; for (cnt=0;cnt pdata[3+cnt]=RecYModemData(&err); if(err==OS_TIMEOUT) { return -1; } } crcrec=RecYModemData(&err)<<8; if(err==OS_TIMEOUT) return -1; crcrec|=RecYModemData(&err); if(err==OS_TIMEOUT) return -1; crc=Y_Modem_CRC(pdata+3,len); if(crc!=crcrec) { if(pdata[0]!=eYmSOH) return -3; else return -4; } return 0; } /*---- R E C Y M O D E M ---- 【功能】:Ymodem的协议流程, 【参数】: **** 【返回】:**** 【说明】:每接收到一个包 回调 cb 进行接收处理 --------------作者:卢杰西 2020年12月1日17:16:27--------------------------------*/ unsigned char RecYModem(pYmdCb cb,unsigned char *recbuf) { unsigned char cntEot=0,cnt,errcnt=0; signed char ret; do{ SendYModemData(eYmC); ret=RecYmPacket(recbuf); if(ret==0 && recbuf[0]==eYmSOH) { cb(recbuf,eYmFileBegin); //文件初始化 break; } else { OSTimeDly(OS_TICKS_PER_SEC); //接收 启动 失败 } }while(++errcnt<100); if(errcnt<100) { SendYModemData(eYmACK); SendYModemData(eYmC); do{ ret=RecYmPacket(recbuf); if(ret==0 || ret==-4) { errcnt=0; if( (recbuf[0]==eYmSOH && cntEot<2) ||recbuf[0]==eYmSTX ) { cntEot=0; cb(recbuf,eYmFileData); //文件下载中 SendYModemData(eYmACK); } else if(recbuf[0]==eYmSOH && cntEot==2) { printf("rec ocrn"); //cb(recbuf,eYmFileEnd0); //文件结束 SendYModemData(eYmACK); break; } else if(recbuf[0]==eYmEOT ) { if(cntEot==0) { SendYModemData(eYmNAK); printf("rec eot 1rn"); ++cntEot; } else { cb(recbuf,eYmFileEnd1); //文件结束 printf("rec eot 1rn"); SendYModemData(eYmACK); SendYModemData(eYmC); break; } } } else { SendYModemData(eYmNAK); } }while(++errcnt<100); } if(errcnt>=100) { //终止传输 for(cnt=0;cnt<10;cnt++) SendYModemData(eYmCANCEL); } return (errcnt<100); } 串口接口的代码: OS_EVENT *OSQModemRec; unsigned char RecYModemData(unsigned char *timeout) { unsigned char rec; rec=(INT32U)OSQPend(OSQModemRec,OS_TICKS_PER_SEC,timeout); return rec; } void SendYModemData(unsigned char ch) { USART_SendData(USART2, ch); while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET) OSTimeDly(1); } |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1632 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1559 浏览 1 评论
985 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
688 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1605 浏览 2 评论
1869浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
652浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
522浏览 3评论
539浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
508浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-25 11:16 , Processed in 1.046357 second(s), Total 79, Slave 62 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号