向單片機(jī)flash中燒錄自定義數(shù)據(jù)的方法
自己做項(xiàng)目碰到和總結(jié)的一個(gè)問(wèn)題,感覺(jué)挺有用的,貼出來(lái),讓后來(lái)的朋友少走彎路!
關(guān)鍵詞:nrf51822? ?hex文件格式詳解? ?flash讀寫(xiě) hex文件創(chuàng)建和燒錄
引言
? ? 答題器項(xiàng)目生產(chǎn)時(shí),需要在程序燒錄時(shí)附帶生產(chǎn)信息(生產(chǎn)時(shí)間、軟件版本等)。后續(xù)若答題器出問(wèn)題時(shí),能知道是哪個(gè)批次生產(chǎn)的答題器,方便定位問(wèn)題。
技術(shù)可行性
? ? 答題器所用芯片nrf51822flash共256KByte,flash根本用不完,我們可以取一塊沒(méi)用到的flash,燒錄時(shí)把生產(chǎn)信息也寫(xiě)進(jìn)去。
一 HEX文件格式詳解
? ? 全文摘錄如下:
------------------------------------摘錄開(kāi)始-----------------------------------------
? ??Hex文件是可以燒錄到MCU中,被MCU執(zhí)行的一種文件格式。如果用記事本打開(kāi)可發(fā)現(xiàn),整個(gè)文件以行為單位,每行以冒號(hào)開(kāi)頭,內(nèi)容全部為16進(jìn)制碼(以ASCII碼形式顯示)。Hex文件可以按照如下的方式進(jìn)行拆分來(lái)分析其中的內(nèi)容:
例如 “:1000080080318B1E0828092820280B1D0C280D2854”可以被看作“0x10 0x00 0x08 0x00 0x80 0x31 0x8B 0x1E 0x08 0x28 0x09 0x28 0x20 0x28 0x0B 0x1D 0x0C 0x28 0x0D 0x28 0x54”
? ?第一個(gè)字節(jié) 0x10表示本行數(shù)據(jù)的長(zhǎng)度;
? ?第二、三字節(jié) 0x00 0x08表示本行數(shù)據(jù)的起始地址;
? ?第四字節(jié) 0x00表示數(shù)據(jù)類(lèi)型,數(shù)據(jù)類(lèi)型有:0x00、0x01、0x02、0x03、0x04、0x05。
? ? ? ?'00' Data Rrecord:用來(lái)記錄數(shù)據(jù),HEX文件的大部分記錄都是數(shù)據(jù)記錄
? ? ? ?'01' End of File Record: 用來(lái)標(biāo)識(shí)文件結(jié)束,放在文件的最后,標(biāo)識(shí)HEX文件的結(jié)尾
? ? ? ?'02' Extended Segment Address Record: 用來(lái)標(biāo)識(shí)擴(kuò)展段地址的記錄
? ? ? ?'03' Start Segment Address Record:開(kāi)始段地址記錄
? ? ? ?'04' Extended Linear Address Record: 用來(lái)標(biāo)識(shí)擴(kuò)展線性地址的記錄
? ? ? ? '05' Start Linear Address Record:開(kāi)始線性地址記錄
? ?然后是數(shù)據(jù),最后一個(gè)字節(jié) 0x54為校驗(yàn)和。
? ? 校驗(yàn)和的算法為:計(jì)算0x54前所有16進(jìn)制碼的累加和(不計(jì)進(jìn)位),檢驗(yàn)和 = 0x100 - 累加和
? ?在上面的后2種記錄,都是用來(lái)提供地址信息的。每次碰到這2個(gè)記錄的時(shí)候,都可以根據(jù)記錄計(jì)算出一個(gè)“基”地址。對(duì)于后面的數(shù)據(jù)記錄,計(jì)算地址的時(shí)候,都是以這些“基”地址為基礎(chǔ)的。
? ?HEX文件都是由記錄(RECORD)組成的。在HEX文件里面,每一行代表一個(gè)記錄。記錄的基本格式為:
? ? ? ? ? ?Record mark ‘:’
? ? ? ? ? ?Length
Load offset Record type INFO or DATA CHKSUM 1 byte 1 byte 2 bytes 1 byte n bytes 1 byte
? ?看個(gè)例子:
:020000040008F2 :10000400FF00A0E314209FE5001092E5011092E5A3 :00000001FF ? ? ?
? ?對(duì)上面的HEX文件進(jìn)行分析:
? ?第1條記錄的長(zhǎng)度為02,LOAD OFFSET為0000,RECTYPE為04,說(shuō)明該記錄為擴(kuò)展段地址記錄。數(shù)據(jù)為0008,校驗(yàn)和為F2。從這個(gè)記錄的長(zhǎng)度和數(shù)據(jù),我們可以計(jì)算出一個(gè)基地址,這個(gè)地址為(0x0008 << 16)。后面的數(shù)據(jù)記錄都以這個(gè)地址為基地址。
? ?第2條記錄的長(zhǎng)度為10(16),LOAD OFFSET為0004,RECTYPE為00,說(shuō)明該記錄為數(shù)據(jù)記錄。數(shù)據(jù)為FF00A0E314209FE5001092E5011092E5,共16個(gè)BYTE。這個(gè)記錄的校驗(yàn)和為A3。此時(shí)的基地址為0X80000,加上OFFSET,這個(gè)記錄里的16BYTE的數(shù)據(jù)的起始地址就是0x80000 + 0x0004 = 0x80004.
? ?第3條記錄的長(zhǎng)度為00,LOAD OFFSET為0000,TYPE = 01,校驗(yàn)和為FF。說(shuō)明這個(gè)是一個(gè)END OF FILE RECORD,標(biāo)識(shí)文件的結(jié)尾。
在上面這個(gè)例子里,實(shí)際的數(shù)據(jù)只有16個(gè)BYTE:FF00A0E314209FE5001092E5011092E5,其起始地址為0x0004.
------------------------------------摘錄結(jié)束-----------------------------------------
二 創(chuàng)建自己的HEX格式文件,并燒錄檢驗(yàn)
? ? 根據(jù)HEX文件格式詳解,我們可以創(chuàng)建自己的hex格式 文件,方法很簡(jiǎn)單:
? ? ? ? step1:新建文本文件test.txt
? ? ? ? step2:向test.txt文件中寫(xiě)入hex格式數(shù)據(jù)
? ? ? ? step3:把文本文件.txt后綴強(qiáng)制轉(zhuǎn)為.hex文件
? ? ? ? step4:如下圖所示
? ?? ?? ?? ?? ?? ??
?? ? 根據(jù)"HEX文件格式詳解"我們知道,這三行的意思是:向地址為0x04FC00的flash中寫(xiě)入8字節(jié)數(shù)據(jù):0x11 0x22 0x33 0x44 0x55 0x66 0x77 0x88
? ? 燒錄進(jìn)51822,用KEIL的DEBUG模式查看:
? ? ? ? ? ? ? ??? ? BINGO!!!!!!!!!
三 進(jìn)階1:HEX文件加入"注釋信息"
? ? 我們構(gòu)建自己的HEX文件時(shí),有時(shí)希望像代碼一樣能添加"注釋信息",這樣即使很久以后,也能知道這些亂七八糟的二進(jìn)制數(shù),到底代表什么意思。
? ? 從"HEX文件格式詳解"中我們知道,HEX文件格式規(guī)律:
? ? ? ? 1)必須是一整行,包括:?Record mark ‘:’-??Length-Load offset-Record type-INFO
or DATA-CHKSUM,從冒號(hào)到校驗(yàn)值,不間斷;
? ? ? ? 2)第一行必須是地址偏移的基地址,如:020000040008F2
? ? ? ? 3)最后一行必須表示HEX文件結(jié)束,如:00000001FF ? ? ?
? ? ? ? 4)只要我們不破壞這個(gè)規(guī)律即可
? ? 我們完全可以在一行的結(jié)束和整個(gè)hex文件結(jié)束后添加想要的"注釋信息",如下:
?? ? hex能燒錄,且查看對(duì)應(yīng)的flash值正確,BINGO!!!!!!!!!!!!!!!
? ? 這是一個(gè)錯(cuò)誤的示范:
?
四 進(jìn)階2:修改項(xiàng)目的HEX文件,添加生產(chǎn)信息
? ? 我們會(huì)創(chuàng)建HEX文件后,在產(chǎn)品生產(chǎn)過(guò)程中,就可以燒錄帶生產(chǎn)信息的HEX文件。但是這有個(gè)弊端,就是產(chǎn)品在生產(chǎn)時(shí)需要燒錄兩個(gè)HEX文件(項(xiàng)目程序生成的HEX文件和我們自己構(gòu)建帶生產(chǎn)信息的HEX文件)。增加生產(chǎn)時(shí)間,浪費(fèi)時(shí)間金錢(qián)。
? ? 怎么修改項(xiàng)目生成的HEX文件,附帶上我們需要的生產(chǎn)信息呢?
? ? 方法很簡(jiǎn)答,如下圖:
? ??
五 進(jìn)階3:如何讀出HEX燒錄進(jìn)flash的數(shù)據(jù)
? ? 燒錄進(jìn)去后,讀取flash值方法有很多,不同單片機(jī)有自己的讀取flash方法。
? ? 下面介紹一種簡(jiǎn)單粗暴的方法:
? ? 1)C語(yǔ)言const關(guān)鍵字:修飾的數(shù)據(jù)類(lèi)型是常亮類(lèi)型,保存在FLASH中,不可修改
? ? 2)所以我們可定義一個(gè)const類(lèi)型的指針,指向我們已知的flash地址,然后直接讀出來(lái)即可
const uint8_t* pFlashTest = (uint8_t *)(0xFC00); ? ? ?//指針地址強(qiáng)制為0xFC00
int main (void)
{
uint8_t i,FlashRead[8];
for(i = 0;i < 8;i++)
{
FlashRead[i] = *(pFlashTest + i); ? ? ? ? ? ? ?//讀出燒錄進(jìn)去的flash數(shù)據(jù)
}
}
keil的DEBUG模式,測(cè)試如下,讀取結(jié)果和我們寫(xiě)入的一致,BINGO!!!!!!!!!!!!!!!!!!!!
??
六 注意事項(xiàng)
? ? 1)注意你寫(xiě)入flash的位置,不能破壞原有程序,也不能超出你芯片的flash范圍。
?