1. 程式人生 > 其它 >Cortex-M3 (NXP LPC1788)之EEPROM儲存器

Cortex-M3 (NXP LPC1788)之EEPROM儲存器

技術標籤:LPC1788

EEPROM是一種非易失性儲存器,主要用於儲存相對少量的資料,如儲存一些系統的配置資訊。通過系統的EEPROM控制模組可以輕鬆的進行EERPOM的儲存控制。

要正確使用EEPROM需要配置掉電暫存器EEPWRDWN確定EEPROM的工作模式,配置EEPROM時鐘分頻器暫存器,使EEPROM工作在375KHZ。下面對EEPROM的讀和寫資料進行介紹。

EEPROM儲存器的訪問有三種操作方式:讀、寫、擦除/程式設計。對EEPROM中寫資料分成兩個單獨的操作:寫和擦除/程式設計。第一步寫操作並不是真正把資料寫入EEPROM的儲存介質中,而只是更新被稱作“頁暫存器”的臨時資料暫存器。只有執行下一步”擦除/程式設計“操作才會真正地更新非易失儲存器。LPC1788共有4K的片內EEPROM,其中EEPROM的每一頁等於頁暫存器大小為64Byte,總共有64頁。大小正好是64*64=4096Byte=4K。首先我們指定的位數,如8、16或者32位,將資料寫入頁暫存器,頁內的地址偏移由EEPROM地址暫存器的第6位決定。如果需要往頁暫存器寫入一串資料,寫完第一個資料後,頁內的偏移地址會自動增加,我們只需把要操作的下一個資料填入EEPROM寫資料暫存器即可。當頁暫存器的64個位元組被寫滿,必須進行程式設計操作,將資料寫入到EEPROM的儲存介質。然後更新頁暫存器的偏移地址。

對於EEPROM的讀操作,首先要向地址暫存器寫入一個12位的地址,高6位為頁的偏移,即我們需要讀哪個頁暫存器。低6位為頁內的偏移,即我們需要讀當前頁的哪個位元組。讀操作也可以自動的對地址暫存器做後遞增,這樣就可以對EEPROM儲存器進行連續的操作而無需每次讀資料都寫入一個新地址。

下面的程式將資訊寫入EEPROM後讀出通過串列埠列印顯示:

#include "LPC1788_REG.h"
#include "uart.h"
 
#define rEECMD          (*(volatile unsigned*)(0x00200080))
#define rEEADDR         (*(volatile unsigned*)(0x00200084))
#define rEEWDATA (*(volatile unsigned*)(0x00200088)) #define rEERDATA (*(volatile unsigned*)(0x0020008C)) #define rEEWSTATE (*(volatile unsigned*)(0x00200090)) #define rEECLKDIV (*(volatile unsigned*)(0x00200094)) #define rEEPWRDWN (*(volatile unsigned*)(0x00200098)) #define rEEINTEN (*(volatile unsigned*)(0x00200FE4))
#define rEEINTCLR (*(volatile unsigned*)(0x00200FD8)) #define rEEINTSET (*(volatile unsigned*)(0x00200FDC)) #define rEEINTSTAT (*(volatile unsigned*)(0x00200FE0)) #define rEEINTSTATCLR (*(volatile unsigned*)(0x00200FE8)) #define rEEINTSTATSET (*(volatile unsigned*)(0x00200FEC)) #define EEPROM_PAGE_SIZE 64 void Init_EEPROM(void); void Write_EEPROM(unsigned char page_num, unsigned char page_offset, char* data, unsigned int count); void Read_EEPROM(unsigned char page_num, unsigned char page_offset, char* data, unsigned int count); char read_buffer[]; char write_buffer[] = {"\n\r\ \t - Name: Nuncle.lee \n\r\ \t - QQ: 23610603 \n\r\ \t - Email: [email protected]\n\r"}; int main(void) { Init_Uart2(); Init_EEPROM(); Write_EEPROM(0, 0, write_buffer, sizeof(write_buffer)); Write_EEPROM(sizeof(write_buffer)/64, sizeof(write_buffer)%64, '\0', 1); Read_EEPROM(0, 0, read_buffer, sizeof(write_buffer)+1); Uart2SendS(read_buffer); return 0; } void Init_EEPROM(void) { unsigned int val=0; rEEPWRDWN = 0; //不處於掉電模式 rEECLKDIV = (CCLK/375000)-1; //設定一個375KHZ的EEPROM時鐘 val = ((((CCLK / 1000000) * 15) / 1000) + 1); //配置等待狀態時間 val |= (((((CCLK / 1000000) * 55) / 1000) + 1) << 8); val |= (((((CCLK / 1000000) * 35) / 1000) + 1) << 16); rEEWSTATE = val; } void Write_EEPROM(unsigned char page_num, unsigned char page_offset, char* data, unsigned int count) { unsigned int i; rEEADDR = (page_offset&0x3f); //確定開始寫的頁內偏移地址 for(i=0; i<count; i++) { rEECMD = 0x3; //8位寫操作 rEEWDATA = *(data+i); while(!(rEEINTSTAT & (0x1<<26))); //等待寫操作完成 page_offset++; if(page_offset >= EEPROM_PAGE_SIZE) //如果當前頁寫滿了64Byte 則啟動 程式設計操作 { rEEINTSTATCLR = 0x1<<28; rEEADDR = (page_num&0x3F)<<6; rEECMD = 0x6; //擦除程式設計 while(!(rEEINTSTAT & (0x1<<28))); //等待程式設計完成 page_offset = 0; page_num++; //寫滿一頁,準備寫下一頁 rEEADDR = 0; //寫滿一頁,從頁的開始寫 } else if(i==count-1) //如果要寫入EPPROM的資料寫完成,啟動程式設計操作 { rEEINTSTATCLR = 0x1<<28; rEEADDR = (page_num&0x3F)<<6; rEECMD = 0x6; //擦除程式設計 while(!(rEEINTSTAT & (0x1<<28))); } } } void Read_EEPROM(unsigned char page_num, unsigned char page_offset, char* data, unsigned int count) { unsigned int i; rEEADDR = (page_num&0x3F)<<6|page_offset&0x3F; //確定讀資料的起始位置,包括頁偏移和頁內的偏移 rEECMD = 0x1<<3; //8位讀,地址自動遞增模式 for(i=0; i<count; i++) { while(!(rEEINTSTAT & (0x1<<26))); //等待上一次讀資料完成 *(data+i) = rEERDATA; page_offset++; if(page_offset >= EEPROM_PAGE_SIZE) //如果當前頁64Byte讀完,準備讀下一頁 { page_offset = 0; page_num++; rEEADDR = (page_num&0x3F)<<6|page_offset&0x3F; rEECMD = 0x1<<3; } } }

程式的執行結果如下圖

在這裡插入圖片描述

程式中,sizeof關鍵字計算出字元陣列的大小,並不包含字串的結束標誌‘\0’。因此還需在sizeof(write_buffer)的位置寫入字串的結束標誌。讀取時讀sizeof(write_buffer)+1個位元組,才能正確的通過串列埠列印資料。當然,也可以自己指定串列埠列印字元的個數,而不用字串結束標誌去判斷。

本文章轉載自 Cortex-M3 (NXP LPC1788)之EEPROM儲存器