久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 11034|回復(fù): 11
打印 上一主題 下一主題
收起左側(cè)

AVR單片機(jī)BootLoader功能應(yīng)用源碼與詳細(xì)介紹

  [復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
一、    題目:

AVR單片機(jī)BootLoader功能應(yīng)用

二、    特色芯片技術(shù)介紹、使用說明:

AVR單片機(jī)中多數(shù)Mega系列單片機(jī)具有片內(nèi)引導(dǎo)程序自編程功能即BootLoader功能。MCU 通過運(yùn)行一個(gè)常駐FLASH的BootLoader 程序,利用任何可用的數(shù)據(jù)接口讀取代碼后寫入自身的FLASH存儲(chǔ)器中,實(shí)現(xiàn)自編程目的。
BootLoader功能將FLASH程序存儲(chǔ)器其分為應(yīng)用程序區(qū)和引導(dǎo)加載區(qū),通過設(shè)置熔絲位BOOTSZ0和BOOTSZ1可以配置不同大小的引導(dǎo)加載區(qū)空間;通過設(shè)置熔絲位BOOTRST用于設(shè)置復(fù)位向量,當(dāng)BOOTRST未被編程時(shí)器件復(fù)位后從應(yīng)用程序區(qū)首地址開始執(zhí)行,當(dāng)BOOTRST被編程時(shí)器件復(fù)位后從引導(dǎo)區(qū)首地址開始執(zhí)行。在設(shè)置好BOOTSZ0、BOOTSZ1和BOOTRST熔絲位后,需要把BootLoader程序定位并寫入到引導(dǎo)區(qū)中,其首地址由熔絲位ROOTSZ0和BOOTSZ1的編程狀態(tài)決定。在單片機(jī)上電復(fù)位后BootLoader程序開始執(zhí)行,BootLoader程序可以通過USART、TWI或其它方式從計(jì)算機(jī)或其它數(shù)據(jù)源讀取應(yīng)用程序代碼并寫入到應(yīng)用區(qū)中。
avr-libc提供一組C程序接口API來支持BootLoader功能,包含在<avr/boot.h>中,主要幾個(gè)宏有:
boot_page_erase ( address ):擦除FLASH指定頁,address是以字節(jié)為單位的FLASH地址。
boot_page_fill ( address, data ):填充BootLoader 緩沖頁,address為以字節(jié)為單位的緩沖頁地址(對mega8:0~64),而data是長度為兩個(gè)字節(jié)的字?jǐn)?shù)據(jù),因此調(diào)用前address 的增量應(yīng)為2。此時(shí)data的高字節(jié)寫入到高地址,低字節(jié)寫入到低地址。
boot_page_write ( address ):boot_page_write執(zhí)行一次的SPM指令,將緩沖頁數(shù)據(jù)寫入到FLASH指定頁。
boot_rww_enable ( ):RWW區(qū)讀使能,根據(jù)自編程的同時(shí)是否允許讀FLASH存儲(chǔ)器。RWW(Read-While-Write)可同時(shí)讀寫區(qū),在對RWW 區(qū)自編程即頁寫入或頁擦除時(shí),由硬件鎖定RWW區(qū),RWW區(qū)的讀操作被禁止,在對RWW區(qū)的編程結(jié)束后應(yīng)當(dāng)調(diào)用boot_rww_enable()使RWW區(qū)開放。

三、    驅(qū)動(dòng)程序的流程圖

本應(yīng)用以實(shí)際使用的Mega系列單片機(jī)Mega168為例,說明AVR單片機(jī)BootLoader的功能應(yīng)用。BootLoader程序通過串口與計(jì)算機(jī)進(jìn)行通信,執(zhí)行讀、寫以及跳轉(zhuǎn)到FLASH應(yīng)用區(qū)的操作。單片機(jī)與計(jì)算機(jī)通信使用Xmodem通信協(xié)議,Xmodem通信協(xié)議見相關(guān)文檔。其程序流程如下圖。(可見附件中“流程圖.vsd”文件)


四、    驅(qū)動(dòng)程序的源程序

對應(yīng)Mega168的BootLoader程序包括bootloader.c和bootloader.h。
源程序清單如下:(可見附件中“bootloader.c”和“bootloader.h”文件)

五、    設(shè)計(jì)及調(diào)試技巧

BootLoader程序不使用中斷,以查詢的方式讀寫UART數(shù)據(jù)。退出BootLoader程序后程序指針跳轉(zhuǎn)到應(yīng)用程序區(qū)首地址,如果要重新執(zhí)行BootLoader程序以加載應(yīng)用區(qū)程序,必須使用硬件復(fù)位。

六、    典型問題及解決辦法

在程序升級過程中遇到多個(gè)模塊通過485總線連接在一起時(shí),引起多個(gè)模塊響應(yīng),造成誤擦除,升級不能成功,在硬件及Bootloader程序中設(shè)置升級條件,條件滿足時(shí)升級模塊程序,否則跳轉(zhuǎn)到應(yīng)用程序區(qū)。

單片機(jī)源程序如下:
  1. #include "bootloader.h"

  2. //串口初始化
  3. void ComInit(void)                                                               
  4. {                                                                                       
  5.         UBRR0H = BAUDREG/256;                                       
  6.         UBRR0L = BAUDREG%256;                                       
  7.         UCSR0A = 0;                                                               
  8.         UCSR0B = (1 << RXEN0)|(1 << TXEN0);               
  9.         UCSR0C = (1 << UCSZ00)|(1 << UCSZ01);       
  10. }

  11. //使用定時(shí)器1:產(chǎn)生以毫秒為單位的時(shí)間
  12. void TimerInit()                                                      
  13. {                                                                 
  14.         OCR1A  = (unsigned int)(timeclk * (F_CPU  / (1024 * 1000.0f)));
  15.         TCCR1A = 0;                                    
  16.         TCCR1B = (1 << WGM12)|(1 << CS12)|(1 << CS10);
  17. }

  18. //更新一個(gè)Flash頁
  19. void write_one_page(unsigned char *buf)
  20. {
  21.         boot_page_erase(FlashAddr);                  
  22.         boot_spm_busy_wait();
  23.         for(pagptr = 0; pagptr < SPM_PAGESIZE; pagptr += 2)
  24.         {
  25.                 boot_page_fill(pagptr, buf[pagptr] + (buf[pagptr + 1] << 8));
  26.         }
  27.         boot_page_write(FlashAddr);                 
  28.         boot_spm_busy_wait();            
  29. }

  30. //跳轉(zhuǎn)到用戶程序
  31. void quit()
  32. {
  33.         boot_rww_enable();
  34.         (*((void(*)(void))PROG_START))();
  35. }

  36. //寫入數(shù)據(jù)到串口
  37. void WriteCom(unsigned char dat)
  38. {
  39. #if RS485
  40.         RS485Enable();
  41. #endif

  42.         UDR0 = dat;
  43.         while(!(UCSR0A & (1<<TXC0)));
  44.         UCSR0A |= (1<<TXC0);

  45. #if RS485
  46.         RS485Disable();
  47. #endif
  48. }

  49. //等待串口數(shù)據(jù)
  50. unsigned char WaitCom()
  51. {
  52.         while(!(UCSR0A & (1<<RXC0)));
  53.         return UDR0;
  54. }

  55. //向串口輸出字符串
  56. void putstr(const char *str)
  57. {
  58.         while(*str)
  59.                 WriteCom(*str++);
  60.         WriteCom(0x0D);
  61.         WriteCom(0x0A);
  62. }

  63. //CRC校驗(yàn)
  64. void crc16(unsigned char *buf, unsigned char n)
  65. {
  66.         unsigned char j;
  67.         unsigned char i;
  68.         unsigned int crc, t;

  69.         crc = 0;
  70.         for(j = n; j > 0; j--)
  71.         {
  72.             crc = (crc ^ (((unsigned int) *buf) << 8));
  73.                 for(i = 8; i > 0; i--)
  74.                 {
  75.                         t = crc << 1;
  76.                         if(crc & 0x8000)
  77.                                 t = t ^ 0x1021;
  78.                         crc = t;
  79.                 }
  80.                 buf++;
  81.         }
  82.         ch = crc / 256;
  83.         cl = crc % 256;
  84. }

  85. int main(void)
  86. {
  87.         unsigned char cnt;
  88.         unsigned char packNO;
  89.         unsigned char crch, crcl;
  90.         unsigned char li;

  91.         asm volatile("cli": : );

  92.         wdt_enable(WDTO_1S);
  93.         TimerInit();

  94. #if RS485
  95.         DDRREG(RS485PORT) |= (1 << RS485TXEn);
  96.         RS485Disable();
  97. #endif

  98.         ComInit();

  99.         putstr(msg1);

  100.         cnt = TimeOutCnt;
  101.         cl = 0;
  102.         while(1)
  103.         {
  104.                 if(TIFR1 & (1<<OCF1A))   
  105.                 {
  106.                         TIFR1 |= (1 << OCF1A);

  107.                         if(cl == CONNECTCNT)
  108.                                 break;

  109.                         wdt_reset();

  110.                         cnt--;
  111.                         if(cnt == 0)
  112.                         {
  113.                         putstr(msg2);

  114.                                 quit();
  115.                         }
  116.                 }

  117.             if(DataInCom())
  118.             {
  119.                         if(ReadCom() == KEY[cl])
  120.                                 cl++;
  121.                         else
  122.                                 cl = 0;
  123.             }
  124.         }

  125.         putstr(msg3);

  126.         cnt = TimeOutCntC;
  127.         while(1)        
  128.         {
  129.                 if(TIFR1 & (1<<OCF1A))   
  130.                 {
  131.                         TIFR1 |= (1 << OCF1A);
  132.                         WriteCom(XMODEM_RWC) ;

  133.                         wdt_reset();

  134.                         cnt--;
  135.                         if(cnt == 0)
  136.                         {
  137.                         putstr(msg2);
  138.                         quit();
  139.                         }
  140.                 }

  141.                 if(DataInCom())
  142.                 {
  143.                         if(ReadCom() == XMODEM_SOH)
  144.                                 break;
  145.                 }
  146.         }

  147.         TCCR1B = 0;

  148.         packNO = 0;
  149.         bufptr = 0;
  150.         cnt = 0;
  151.         FlashAddr = 0;
  152.         do
  153.         {
  154.                 packNO++;
  155.                 ch =  WaitCom();                     
  156.                 cl = ~WaitCom();
  157.                 if ((packNO == ch) && (packNO == cl))
  158.                 {
  159.                         for(li = 0; li < BUFFERSIZE; li++)     
  160.                         {
  161.                                 buf[bufptr++] = WaitCom();
  162.                         }
  163.                         crch = WaitCom();
  164.                         crcl = WaitCom();
  165.                         crc16(&buf[bufptr - BUFFERSIZE], BUFFERSIZE);
  166.                         if((crch == ch) && (crcl == cl))
  167.                         {
  168.                                 if(FlashAddr < BootStart)            
  169.                                 {
  170.                                         while(bufptr > 0)            
  171.                                         {
  172.                                                 write_one_page(&buf[BUFSIZE - bufptr]);
  173.                                                 FlashAddr += SPM_PAGESIZE;      
  174.                                                 bufptr -= SPM_PAGESIZE;
  175.                                         }
  176.                                 }
  177.                                 else                              
  178.                                 {
  179.                                         bufptr = 0;                        
  180.                                 }

  181.                                 WriteCom(XMODEM_ACK);
  182.                                 cnt = 0;

  183.                                 wdt_reset();

  184.                         }
  185.                         else
  186.                         {
  187.                                 WriteCom(XMODEM_NAK);
  188.                                 cnt++;
  189.                         }
  190.             }
  191. ……………………

  192. …………限于本文篇幅 余下代碼請從51黑下載附件…………
復(fù)制代碼


所有資料51hei提供下載:

AVR單片機(jī)BootLoader功能應(yīng)用.rar (88 KB, 下載次數(shù): 144)




評分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏4 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:25103 發(fā)表于 2018-8-2 23:17 | 只看該作者
謝謝謝謝分享,頂一個(gè)!!
回復(fù)

使用道具 舉報(bào)

板凳
ID:85043 發(fā)表于 2019-3-15 16:26 | 只看該作者
學(xué)習(xí)學(xué)習(xí),
謝謝謝謝分享,頂一個(gè)!!
回復(fù)

使用道具 舉報(bào)

地板
ID:455955 發(fā)表于 2019-10-31 23:28 | 只看該作者
多謝,多謝!
回復(fù)

使用道具 舉報(bào)

5#
ID:108023 發(fā)表于 2019-11-24 16:07 | 只看該作者
謝謝分享  正需要這個(gè)
回復(fù)

使用道具 舉報(bào)

6#
ID:438099 發(fā)表于 2020-2-6 22:12 | 只看該作者
這方面資料比較少,謝謝樓主分享
回復(fù)

使用道具 舉報(bào)

7#
ID:738095 發(fā)表于 2020-7-3 23:56 | 只看該作者
感謝分享,資料很不錯(cuò)
回復(fù)

使用道具 舉報(bào)

8#
ID:413383 發(fā)表于 2020-8-6 22:09 | 只看該作者
感謝分享,資料很不錯(cuò),以前知道用并口專用編程器,可用ISP, JTAG下載程序,單位有一臺(tái)特靈的冷機(jī),有一個(gè)溫度傳感器壞了,廠家說不能自已換,要寫編號和代碼,廠家來的人換上新的溫度傳感器,用一永磁塊靠近傳感器,然后用電腦下載程序,后來把壞的傳感器拆開,里面是ATmega8a和485通信模塊,就奇怪ATmega8a怎么能通過RS232串口下載程序呢,后來查資料才知道要先下載BootLoader引導(dǎo)程序,這個(gè)還不會(huì)用
回復(fù)

使用道具 舉報(bào)

9#
ID:81138 發(fā)表于 2021-1-29 09:30 | 只看該作者
我的Atmega32在Arduino Pro Mini  上無發(fā)刷BootLoader引導(dǎo)程序
回復(fù)

使用道具 舉報(bào)

10#
ID:81138 發(fā)表于 2021-1-29 10:49 | 只看該作者
我的ATmega328適用次方法不
回復(fù)

使用道具 舉報(bào)

11#
ID:128321 發(fā)表于 2024-7-4 14:58 | 只看該作者
我的ATmega328適用次方法不
回復(fù)

使用道具 舉報(bào)

12#
ID:71233 發(fā)表于 2024-7-17 11:02 | 只看該作者
這個(gè)不知道是否適合于ATmega 16.
回復(fù)

使用道具 舉報(bào)

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 亚洲 欧美 日韩 在线 | 日韩中文在线观看 | 亚洲一区二区三区四区在线观看 | 视频1区 | 精品国产三级 | 国产精品欧美一区二区 | 精品久久久久久 | 国产精品不卡一区 | 激情视频网站 | 九色网址 | 亚洲精品久久久蜜桃 | 国产精品一区在线 | 日韩成人一区 | 青青久在线视频 | 91中文 | 91日韩在线 | eeuss国产一区二区三区四区 | 在线观看一区 | 亚洲视频一区在线观看 | yeyeav| 人人人人干 | 亚洲欧美网站 | 中文字幕在线精品 | 二区三区视频 | 国产高清无av久久 | 亚洲国产成人精品一区二区 | 亚洲日韩欧美一区二区在线 | 成人毛片视频免费 | 亚洲成人免费在线 | 久久精品国产一区二区三区不卡 | 高清成人av| www免费视频| 欧美综合国产精品久久丁香 | 欧美日韩中文字幕 | 国产精品一区二区av | 久久爱综合 | 欧美啪啪网站 | 在线日韩视频 | 成人在线视频网站 | 中文字幕在线观看成人 | 盗摄精品av一区二区三区 |