找回密码
 注册
关于网站域名变更的通知
查看: 222|回复: 2
打印 上一主题 下一主题

关于STC8A8K64S单片机远程升级讨论

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2022-6-17 10:19 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
这个话题,相信很多朋友都有讨论和使用。今天我就说说我自已成功使用的方法。首先单片机需要有这个IAP功能。STC单片机在选型时要注意,不是哪一款都可以,要有IAP功能才行。单片机通过串口或其它通讯方式,接收升级BIN文件,写入到内部FLASH中,校验通过,执行自动升级过程。我的升级思想及过程如下。; h/ o/ S) Z+ R/ V( W$ c  [& b
1:出厂程序:(含有IAP功能)程序起址地址为单片机内存的后半部份,例如0X8000,KEIL中需要设置一下
8 _. h7 s, v8 z( Y" J- u2 H7 `+ r6 k5 n* L+ `7 x+ s
2:为什么要设置成后半部份,这是因为我把前半部份的空间留给后续需要升级时的程序。! ~! t) v$ e& f) N
3:因为中断向量部份在最前面的内存空间,无法改变,因此我的升级方法比较简单暴力。当接收完校验通过后,直接改变中断向量部份空间。: H0 }2 x) l7 w
4:贴出代码:) F. T2 q0 e7 A
  • int main()
  • {
  •         LEDs_up_ten_flag=0; //流水灯开始
  •         GPIOInit();          //GPIO+时钟初始化
  •         Iap_Isp();          //升级包检测
  •         Uart1_Init();                //115200bps@24MHz
  •         Uart2_Init();                //9600bps@24MHz
  •         Timer0Init();       //1毫秒@24.000MHz
  •         printf("\r\n青橙新能源4G控制充电板V00启动成功!\r\n");
  •          LETCAT1_Init(); //模组初始化及登陆服务器
  •        LB0910_Init(); //0910初始化
  •          BUZZFlag=1;
  •         WDT_CONTR = 0x27;//使能看门狗,溢出时间约为5s
  •         BeatTimescnt=BeatTimesSet-10;  //快速上线心跳
  • //          Read_PortTimes(); //读出端口时间数据 云端已实现
  •           RestTimes=0;
  •                 LEDs_up_ten_flag=1;//流水灯禁止
  •                 while(1)
  •                         {
  •                                         LED_show();
  •                                         Uart1_drive();                           //串口功能函数,主循环中调用
  •                                         Uart2_drive();                           //串口功能函数,主循环中调用                                  HeartbeatServer();
  •                                         WDT_CONTR |= 0x10;    //清看门狗,否则系统复位
  •                                   if(RestTimes>=120)
  •                                         {
  •                                                 RestTimes=0;
  •                                                 IAP_CONTR |= 0x60;
  •                                         }
  •                         }
  • }
  • #include "EEPROM.H"
  • u16 code IAP_Code1[60]={
  •                                                                                                                 0x0200,0x0400,0x0600,0x0800,0x0A00,0x0C00,0x0E00,  //升级版地址30K
  •                                                                                                          0x1000,0x1200,0x1400,0x1600,0x1800,0x1A00,0x1C00,0x1E00,
  •                                                                                                          0x2000,0x2200,0x2400,0x2600,0x2800,0x2A00,0x2C00,0x2E00,
  •                                                                                                          0x3000,0x3200,0x3400,0x3600,0x3800,0x3A00,0x3C00,0x3E00,
  •                                                                                                          0x4000,0x4200,0x4400,0x4600,0x4800,0x4A00,0x4C00,0x4E00,
  •                                                                                                          0x5000,0x5200,0x5400,0x5600,0x5800,0x5A00,0x5C00,0x5E00,
  •                                                                                                          0x6000,0x6200,0x6400,0x6600,0x6800,0x6A00,0x6C00,0x6E00,
  •                                                                                                          0x7000,0x7200,0x7400,0x7600,0x7800
  •                                                                                                 };
  • /*u16 code IAP_Code2[50]={ 0x8000,0x8200,0x8400,0x8600,0x8800,0x8A00,0x8C00,0x8E00,
  •                                                                                                                 0x9000,0x9200,0x9400,0x9600,0x9800,0x9A00,0x9C00,0x9E00,            //基础版软件放置地址        25K
  •                                                                                                                 0xA000,0xA200,0xA400,0xA600,0xA800,0xAA00,0xAC00,0xAE00,
  •                                                                                                                 0xB000,0xB200,0xB400,0xB600,0xB800,0xBA00,0xBC00,0xBE00,
  •                                                                                                                 0xC000,0xC200,0xC400,0xC600,0xC800,0xCA00,0xCC00,0xCE00,
  •                                                                                                                 0xD000,0xD200,0xD400,0xD600,0xD800,0xDA00,0xDC00,0xDE00,
  •                                                                                                                 0xE000,0xE200,
  •                                                                                                 };
  •                                                                                                 */
  • void IapIdle()                   //关闭 IAP功能 并保护数据
  • {
  •         IAP_CONTR = 0;          // 关闭 IAP 功能
  •         IAP_CMD = 0;                         // 清除命令寄存器
  •         IAP_TRIG = 0;                 // 清除触发寄存器
  •         IAP_ADDRH = 0x80; // 将地址设置到非 IAP 区域
  •         IAP_ADDRL = 0;
  • }
  • u8 IapRead(u16 addr)                                // 读数据的操作
  • {
  •         char dat;
  •         IAP_CONTR = WT_24M;                                                 // 使能 IAP
  •         IAP_CMD = 1;                                                                         // 设置 IAP 读命令
  •         IAP_ADDRL = addr;                                                 // 设置 IAP 低地址
  •         IAP_ADDRH = addr >> 8;                                 // 设置 IAP 高地址
  •         IAP_TRIG = 0x5a;                                                         // 写触发命令 (0x5a)
  •         IAP_TRIG = 0xa5;                                                         // 写触发命令 (0xa5)
  •         _nop_();
  •         dat = IAP_DATA;                                                         // 读 IAP 数据
  •         IapIdle();                                                                          // 关闭 IAP 功能
  •         return dat;
  • }
  • void IapProgram(u16 addr, u8 dat)                 //写数据操作。
  • {
  •         IAP_CONTR = WT_24M;                                   // 使能 IAP
  •         IAP_CMD = 2;                                                                   // 设置 IAP 写命令
  •         IAP_ADDRL = addr;                                          // 设置 IAP 低地址
  •         IAP_ADDRH = addr >> 8;                         // 设置 IAP 高地址
  •         IAP_DATA = dat;                                                         // 写 IAP 数据
  •         IAP_TRIG = 0x5a;                                                         // 写触发命令 (0x5a)
  •         IAP_TRIG = 0xa5;                                                         // 写触发命令 (0xa5)
  •         _nop_();
  •         IapIdle();                                                                          // 关闭 IAP 功能
  • }
  • void IapErase(u16 addr)
  • {
  •         IAP_CONTR =WT_24M;                  // 使能 IAP
  •         IAP_CMD = 3;                                                 // 设置 IAP 擦除命令
  •         IAP_ADDRL = addr;                         // 设置 IAP 低地址
  •         IAP_ADDRH = addr >> 8;         // 设置 IAP 高地址
  •         IAP_TRIG = 0x5a;                                 // 写触发命令 (0x5a)
  •         IAP_TRIG = 0xa5;                                 // 写触发命令 (0xa5)
  •         _nop_();                                                                                          //
  •         IapIdle();                                                                          // 关闭 IAP 功能
  • }
  • void Iap_Isp()
  • {
  •         ///系统切换,当读到IAPADD地址存有IAP程序中断向量文件时,写到0X0000地址中,并重启到新的
  •         u8 IapBootCode=0;
  •         u16 i;
  •         for(i=0;i<0x0200;i++)
  •         {
  •                 IapBootCode=IapRead;                //读出ISP中断向量文件块
  •                 IapProgram(ISPadd+i, IapBootCode);     //保存在专用区,IAP返回ISP时使用。备用  ISPadd=0xF400
  •         }
  •         IapBootCode=IapRead(IAPadd);                                                  //读出升级文件IAP保存区起始跳转数据,如果有,表示有升级程序,需要写入起始区,0x0000;写入后就可以使用升级程序了
  •         if(IapBootCode==0x02)
  •         {
  •                 IapErase(0x0000);                                                          //擦除中断向量文件块,准备写入新的IAP中断向量
  •                 for(i=0;i<0x0200;i++)
  •                 {
  •                         IapBootCode=IapRead(IAPadd+i);             //读出IAP中断向量文件块,
  •                         IapProgram(i, IapBootCode);                      //将IAP的中断向量区写入起始位置
  •                 }
  •                 IapErase(IAPadd);                                        //擦除IAP中断向量文件块,防止死循环。
  •                 IAP_CONTR=0x60;                                          //重启,将进入IAP程序
  •         }
  • }
  •    if(CmpMemory(pbuf,&cmd7[0], sizeof(cmd7)-1))      //升级程序包接收转存功能程序
  •          {
  •                 u16 m=0,n=0,tEMChar=0;
  •                   static xdata Buftem[0x0200]={0};  //IAP临时保存
  •                  static u8 Hchar=0;    static u8 Lchar=0;          //临时字高位 //临时字低位
  •                 static bit Saveflag=0;                                        // 存储标志
  •                   ET0=0;
  •                   BeatTimescnt=0;                                                          //收到指令,将心跳时间复位
  •                         RestTimes=0;
  •                         StorageArray(&IAP_num[0],&Uart1_Rxd_buff[0],15);   //转化提取升级包序号
  •                         IAPnum=(u8)atoi(IAP_num);
  •                          pbuf=&Uart1_Rxd_buff[0];                          //接收指令转赋值
  •                         for(n=0;n<Uart1_bufcnt;n++)
  •                         {
  •                                  temchar=*(pbuf+n);
  •                                 if(temchar=='\"')                      //判断“号的数量,
  •                                         m++;
  •                                 if(m==19&&temchar!='\"')   //提取数据包数据,存入EEPARM
  •                                 {
  •                                         if(Saveflag==0)
  •                                         {
  •                                                 if(temchar>='0'&&temchar<='9') //如果接收到的是数字, 转化16进制高位
  •                                                         { Hchar=temchar-0x30;}
  •                                                 else
  •                                                         { Hchar=temchar-87;}          //如果接收到的是字母, 转化16进制高位
  •                                                 Saveflag=!Saveflag;                         //数据保存标志取反
  •                                         }
  •                                         else
  •                                         {
  •                                                 if(temchar>='0'&&temchar<='9') //如果接收到的是数字, 转化16进制高位
  •                                                         { Lchar=temchar-0x30;}
  •                                                 else
  •                                                         { Lchar=temchar-87;}                          //如果接收到的是字母, 转化16进制高位
  •                                                         Saveflag=!Saveflag;                                         //数据保存标志取反
  •                                                         temchar=(Hchar<<4|Lchar);                //高低四位合并
  •                                                         if(IAP_cnt<0x0200)
  •                                                                 {
  •                                                                         Buftem[IAP_cnt]=temchar;//中断向量表临时保存
  •                                                                         //SBUF=Buftem[IAP_cnt];Delay1ms();
  •                                                                 }
  •                                                         else
  •                                                                 {
  •                                                                         IapProgram(IAP_Code1[0]+IAP_cnt-0x0200, temchar);     //写入实际数据内存地址
  •                                                                         //SBUF=IapRead(IAP_Code1[0]+IAP_cnt-0x0200);Delay1ms();        //读出        验证
  •                                                                 }
  •                                                                 IAP_cnt++;
  •                                                                 IAP_ChecksumAcc+=(u32)temchar;
  •                                                                 if(IAP_cnt==IAPLen&&IAP_ChecksumAcc==IAPChecksum)  //写入长度和校验和都相同
  •                                                                 {
  •                                                                                 for(m=0;m<0x0200;m++)
  •                                                                                 {
  •                                                                                         IapProgram(IAPadd+m, Buftem[m]);     //最后写入中断向量文件,防止断电时无法回到基础版
  •                                                                                         //SBUF=IapRead(IAPadd+m);        //读出        验证
  •                                                                                         Delay1ms();
  •                                                                                 }
  •                                                                                 // Delay1ms_cont(5000);//
  •                                                                                 printf("\r\n_num_%bd_len=%u--",IAPnum,IAP_cnt);         Delay1ms_cont(10);
  •                                                                                 printf("\r\n_num_%bd_ChecksumAcc=%lu--",IAPnum,IAP_ChecksumAcc);         Delay1ms_cont(10);
  •                                                                                 printf("\r\n***********The driver upgrade is successful!*************\r\n");        Delay1ms_cont(10);                                                                                                                                                                                                                                                                 //保存相关数据再重启
  •                                                                  //   Save_PortTimes(); //保存端口时间数据
  •                                                                                 IAP_CONTR |= 0x60;
  •                                                                 }
  •                                         }
  •                                 }
  •                         }
  •                         ET0=1;
  •                                 printf("\r\n_num_%bd_len=%u--\r\n",IAPnum,IAP_cnt);         Delay1ms_cont(10);
  •                           printf("_num_%bd_ChecksumAcc=%lu--\r\n",IAPnum,IAP_ChecksumAcc);         Delay1ms_cont(10);
  •                           Delay1ms_cont(1500);
  •         printf("{\"pc\":\"update\",\"mid\":\"%s\",\"res\":\"1\",\"softid\":\"%s\",\"num\":\"%bd\"}",AT_SIMID,&IAP_softid[0],IAPnum+1);
  •                                 return;
  •         }+ J% N- e2 L# {# t, @8 b/ ?

" q2 P$ D  u1 ~- i1 n

该用户从未签到

2#
发表于 2022-6-17 11:16 | 只看该作者
太详细了,Thanks♪(・ω・)ノ

该用户从未签到

3#
发表于 2022-6-17 14:15 | 只看该作者
太详细了,Thanks♪(・ω・)ノ。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-6-18 05:17 , Processed in 0.093750 second(s), 23 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

快速回复 返回顶部 返回列表