mini2440----keil for AMR之IIC讀寫(xiě)EEPROM(AT24C08)
文章大綱:
一:EEPROM芯片介紹(包括各種讀寫(xiě)的時(shí)序與管腳定義)
二:S3C2440中對(duì)于IIC需要配置的寄存器
三:IIC成功讀寫(xiě)EEPROM的程序(光盤的那個(gè)IIC讀寫(xiě)程序真心對(duì)初學(xué)者不好理解)
一:EEPROM芯片介紹
在這里分析AT24C02A/AT24C04A/AT24C08A,對(duì)于其他不同型號(hào)的EEPROM芯片要根據(jù)具體手冊(cè)進(jìn)行分析。他們的大小分別是2K(256*8)/4K(512*8)/8K(1024*8)因此可以看出實(shí)際大小是256/512/1024byte,。對(duì)于AT24C02A的三位地址線都是寫(xiě)死的,因?yàn)樵谶M(jìn)行讀寫(xiě)操作時(shí)使用8位地址已經(jīng)足夠,所以三位地址線寫(xiě)死作為片選,對(duì)于AT24C08A的三位地址線第一位必須寫(xiě)死,后兩位可以作為內(nèi)部頁(yè)地址。因?yàn)锳T24C08A的大小超過(guò)了256byte,8為尋址,已經(jīng)沒(méi)法使用到芯片內(nèi)所有的空間。因此對(duì)于后面兩位也就可以由程序決定了。
寫(xiě)EEPROM有兩種,(在寫(xiě)數(shù)據(jù)的時(shí)候,AMR9作為主設(shè)備,EEPROM是從設(shè)備)
第一種寫(xiě)byte方式:
寫(xiě)一個(gè)byte實(shí)際上需要發(fā)送三次數(shù)據(jù)。在這個(gè)過(guò)程中,主設(shè)備為發(fā)送狀態(tài)。第一個(gè)數(shù)據(jù)——設(shè)備地址。第二數(shù)據(jù)——ARM9想寫(xiě)的EEPROM中的地址。第三個(gè)數(shù)據(jù)——想寫(xiě)入到EEPROM中的具體數(shù)據(jù)。最后停止。
第二種寫(xiě)頁(yè)方式:
自我感覺(jué)其實(shí)寫(xiě)頁(yè)與寫(xiě)byte應(yīng)該是一致的,第一個(gè)數(shù)據(jù)——設(shè)備地址。第二數(shù)據(jù)——ARM9想寫(xiě)的EEPROM中的地址(但是這個(gè)地址是首地址。AT24C02一頁(yè)是8byte,AT24C04/08一頁(yè)是16byte。所以在寫(xiě)頁(yè)的時(shí)候最多寫(xiě)一頁(yè)的大小,如果寫(xiě)太多就會(huì)重新又從首地址開(kāi)始,以前寫(xiě)的會(huì)被覆蓋掉。)。第三、四、······數(shù)據(jù)——就是你想寫(xiě)入到EEPROM中的數(shù)據(jù)。最后停止
讀EEPROM中的數(shù)據(jù)
第一種讀當(dāng)前地址數(shù)據(jù)
主設(shè)備仍然是ARM9,從設(shè)備是EEPROM,但是要注意主設(shè)備的狀態(tài),有時(shí)候會(huì)是發(fā)送狀態(tài),有時(shí)候會(huì)是接收狀態(tài)
第一個(gè)數(shù)據(jù)——(主設(shè)備現(xiàn)在處于發(fā)生狀態(tài))發(fā)送從設(shè)備地址,并且把主設(shè)備配置為接收狀態(tài)。
第二個(gè)數(shù)據(jù)——(主設(shè)備處于接收狀態(tài))ARM9接收數(shù)據(jù),注意此時(shí)是NO ACK。再停止。(要在產(chǎn)生NO ACK后在讀取數(shù)據(jù)這時(shí)數(shù)據(jù)會(huì)是穩(wěn)定的。網(wǎng)上有問(wèn)為什么在讀IIC最后需要讀兩次,我自己實(shí)驗(yàn)了,只需要最后一次就行,)
第二種隨機(jī)讀數(shù)據(jù)方式
第一個(gè)數(shù)據(jù)——(主設(shè)備處于發(fā)生狀態(tài)),發(fā)送一個(gè)從設(shè)備地址。第一個(gè)設(shè)備地址是用來(lái)從設(shè)備匹配的,也在文檔中被稱為a “dummy” byte write sequence
第二個(gè)數(shù)據(jù)——(主設(shè)備處于發(fā)生狀態(tài)),發(fā)送一個(gè)想讀取數(shù)據(jù)在EEPROM中的地址。
第三個(gè)數(shù)據(jù)——(主設(shè)備處于發(fā)生狀態(tài)),發(fā)送一個(gè)從設(shè)備地址。這是特定要求這樣發(fā)送的。。(在這里主設(shè)備會(huì)被配置為接收狀態(tài)),這此發(fā)送設(shè)備地址是用來(lái)同時(shí)調(diào)整主設(shè)備狀態(tài)的。
第四個(gè)數(shù)據(jù)——(主設(shè)備處于接收狀態(tài))需要讀的數(shù)據(jù)。也是一個(gè)NO ACK,與讀當(dāng)前地址類似。最后再停止。
第三種讀序列地址
與讀當(dāng)前數(shù)據(jù)有些類似。
第一個(gè)數(shù)據(jù)——(主設(shè)備處于發(fā)送狀態(tài)),發(fā)出設(shè)備地址,并配置主設(shè)備為接收狀態(tài)。為后面接收數(shù)據(jù)準(zhǔn)備
第二、三···個(gè)數(shù)據(jù)——(主設(shè)備處于接收狀態(tài)),前面每個(gè)數(shù)據(jù)都會(huì)發(fā)送ACK,最后一個(gè)數(shù)據(jù)是一個(gè)NO ACK。
再停止。
以上這些,主要要注意主設(shè)備狀態(tài)的調(diào)整,以及為NO ACK時(shí)的處理,后面有事例程序,能夠比較清楚的看到怎么進(jìn)行處理的。
二:S3C2440中對(duì)于IIC需要配置的寄存器
GPECON,主要是把這個(gè)GPIO配置為IIC模式。
IICCON:其中[0]---[3]與[6]共同決定IIC總線的時(shí)鐘頻率。
[4]是一個(gè)中斷標(biāo)志位,我們?nèi)绻麤](méi)有用中斷方式的話,應(yīng)該可以通過(guò)查詢這一位進(jìn)行。(我用的中斷,沒(méi)有具體自己實(shí)踐)
[5]IIC中斷使能。[7]是否發(fā)送ACK。這一位在后面讀數(shù)據(jù)的時(shí)候,要注意進(jìn)行改變。
IICSTAT:這個(gè)寄存器主要是一些標(biāo)志為,不需要配置,主要要配置的是這幾位。
[4]使能IIC數(shù)據(jù)線的,使其能夠發(fā)送數(shù)據(jù)。
[5]啟動(dòng)和停止IIC,1啟動(dòng)。0停止。
[6-7]是配置AMR9的狀態(tài)的,一般CPU是一個(gè)主設(shè)備的角色。只有在兩塊CPU進(jìn)行相互通信的時(shí)候,可能把他配置成為一個(gè)從設(shè)備的狀態(tài)。所以在我們實(shí)驗(yàn)中,ARM9全部都是處于主設(shè)備的角色。
IICADD是CPU做從設(shè)備的時(shí)候,給他配置的從設(shè)備地址,這里可以不用配置。
IICDS:數(shù)據(jù)移位寄存器。發(fā)送數(shù)據(jù)就是把數(shù)據(jù)發(fā)到這個(gè)寄存器。接收數(shù)據(jù)就是從這個(gè)寄存器中去取數(shù)據(jù)。
如果使用中斷當(dāng)然還得配置INTMSK,打開(kāi)IIC中斷。
三:IIC成功讀寫(xiě)EEPROM的程序
首先要對(duì)程序有幾點(diǎn)說(shuō)明:
1:f_GetACK必須是volatile類型,因?yàn)樵谥袛嘀懈淖兞酥担蝗恢当槐4嬖诰彺嬷辛?,最后檢測(cè)時(shí),不能真正讀到其值。詳細(xì)見(jiàn)
在C編程中使用到的幾個(gè)重要關(guān)鍵字之一volatile2:IIC的中斷總是在ACK周期內(nèi),產(chǎn)生的,我沒(méi)有貼出操作流程圖,ARM9文檔中IIC這章已經(jīng)清楚給出。所以在有ACK的那些數(shù)據(jù)發(fā)送與接收都可以用中斷操作,但是從讀數(shù)據(jù)的后接收數(shù)據(jù)來(lái)看,由于是NO ACK,所以就沒(méi)有用中斷操作了,而且自己進(jìn)行了一個(gè)延時(shí)。在讀數(shù)據(jù)。copy
-
staticU8_iicData[IICBUFSIZE];
-
staticvolatileintf_GetACK;
view plaincopy
-
voidTest_Iic(void)
-
{
-
unsignedinti,j,save_E,save_PE;
-
staticU8data[256];
-
-
Uart_Printf("\nIICTest(Interrupt)usingAT24C02\n");
-
-
save_E=rGPECON;
-
save_PE=rGPEUP;
-
IIC_Init();//初始化IIC必須的一些寄存器
-
Uart_Printf("WritetestdataintoAT24C02\n");
-
-
for(i=0;i<48;i++)
-
Wr24C080(0xa0,i,i);//slvaddr,addr,data
-
-
-
for(i=0;i<48;i++)
-
data[i]=0;
-
-
Uart_Printf("ReadtestdatafromAT24C02\n");
-
-
for(i=0;i<48;i++)
-
Rd24C080(0xa0,i,&(data[i]));
-
-
//Linechanged0~f
-
for(i=0;i<3;i++)
-
{
-
for(j=0;j<16;j++)
-
Uart_Printf("%2x",data[i*16+j]);
-
Uart_Printf("\n");
-
}
-
rINTMSK|=BIT_IIC;
-
rGPEUP=save_PE;
-
rGPECON=save_E;
-
}
copy
-
voidIIC_Init(void)
-
{
-
//配置GPE端口為IIC功能
-
rGPECON&=~(0xF<<28);
-
rGPECON|=(1<<31)|(1<<29);
-
//產(chǎn)生ACK,IIC中斷使能,頻率200KHz
-
rIICCON=0;
-
rIICCON|=(7)|(1<<5)|(1<<7);
-
//模式為主發(fā)送,使能Rx/Tx(不管是讀還是寫(xiě)初始化都為主發(fā)送)
-
rIICSTAT|=(3<<6)|(1<<4);
-
rIICADD=0x10;//從地址表示2440作為從設(shè)備的時(shí)候的地址,
-
//在這里2440是作為一個(gè)主設(shè)備存在的,所以沒(méi)有作用。
-
//EEPROM的標(biāo)識(shí)符為1010
-
//控制字節(jié),其中高四位為器件類型標(biāo)識(shí)符,后三位作為片選
-
//最后一位決定讀寫(xiě),0是讀,1是寫(xiě)。
-
-
//IIC傳輸中斷開(kāi)啟
-
rINTMOD=0x0;
-
rINTMSK&=~BIT_IIC;
-
pISR_IIC=(unsigned)IicInt;
-
}
copy
-
//*************************[Wr24C080]****************************
-
voidWr24C080(U32slvAddr,U32addr,U8data)
-
{
-
f_GetACK=0;
-
rIICDS = slvAddr; //發(fā)送第一個(gè)數(shù)