|
這個(gè)話題,相信很多朋友都有討論和使用。今天我就說說我自已成功使用的方法。首先單片機(jī)需要有這個(gè)IAP功能。STC單片機(jī)在選型時(shí)要注意,不是哪一款都可以,要有IAP功能才行。單片機(jī)通過串口或其它通訊方式,接收升級BIN文件,寫入到內(nèi)部FLASH中,校驗(yàn)通過,執(zhí)行自動(dòng)升級過程。我的升級思想及過程如下。
1:出廠程序:(含有IAP功能)程序起址地址為單片機(jī)內(nèi)存的后半部份,例如0X8000,KEIL中需要設(shè)置一下
1.png (34.79 KB, 下載次數(shù): 102)
下載附件
2022-1-17 14:38 上傳
2.png (26.99 KB, 下載次數(shù): 112)
下載附件
2022-1-17 14:38 上傳
2:為什么要設(shè)置成后半部份,這是因?yàn)槲野亚鞍氩糠莸目臻g留給后續(xù)需要升級時(shí)的程序。
3:因?yàn)橹袛嘞蛄坎糠菰谧钋懊娴膬?nèi)存空間,無法改變,因此我的升級方法比較簡單暴力。當(dāng)接收完校驗(yàn)通過后,直接改變中斷向量部份空間。
4:貼出代碼:
- int main()
- {
- LEDs_up_ten_flag=0; //流水燈開始
- GPIOInit(); //GPIO+時(shí)鐘初始化
- Iap_Isp(); //升級包檢測
- Uart1_Init(); //115200bps@24MHz
- Uart2_Init(); //9600bps@24MHz
- Timer0Init(); //1毫秒@24.000MHz
- printf("\r\n青橙新能源4G控制充電板V00啟動(dòng)成功!\r\n");
- LETCAT1_Init(); //模組初始化及登陸服務(wù)器
- LB0910_Init(); //0910初始化
- BUZZFlag=1;
- WDT_CONTR = 0x27;//使能看門狗,溢出時(shí)間約為5s
- BeatTimescnt=BeatTimesSet-10; //快速上線心跳
- // Read_PortTimes(); //讀出端口時(shí)間數(shù)據(jù) 云端已實(shí)現(xiàn)
- RestTimes=0;
- LEDs_up_ten_flag=1;//流水燈禁止
- while(1)
- {
- LED_show();
- Uart1_drive(); //串口功能函數(shù),主循環(huán)中調(diào)用
- Uart2_drive(); //串口功能函數(shù),主循環(huán)中調(diào)用 HeartbeatServer();
- WDT_CONTR |= 0x10; //清看門狗,否則系統(tǒng)復(fù)位
- 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, //基礎(chǔ)版軟件放置地址 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() //關(guān)閉 IAP功能 并保護(hù)數(shù)據(jù)
- {
- IAP_CONTR = 0; // 關(guān)閉 IAP 功能
- IAP_CMD = 0; // 清除命令寄存器
- IAP_TRIG = 0; // 清除觸發(fā)寄存器
- IAP_ADDRH = 0x80; // 將地址設(shè)置到非 IAP 區(qū)域
- IAP_ADDRL = 0;
- }
- u8 IapRead(u16 addr) // 讀數(shù)據(jù)的操作
- {
- char dat;
- IAP_CONTR = WT_24M; // 使能 IAP
- IAP_CMD = 1; // 設(shè)置 IAP 讀命令
- IAP_ADDRL = addr; // 設(shè)置 IAP 低地址
- IAP_ADDRH = addr >> 8; // 設(shè)置 IAP 高地址
- IAP_TRIG = 0x5a; // 寫觸發(fā)命令 (0x5a)
- IAP_TRIG = 0xa5; // 寫觸發(fā)命令 (0xa5)
- _nop_();
- dat = IAP_DATA; // 讀 IAP 數(shù)據(jù)
- IapIdle(); // 關(guān)閉 IAP 功能
- return dat;
- }
- void IapProgram(u16 addr, u8 dat) //寫數(shù)據(jù)操作。
- {
- IAP_CONTR = WT_24M; // 使能 IAP
- IAP_CMD = 2; // 設(shè)置 IAP 寫命令
- IAP_ADDRL = addr; // 設(shè)置 IAP 低地址
- IAP_ADDRH = addr >> 8; // 設(shè)置 IAP 高地址
- IAP_DATA = dat; // 寫 IAP 數(shù)據(jù)
- IAP_TRIG = 0x5a; // 寫觸發(fā)命令 (0x5a)
- IAP_TRIG = 0xa5; // 寫觸發(fā)命令 (0xa5)
- _nop_();
- IapIdle(); // 關(guān)閉 IAP 功能
- }
- void IapErase(u16 addr)
- {
- IAP_CONTR =WT_24M; // 使能 IAP
- IAP_CMD = 3; // 設(shè)置 IAP 擦除命令
- IAP_ADDRL = addr; // 設(shè)置 IAP 低地址
- IAP_ADDRH = addr >> 8; // 設(shè)置 IAP 高地址
- IAP_TRIG = 0x5a; // 寫觸發(fā)命令 (0x5a)
- IAP_TRIG = 0xa5; // 寫觸發(fā)命令 (0xa5)
- _nop_(); //
- IapIdle(); // 關(guān)閉 IAP 功能
- }
- void Iap_Isp()
- {
- ///系統(tǒng)切換,當(dāng)讀到IAPADD地址存有IAP程序中斷向量文件時(shí),寫到0X0000地址中,并重啟到新的
- u8 IapBootCode=0;
- u16 i;
- for(i=0;i<0x0200;i++)
- {
- IapBootCode=IapRead[i]; //讀出ISP中斷向量文件塊
- IapProgram(ISPadd+i, IapBootCode); //保存在專用區(qū),IAP返回ISP時(shí)使用。備用 ISPadd=0xF400
- }
- IapBootCode=IapRead(IAPadd); //讀出升級文件IAP保存區(qū)起始跳轉(zhuǎn)數(shù)據(jù),如果有,表示有升級程序,需要寫入起始區(qū),0x0000;寫入后就可以使用升級程序了
- if(IapBootCode==0x02)
- {
- IapErase(0x0000); //擦除中斷向量文件塊,準(zhǔn)備寫入新的IAP中斷向量
- for(i=0;i<0x0200;i++)
- {
- IapBootCode=IapRead(IAPadd+i); //讀出IAP中斷向量文件塊,
- IapProgram(i, IapBootCode); //將IAP的中斷向量區(qū)寫入起始位置
- }
- IapErase(IAPadd); //擦除IAP中斷向量文件塊,防止死循環(huán)。
- IAP_CONTR=0x60; //重啟,將進(jìn)入IAP程序
- }
-
- }
- if(CmpMemory(pbuf,&cmd7[0], sizeof(cmd7)-1)) //升級程序包接收轉(zhuǎn)存功能程序
- {
- u16 m=0,n=0,temchar=0;
- static xdata Buftem[0x0200]={0}; //IAP臨時(shí)保存
- static u8 Hchar=0; static u8 Lchar=0; //臨時(shí)字高位 //臨時(shí)字低位
- static bit Saveflag=0; // 存儲標(biāo)志
- ET0=0;
- BeatTimescnt=0; //收到指令,將心跳時(shí)間復(fù)位
- RestTimes=0;
- StorageArray(&IAP_num[0],&Uart1_Rxd_buff[0],15); //轉(zhuǎn)化提取升級包序號
- IAPnum=(u8)atoi(IAP_num);
- pbuf=&Uart1_Rxd_buff[0]; //接收指令轉(zhuǎn)賦值
-
- for(n=0;n<Uart1_bufcnt;n++)
- {
- temchar=*(pbuf+n);
- if(temchar=='\"') //判斷“號的數(shù)量,
- m++;
- if(m==19&&temchar!='\"') //提取數(shù)據(jù)包數(shù)據(jù),存入EEPARM中
- {
- if(Saveflag==0)
- {
- if(temchar>='0'&&temchar<='9') //如果接收到的是數(shù)字, 轉(zhuǎn)化16進(jìn)制高位
- { Hchar=temchar-0x30;}
- else
- { Hchar=temchar-87;} //如果接收到的是字母, 轉(zhuǎn)化16進(jìn)制高位
- Saveflag=!Saveflag; //數(shù)據(jù)保存標(biāo)志取反
- }
- else
- {
- if(temchar>='0'&&temchar<='9') //如果接收到的是數(shù)字, 轉(zhuǎn)化16進(jìn)制高位
- { Lchar=temchar-0x30;}
- else
- { Lchar=temchar-87;} //如果接收到的是字母, 轉(zhuǎn)化16進(jìn)制高位
-
- Saveflag=!Saveflag; //數(shù)據(jù)保存標(biāo)志取反
- temchar=(Hchar<<4|Lchar); //高低四位合并
- if(IAP_cnt<0x0200)
- {
- Buftem[IAP_cnt]=temchar;//中斷向量表臨時(shí)保存
- //SBUF=Buftem[IAP_cnt];Delay1ms();
- }
- else
- {
- IapProgram(IAP_Code1[0]+IAP_cnt-0x0200, temchar); //寫入實(shí)際數(shù)據(jù)內(nèi)存地址
- //SBUF=IapRead(IAP_Code1[0]+IAP_cnt-0x0200);Delay1ms(); //讀出 驗(yàn)證
- }
- IAP_cnt++;
- IAP_ChecksumAcc+=(u32)temchar;
-
- if(IAP_cnt==IAPLen&&IAP_ChecksumAcc==IAPChecksum) //寫入長度和校驗(yàn)和都相同
- {
-
- for(m=0;m<0x0200;m++)
- {
- IapProgram(IAPadd+m, Buftem[m]); //最后寫入中斷向量文件,防止斷電時(shí)無法回到基礎(chǔ)版
- //SBUF=IapRead(IAPadd+m); //讀出 驗(yàn)證
- 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); //保存相關(guān)數(shù)據(jù)再重啟
- // Save_PortTimes(); //保存端口時(shí)間數(shù)據(jù)
- 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;
- }
復(fù)制代碼
|
評分
-
查看全部評分
|