第一次來這里分享自己的心得,在電子網轉了很久也沒見到一份精簡的代碼(優秀的代碼不少啊),今天給大家講講STM8的IAP
STM8 IAP可以做什么
做遠程程序更新,我們只需要燒入底層程序(boot),就可以像手機更新系統那樣來更新我們單片機的軟件,當然出廠也是可以連boot和app都燒進去的
這里不多廢話 上傳代碼,不會的留言
單片機源程序如下:
- #include "usart.h"
- #include "string.h"
- ///////////////////////////////////////////////////////////////////
- //函數名稱:main ///
- //功能描述:程序入口,處理程序更新 ///
- //作 者:baishuyuan ///
- //注意事項:程序不可大于APP起始地址 ///
- ///////////////////////////////////////////////////////////////////
- const u8 FLASHKEY = 0xFF;//APP標志位
- #define MAIN_USER_Start_ADDR ((uint32_t)0x8000+0xB00-4)//用戶代碼的起始地址
- #define MIN_USER_Start_ADDR (MAIN_USER_Start_ADDR+4)//用戶代碼的起始地址 字節偏移5個字節
- u16 APP_BIT_ADDR = 0x1000;//用戶代碼的起始地址
- #define PWR_HOLD_GPIO GPIOD
- #define PWR_HOLD_GPIO_Pin GPIO_Pin_0
- /*******************************************************************************
- **函數名稱:void delay(unsigned int ms) Name: void delay(unsigned int ms)
- **功能描述:大概延時
- **入口參數:unsigned int ms 輸入大概延時數值
- **輸出:無
- ******************************************************************************/
- void delay(unsigned int ms)
- {
- unsigned int x , y;
- for(x = ms; x > 0; x--) /* 通過一定周期循環進行延時*/
- for(y = 1000 ; y > 0 ; y--);
- }
- //定義指向函數的指針類型
- typedef void ( *AppMainTyp)(void);
- uint32_t FLASH_ReadWord(uint32_t Address)
- {
- return(*(PointerAttr uint32_t *) (uint16_t)Address);
- }
- #include "stm8l15x_itc.h"
- //重新初始化STM8的中斷向量表 把它重新定義到APP的中斷向量中
- void STM8_HanderIqr_Init(void)
- {
- disableInterrupts(); //關閉中斷
- uint8_t Index;
- FLASH_Unlock(FLASH_MemType_Program);
- for(Index = 1; Index < 0X20;Index++)
- {
- if(FLASH_ReadWord(0X8000+4*Index)!=(0X82000000+MIN_USER_Start_ADDR+Index*4))
- {
- FLASH_ProgramWord(0X8000+4*Index,0X82000000+MIN_USER_Start_ADDR+Index*4);
- }
- }
- FLASH_Lock(FLASH_MemType_Program);
- }
- //跳轉到用戶代碼
- void goto_app(void)
- {
- //重定義STM8的中斷向量
- STM8_HanderIqr_Init();
- //跳轉至APP
- asm("LDW X, SP ");
- asm("LD A, $FF");
- asm("LD XL, A ");
- asm("LDW SP, X ");
- asm("JPF $8B00");
- }
-
- /*******************************************************************************
- **函數名稱:void EEPROM_Byte_Write(unsigned int address , unsigned char date)
- **功能描述:向EEPROM中固定地址寫入一個字節數據
- **入口參數:unsigned int address , unsigned char date
- address :要寫入數據的存儲地址
- date :一個字節數據
- **輸出:無
- *******************************************************************************/
- void EEPROM_Byte_Write(unsigned int address , unsigned char date)
- {
-
- FLASH_SetProgrammingTime(FLASH_ProgramTime_TProg); //設定編程時間為標準編程時間
-
- //MASS 密鑰,解除EEPROM的保護
- FLASH_Unlock(FLASH_MemType_Data);
-
- FLASH_ProgramByte(address , date); //把數據寫入相應的存儲地址
-
- while(FLASH_GetFlagStatus(FLASH_FLAG_EOP) == 1); //等待編程結束
- }
- /**********************************************************************
- * 函數名稱: XOR_Inverted_Check
- * 功能描述:數據的異或取反校驗
- * para:
- inBuf: 需檢測的字符串
- inLen: 所需檢測的字符串長度
- ***********************************************************************/
- u8 XOR_Inverted_Check(unsigned char* inBuf, unsigned char inLen)
- {
- u8 check = 0, i;
- for (i = 0; i < inLen; i++)
- {
- check ^= inBuf[i];
- }
- check = ~check;
- return check;
- }
- u8 Write_App(u8 * Write_Data,u8 Write_Len)
- {
- static u32 addr = MIN_USER_Start_ADDR;//得到flash地址
- u8 i = 0;
- for(i=3;i<(Write_Len-1);i++)
- {
- if(i<(Write_Len-1))
- {
- FLASH_ProgramByte(addr , USART_RX_BUF[i]); //把數據寫入相應的存儲地址
- }
- addr++;//為下次寫入做準備
- }
- if(Write_Len<24)
- {
- EEPROM_Byte_Write(APP_BIT_ADDR,FLASHKEY);
- addr=MAIN_USER_Start_ADDR;//重置flash寫地址
- }
- return i;
- }
-
- void Memset()
- {
- memset(USART_RX_BUF,0,USART_RX_STA);
- USART_RX_STA=0;
- }
- void main()
- {
- u8 STR[]={0x7b,0x05,0xf2,0x03,0x70,'\r','\n','\0'};
- u32 i=0;
- disableInterrupts(); //關閉系統總中斷
- GPIO_DeInit(GPIOD);
- /* Port D in output push-pull 0 */
- GPIO_Init(GPIOD,GPIO_Pin_All, GPIO_Mode_Out_PP_Low_Slow);
- GPIO_Init(PWR_HOLD_GPIO, PWR_HOLD_GPIO_Pin, GPIO_Mode_Out_PP_Low_Slow); //默認all電源為關 D0 推挽-輸出低-高速
- GPIO_SetBits(PWR_HOLD_GPIO, PWR_HOLD_GPIO_Pin);
- CLK_SYSCLKDivConfig(CLK_SYSCLKDiv_1); //內部時鐘為1分頻 = 16Mhz
- FLASH_Unlock(FLASH_MemType_Program);//MASS 密鑰,解除FLASH的保護
- FLASH_Unlock(FLASH_MemType_Data);//MASS 密鑰,解除EEPROM的保護
- FLASH_SetProgrammingTime(FLASH_ProgramTime_TProg); //設定編程時間為標準編程時間
- while(FLASH_GetFlagStatus(FLASH_FLAG_PUL) == RESET);
- //如果用戶代碼更新完成標記存在 則表示當前已經有APP代碼 直接運行
- if(FLASH_ReadByte(APP_BIT_ADDR+1)==0 && FLASH_ReadByte(MIN_USER_Start_ADDR)==0x82)//出廠首次燒錄入口
- {
- // FLASH_ProgramByte(APP_BIT_ADDR , FLASHKEY); //寫入更新完成標志位
- // goto_app(); //運行APP
- }
- else if(FLASH_ReadByte(MIN_USER_Start_ADDR)==0x82 && FLASH_ReadByte(APP_BIT_ADDR)==FLASHKEY && FLASH_ReadByte(APP_BIT_ADDR+1)!=0)//關機重啟設備入口
- {
- // goto_app(); //運行APP
- }
- else//更新APP入口
- {
- // if( FLASH_ReadByte(APP_BIT_ADDR)!=0x00)//標志位清空 這段是APP的
- // {
- // FLASH_EraseByte(APP_BIT_ADDR);
- // }
- // for(i=MAIN_USER_Start_ADDR;i<0x9FF0;i++)//限定地址不可超過0x9FF0,清空flash
- // {
- // FLASH_EraseByte(i); //把數據寫入相應的存儲地址
- // }
- }
- enableInterrupts(); //使能系統總中斷
- //等待USART1接收字符中斷產生,中斷服務函數在 stm8l15x_it.c文件里的 函數 INTERRUPT_HANDLER(USART1_RX_TIM5_CC_IRQHandler,28)
- UART1_Init(9600);//串口初始化
- UART1_TX_STR(STR);//接收第一幀數據
- while(1)
- {
- UART1_TX_STR(STR);//發送測試數據
- delay(1000);//短暫延遲
- i=0xFFFFF;
- while(i>10)
- {
- i--;
- };
- if(UPDATE_APP_OK)UPDATE_APP_OK++;//串口接收完成標志位
- if(UPDATE_APP_OK>5)//接收完成了
- {
- UPDATE_APP_OK=0;
- if((USART_RX_BUF[USART_RX_STA-1])==//CRC
- (XOR_Inverted_Check(USART_RX_BUF,USART_RX_STA-1)))
- {
- if(USART_RX_STA>5 && USART_RX_STA<=USART_RX_LEN)
- {
- if(Write_App(USART_RX_BUF,USART_RX_STA)==(USART_RX_LEN-1))
- {
- UART1_TX_STR(STR);//持續接收
- }
- else
- {
- Memset();
- STR[3]=0x05;
- STR[4]=0x76;
- UART1_TX_STR(STR);//go to app sending data
- // goto_app();//進入更新后的APP
- }
- }
- }
- Memset();
- }
- }
- }
復制代碼
所有資料51hei提供下載:
實驗1boot.7z
(1.68 MB, 下載次數: 115)
2019-10-25 03:45 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|