久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费
標題:
AVR單片機BootLoader功能應用源碼與詳細介紹
[打印本頁]
作者:
waynehuge
時間:
2018-8-2 09:17
標題:
AVR單片機BootLoader功能應用源碼與詳細介紹
一、 題目:
AVR單片機BootLoader功能應用
二、 特色芯片技術介紹、使用說明:
AVR單片機中多數Mega系列單片機具有片內引導程序自編程功能即BootLoader功能。MCU 通過運行一個常駐FLASH的BootLoader 程序,利用任何可用的數據接口讀取代碼后寫入自身的FLASH存儲器中,實現自編程目的。
BootLoader功能將FLASH程序存儲器其分為應用程序區和引導加載區,通過設置熔絲位BOOTSZ0和BOOTSZ1可以配置不同大小的引導加載區空間;通過設置熔絲位BOOTRST用于設置復位向量,當BOOTRST未被編程時器件復位后從應用程序區首地址開始執行,當BOOTRST被編程時器件復位后從引導區首地址開始執行。在設置好BOOTSZ0、BOOTSZ1和BOOTRST熔絲位后,需要把BootLoader程序定位并寫入到引導區中,其首地址由熔絲位ROOTSZ0和BOOTSZ1的編程狀態決定。在單片機上電復位后BootLoader程序開始執行,BootLoader程序可以通過USART、TWI或其它方式從計算機或其它數據源讀取應用程序代碼并寫入到應用區中。
avr-libc提供一組C程序接口API來支持BootLoader功能,包含在<avr/boot.h>中,主要幾個宏有:
boot_page_erase ( address ):擦除FLASH指定頁,address是以字節為單位的FLASH地址。
boot_page_fill ( address, data ):填充BootLoader 緩沖頁,address為以字節為單位的緩沖頁地址(對mega8:0~64),而data是長度為兩個字節的字數據,因此調用前address 的增量應為2。此時data的高字節寫入到高地址,低字節寫入到低地址。
boot_page_write ( address ):boot_page_write執行一次的SPM指令,將緩沖頁數據寫入到FLASH指定頁。
boot_rww_enable ( ):RWW區讀使能,根據自編程的同時是否允許讀FLASH存儲器。RWW(Read-While-Write)可同時讀寫區,在對RWW 區自編程即頁寫入或頁擦除時,由硬件鎖定RWW區,RWW區的讀操作被禁止,在對RWW區的編程結束后應當調用boot_rww_enable()使RWW區開放。
三、 驅動程序的流程圖
本應用以實際使用的Mega系列單片機Mega168為例,說明AVR單片機BootLoader的功能應用。BootLoader程序通過串口與計算機進行通信,執行讀、寫以及跳轉到FLASH應用區的操作。單片機與計算機通信使用Xmodem通信協議,Xmodem通信協議見相關文檔。其程序流程如下圖。(可見附件中“流程圖.vsd”文件)
四、 驅動程序的源程序
對應Mega168的BootLoader程序包括bootloader.c和bootloader.h。
源程序清單如下:(可見附件中“bootloader.c”和“bootloader.h”文件)
五、 設計及調試技巧
BootLoader程序不使用中斷,以查詢的方式讀寫UART數據。退出BootLoader程序后程序指針跳轉到應用程序區首地址,如果要重新執行BootLoader程序以加載應用區程序,必須使用硬件復位。
六、 典型問題及解決辦法
在程序升級過程中遇到多個模塊通過485總線連接在一起時,引起多個模塊響應,造成誤擦除,升級不能成功,在硬件及Bootloader程序中設置升級條件,條件滿足時升級模塊程序,否則跳轉到應用程序區。
單片機源程序如下:
#include "bootloader.h"
//串口初始化
void ComInit(void)
{
UBRR0H = BAUDREG/256;
UBRR0L = BAUDREG%256;
UCSR0A = 0;
UCSR0B = (1 << RXEN0)|(1 << TXEN0);
UCSR0C = (1 << UCSZ00)|(1 << UCSZ01);
}
//使用定時器1:產生以毫秒為單位的時間
void TimerInit()
{
OCR1A = (unsigned int)(timeclk * (F_CPU / (1024 * 1000.0f)));
TCCR1A = 0;
TCCR1B = (1 << WGM12)|(1 << CS12)|(1 << CS10);
}
//更新一個Flash頁
void write_one_page(unsigned char *buf)
{
boot_page_erase(FlashAddr);
boot_spm_busy_wait();
for(pagptr = 0; pagptr < SPM_PAGESIZE; pagptr += 2)
{
boot_page_fill(pagptr, buf[pagptr] + (buf[pagptr + 1] << 8));
}
boot_page_write(FlashAddr);
boot_spm_busy_wait();
}
//跳轉到用戶程序
void quit()
{
boot_rww_enable();
(*((void(*)(void))PROG_START))();
}
//寫入數據到串口
void WriteCom(unsigned char dat)
{
#if RS485
RS485Enable();
#endif
UDR0 = dat;
while(!(UCSR0A & (1<<TXC0)));
UCSR0A |= (1<<TXC0);
#if RS485
RS485Disable();
#endif
}
//等待串口數據
unsigned char WaitCom()
{
while(!(UCSR0A & (1<<RXC0)));
return UDR0;
}
//向串口輸出字符串
void putstr(const char *str)
{
while(*str)
WriteCom(*str++);
WriteCom(0x0D);
WriteCom(0x0A);
}
//CRC校驗
void crc16(unsigned char *buf, unsigned char n)
{
unsigned char j;
unsigned char i;
unsigned int crc, t;
crc = 0;
for(j = n; j > 0; j--)
{
crc = (crc ^ (((unsigned int) *buf) << 8));
for(i = 8; i > 0; i--)
{
t = crc << 1;
if(crc & 0x8000)
t = t ^ 0x1021;
crc = t;
}
buf++;
}
ch = crc / 256;
cl = crc % 256;
}
int main(void)
{
unsigned char cnt;
unsigned char packNO;
unsigned char crch, crcl;
unsigned char li;
asm volatile("cli": : );
wdt_enable(WDTO_1S);
TimerInit();
#if RS485
DDRREG(RS485PORT) |= (1 << RS485TXEn);
RS485Disable();
#endif
ComInit();
putstr(msg1);
cnt = TimeOutCnt;
cl = 0;
while(1)
{
if(TIFR1 & (1<<OCF1A))
{
TIFR1 |= (1 << OCF1A);
if(cl == CONNECTCNT)
break;
wdt_reset();
cnt--;
if(cnt == 0)
{
putstr(msg2);
quit();
}
}
if(DataInCom())
{
if(ReadCom() == KEY[cl])
cl++;
else
cl = 0;
}
}
putstr(msg3);
cnt = TimeOutCntC;
while(1)
{
if(TIFR1 & (1<<OCF1A))
{
TIFR1 |= (1 << OCF1A);
WriteCom(XMODEM_RWC) ;
wdt_reset();
cnt--;
if(cnt == 0)
{
putstr(msg2);
quit();
}
}
if(DataInCom())
{
if(ReadCom() == XMODEM_SOH)
break;
}
}
TCCR1B = 0;
packNO = 0;
bufptr = 0;
cnt = 0;
FlashAddr = 0;
do
{
packNO++;
ch = WaitCom();
cl = ~WaitCom();
if ((packNO == ch) && (packNO == cl))
{
for(li = 0; li < BUFFERSIZE; li++)
{
buf[bufptr++] = WaitCom();
}
crch = WaitCom();
crcl = WaitCom();
crc16(&buf[bufptr - BUFFERSIZE], BUFFERSIZE);
if((crch == ch) && (crcl == cl))
{
if(FlashAddr < BootStart)
{
while(bufptr > 0)
{
write_one_page(&buf[BUFSIZE - bufptr]);
FlashAddr += SPM_PAGESIZE;
bufptr -= SPM_PAGESIZE;
}
}
else
{
bufptr = 0;
}
WriteCom(XMODEM_ACK);
cnt = 0;
wdt_reset();
}
else
{
WriteCom(XMODEM_NAK);
cnt++;
}
}
……………………
…………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
0.png
(48.38 KB, 下載次數: 138)
下載附件
2018-8-2 15:30 上傳
所有資料51hei提供下載:
AVR單片機BootLoader功能應用.rar
(88 KB, 下載次數: 144)
2018-8-2 09:16 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
作者:
huaishang
時間:
2018-8-2 23:17
謝謝謝謝分享,頂一個!
作者:
xinghai333
時間:
2019-3-15 16:26
學習學習,
謝謝謝謝分享,頂一個!
作者:
yys3210
時間:
2019-10-31 23:28
多謝,多謝!
作者:
dm800s
時間:
2019-11-24 16:07
謝謝分享 正需要這個
作者:
幸運大亨
時間:
2020-2-6 22:12
這方面資料比較少,謝謝樓主分享
作者:
ziteng00
時間:
2020-7-3 23:56
感謝分享,資料很不錯
作者:
hulilanyua
時間:
2020-8-6 22:09
感謝分享,資料很不錯,以前知道用并口專用編程器,可用ISP, JTAG下載程序,單位有一臺特靈的冷機,有一個溫度傳感器壞了,廠家說不能自已換,要寫編號和代碼,廠家來的人換上新的溫度傳感器,用一永磁塊靠近傳感器,然后用電腦下載程序,后來把壞的傳感器拆開,里面是ATmega8a和485通信模塊,就奇怪ATmega8a怎么能通過RS232串口下載程序呢,后來查資料才知道要先下載BootLoader引導程序,這個還不會用
作者:
cyrs
時間:
2021-1-29 09:30
我的Atmega32在Arduino Pro Mini 上無發刷BootLoader引導程序
作者:
cyrs
時間:
2021-1-29 10:49
我的ATmega328適用次方法不
作者:
yjwpm
時間:
2024-7-4 14:58
我的ATmega328適用次方法不
作者:
lmn2005
時間:
2024-7-17 11:02
這個不知道是否適合于ATmega 16.
歡迎光臨 (http://m.zg4o1577.cn/bbs/)
Powered by Discuz! X3.1
主站蜘蛛池模板:
99re66在线观看精品热
|
精品国产一区二区三区性色
|
一级a性色生活片久久毛片 午夜精品在线观看
|
99久久精品国产一区二区三区
|
91天堂网
|
aa级毛片毛片免费观看久
|
久久久人
|
久久精品欧美一区二区三区麻豆
|
国产美女视频
|
久久综合久久综合久久
|
欧美美女被c
|
精品国产欧美一区二区三区不卡
|
日韩久久中文字幕
|
久久99这里只有精品
|
美女黄视频网站
|
日韩中文在线观看
|
成人自拍av
|
天堂亚洲
|
精品一二区
|
影音先锋成人资源
|
亚洲小视频在线观看
|
99re超碰
|
九九久久这里只有精品
|
国产视频三区
|
在线超碰
|
日本免费一区二区三区四区
|
国产成人jvid在线播放
|
精品久久免费
|
最新一级毛片
|
伊人色综合久久天天五月婷
|
天天干视频
|
久久久久久国产免费视网址
|
国产网站在线
|
色约约视频
|
欧美精品在线免费观看
|
在线观看特色大片免费网站
|
精品一区二区在线观看
|
91精品国产一区二区
|
精品欧美乱码久久久久久
|
国产精品成人69xxx免费视频
|
亚洲欧美日韩一区
|