|
技術(shù)交流 | 電路欣賞 | 工控天地 | 數(shù)字廣電 | 通信技術(shù) | 電源技術(shù) | 測控之家 | EMC技術(shù) | ARM技術(shù) | EDA技術(shù) | PCB技術(shù) | 嵌入式系統(tǒng) 驅(qū)動(dòng)編程 | 集成電路 | 器件替換 | 模擬技術(shù) | 新手園地 | 單 片 機(jī) | DSP技術(shù) | MCU技術(shù) | IC 設(shè)計(jì) | IC 產(chǎn)業(yè) | CAN-bus/DeviceNe |
GCC下操作M48的EEPROM到底是怎莫回事?影響量產(chǎn) |
作者:ipman 欄目:單片機(jī) |
unsigned CHAR EEPROM_read(unsigned int uiAddress) { /* 等待上一次寫操作結(jié)束 */ while(EECR & (1<<EEWE)) ; /* 設(shè)置地址寄存器 */ EEAR = uiAddress; /* 設(shè)置EERE 以啟動(dòng)讀操作 */ EECR |= (1<<EERE); /* 自數(shù)據(jù)寄存器返回?cái)?shù)據(jù) */ return EEDR; } void EEPROM_write_l(unsigned int uiAddress, unsigned LONG ucData) { u08 i; u08 data; for(i=0;i<4;i++) { data=(ucData>>(i*8))&0xFF; EEPROM_write(uiAddress+i,data); } } 這個(gè)datasheet中的函數(shù)竟然沒有起作用,我要讀一個(gè)LONG數(shù)值,竟然沒起作用,讀取數(shù)組更不敢想了。 * - 本貼最后修改時(shí)間:2005-11-9 8:44:05 修改者:ipman |
2樓: | >>參與討論 |
作者: zsmbj 于 2005/11/8 20:39:00 發(fā)布:
GCC 說暫時(shí)不支持M48的EEPROM操作! |
3樓: | >>參與討論 |
作者: zj4068 于 2005/11/8 22:43:00 發(fā)布:
把這句這樣寫試試 把EEAR = uiAddress; 這句改成下面的兩句試試看 EEARH = uiAddress >> 8; EEARL = uiAddress & 0x00FF; 問題出在io.h這里的 #if E2END < 0x100 && !defined(__COMPILING_AVR_LIBC__) # undef EEAR # if E2END > 0 # define EEAR _SFR_IO8(0x1E) 因?yàn)閙ega48的E2END為0xff小于0x100,所以這里會(huì)把EEAR定義到_SFR_IO8(0x1E)這里來。如果你編譯的是,ega88或者168,它們的E2END都大于0x100。所以不會(huì)出現(xiàn)這個(gè)問題。 我在幾個(gè)月前就發(fā)現(xiàn)了。好象在avrfreaks上說會(huì)在下一個(gè)版中改掉megax8中EEPROM的這個(gè)bug問題。 |
4樓: | >>參與討論 |
作者: ipman 于 2005/11/8 22:57:00 發(fā)布:
`EEARH' undeclared (first use in this function) |
5樓: | >>參與討論 |
作者: abc2001 于 2005/11/9 12:20:00 發(fā)布:
gcc \note This library will \e not work with the following devices since these devices have the EEPROM IO ports at different locations: - AT90CAN128 - ATMEGA48 - ATmega88 - ATmega165 - ATMEGA168 - ATmega169 - ATMEGA325 - ATMEGA3250 - ATMEGA645 - ATMEGA6450 */ |
6樓: | >>參與討論 |
作者: zsmbj 于 2005/11/9 13:32:00 發(fā)布:
如zj4068 所說,修改后看lss文件是對的了。 不過EEPROM 的讀寫函數(shù)都要自己編寫,不能調(diào)用現(xiàn)成的API函數(shù)。否則地址就會(huì)出錯(cuò)。 ATMEL的IO地址改來改去的真是煩。 寫了個(gè)M48的EEPROM讀寫函數(shù),供你測試: unsigned CHAR EEPROM_read(unsigned int uiAddress) { /* 等待上一次寫操作結(jié)束 */ while(EECR & (1<<EEPE)) ; /* 設(shè)置地址寄存器 */ // EEARH = uiAddress >> 8; EEARL = uiAddress & 0x00FF; /* 設(shè)置EERE 以啟動(dòng)讀操作 */ EECR |= (1<<EERE); /* 自數(shù)據(jù)寄存器返回?cái)?shù)據(jù) */ return EEDR; } void EEPROM_write(unsigned int uiAddress,unsigned CHAR data) { /* 等待上一次寫操作結(jié)束 */ while(EECR & (1<<EEPE)) ; /* 設(shè)置地址寄存器 */ // EEARH = uiAddress >> 8; EEARL = uiAddress & 0x00FF; /* 設(shè)置數(shù)據(jù)寄存器 */ EEDR = data; /* 暫時(shí)關(guān)閉中斷 */ __asm__ __volatile__ ( \ "in __tmp_reg__,__SREG__" "\n\t" \ "cli" "\n\t" \ ); /* 設(shè)置EEPE 以啟動(dòng)寫操作 */ EECR |= (1<<EEMPE); EECR |= (1<<EEPE); /* 恢復(fù)中斷 */ __asm__ __volatile__ ( \ "out __SREG__,__tmp_reg__" "\n\t" \ ); } * - 本貼最后修改時(shí)間:2005-11-9 13:48:02 修改者:zsmbj |
7樓: | >>參與討論 |
作者: 笑蒼天 于 2005/11/9 14:52:00 發(fā)布:
我用過48,提供我試過好用的程序參考 //----------------------------------------------------------- // 函數(shù)編寫: 笑蒼天 // 函數(shù)功能: 從EEPROM中讀指定數(shù)據(jù) // 輸入?yún)?shù):EEPROM地址 ram地址 數(shù)據(jù)長度 // 返回參數(shù):無 //---------------------------------------------------------- void Data_Read(unsigned CHAR ucAddress,unsigned CHAR *Ram_Buf,unsigned CHAR len) { //unsigned CHAR i; while(len--) { // 等待上一次寫操作結(jié)束 while(EECR & (1<<EEPE)) ; // 設(shè)置地址寄存器 //EEARH = 0; EEARL = ucAddress++; // 設(shè)置EERE 以啟動(dòng)讀操作 EECR |= (1<<EERE); // 自數(shù)據(jù)寄存器返回?cái)?shù)據(jù) *Ram_Buf++ = EEDR; } } //----------------------------------------------------------- // 函數(shù)編寫: 笑蒼天 // 函數(shù)功能: 向EEPROM中寫指定數(shù)據(jù) // 輸入?yún)?shù):EEPROM地址 ram地址 數(shù)據(jù)長度 // 返回參數(shù):無 //---------------------------------------------------------- void Data_Write(unsigned CHAR ucAddress,unsigned CHAR *Ram_Buf,unsigned CHAR len) { while(len--) { //Eeprom_Write(ucAddress++,*Ram_Buf++); // 等待上一次寫操作結(jié)束 while(EECR & (1<<EEPE)) ; // 設(shè)置地址和數(shù)據(jù)寄存器 //EEARH = 0; EEARL = ucAddress++; EEDR = *Ram_Buf++; cli(); //disable all interrupts // 置位EEMWE EECR |= (1<<EEMPE); // 置位EEWE 以啟動(dòng)寫操作E EECR |= (1<<EEPE); sei(); //re-enable interrupts } } 基本和版主的相同,只是我傳的地址是無符合字符型,但我想效果是一樣的。 |
8樓: | >>參與討論 |
作者: 農(nóng)民講習(xí)所 于 2005/11/9 15:18:00 發(fā)布:
兩個(gè)疑問 1.為什么在啟動(dòng)寫操作時(shí)要關(guān)中斷? 2.為什么不在操作完后地址歸0? 即使是關(guān)中斷,直接使用CLI、SEI會(huì)有問題的。比如使用該函數(shù)前外部是關(guān)中斷狀態(tài),使用該函數(shù)后,中斷'悄悄'打開了,很危險(xiǎn)的BUG都是這樣產(chǎn)生的。 * - 本貼最后修改時(shí)間:2005-11-9 15:20:58 修改者:農(nóng)民講習(xí)所 |
9樓: | >>參與討論 |
作者: 笑蒼天 于 2005/11/9 15:27:00 發(fā)布:
農(nóng)民講習(xí)所說的很對 我也注意到了,所以很小心的使用這個(gè)函數(shù)。 我又看了版主的關(guān)中斷和恢復(fù)中斷部分,不會(huì)出現(xiàn)所長所說的問題。確實(shí)是高,不愧為版主。 |
10樓: | >>參與討論 |
作者: 農(nóng)民講習(xí)所 于 2005/11/9 15:46:00 發(fā)布:
笑兄還沒回答兩個(gè)問題啊 把參考題倒回答了。:) |
11樓: | >>參與討論 |
作者: zsmbj 于 2005/11/9 15:52:00 發(fā)布:
我的函數(shù)不會(huì)出現(xiàn)農(nóng)民講習(xí)所出現(xiàn)的情況了。 EEPROM有詳細(xì)說明: 1. Wait until EEPE becomes zero. 2. Wait until SELFPRGEN in SPMCSR becomes zero. 3. Write new EEPROM address to EEAR (optional). 4. Write new EEPROM data to EEDR (optional). 5. Write a logical one to the EEMPE bit while writing a zero to EEPE in EECR. 6. Within four clock cycles after setting EEMPE, write a logical one to EEPE. 注意6,所以在設(shè)置這個(gè)bit時(shí)必須關(guān)閉中斷,否則如果剛好在5步后就來一個(gè)中斷,實(shí)際是沒有正確寫入的。 先關(guān)閉中斷,這是對了,在關(guān)閉之前已經(jīng)先讀取了狀態(tài)位的內(nèi)容,最后恢復(fù)的時(shí)候不知只簡單的再打開中斷,而是回復(fù)了狀態(tài)位原來的內(nèi)容,不會(huì)出現(xiàn)被誤打開的情況了。 而笑蒼天的先cli然后再sei則會(huì)出現(xiàn)這個(gè)問題。也是一個(gè)bug。不過趕上的概率非常小。不過還是要修改的好! 第二個(gè)問題就沒有明白“為什么不在操作完后地址歸0?”這有什么用處? |
12樓: | >>參與討論 |
作者: zsmbj 于 2005/11/9 16:05:00 發(fā)布:
其實(shí)“Within four clock cycles ”不單是EEPROM有 如:EEPROM: EECR-----EEMPE WDT: WDTCSR----WDCE SPM: SPMCSR----SELFPRGEN 也都是這個(gè)結(jié)構(gòu)。所以處理的時(shí)候也一定要考慮到中斷的發(fā)生。 所以如果編譯器有函數(shù)還是調(diào)用現(xiàn)出的函數(shù),否則如果自己編寫則一定要仔細(xì)閱讀每一個(gè)bit的意義。否則可能會(huì)出現(xiàn)bug。 其實(shí)ATMEL既然把這個(gè)4個(gè)時(shí)鐘限制的那么死,就應(yīng)該考慮到中斷的發(fā)生。干脆還不如硬件增加一個(gè)設(shè)計(jì),一旦啟動(dòng)了這個(gè)功能后,就硬件自動(dòng)禁止4clock的中斷響應(yīng)。就省的程序里手工禁止了,硬件實(shí)現(xiàn)起來更容易。豈不痛快! 看來ATMEL還是考慮的不周全! * - 本貼最后修改時(shí)間:2005-11-9 16:12:53 修改者:zsmbj |
13樓: | >>參與討論 |
作者: kokan 于 2005/11/9 16:25:00 發(fā)布:
我用如下函數(shù)寫EEmega128 有幾次出現(xiàn)了FF(沒寫成功 void WR_EE(unsigned int addr, unsigned CHAR *data, unsigned CHAR length) { while(length) { while(EECR&(1<<EEWE)); EEAR = addr; EEDR = *data; EECR|= (1<<EEMWE); EECR|= (1<<EEWE); NOP();NOP();NOP(); addr++; data++; length--; } } 是不是修改為如下,就不會(huì)出現(xiàn)寫不成功的現(xiàn)象呢? void WR_EE(unsigned int addr, unsigned CHAR *data, unsigned CHAR length) { while(length) { while(EECR&(1<<EEWE)); EEAR = addr; EEDR = *data; cSREG=SREG; //關(guān)閉 CLI(); EECR|= (1<<EEMWE); EECR|= (1<<EEWE); SREG=cSREG; //再打開 addr++; data++; length--; } } |
14樓: | >>參與討論 |
作者: kokan 于 2005/11/9 16:38:00 發(fā)布:
看了"eeprom.h"的內(nèi)容,發(fā)現(xiàn)也沒有“關(guān)中斷”啊 #include "eeprom.h" EEPROM_WRITE() EEPROM_READ() 是不是也會(huì)出現(xiàn)寫不成功的時(shí)候! |
15樓: | >>參與討論 |
作者: 農(nóng)民講習(xí)所 于 2005/11/9 17:10:00 發(fā)布:
哦,是這樣。 ATMEL的EEPROM原來不是常出現(xiàn)EEPROM丟失問題嗎?解決方案中提到讀或?qū)懲瓴僮鲿r(shí),把地址歸0以犧牲0地址EEPROM的代價(jià)保護(hù)其它位。難道現(xiàn)在改進(jìn)了嗎? |
16樓: | >>參與討論 |
作者: 笑蒼天 于 2005/11/9 17:16:00 發(fā)布:
哦,原來是這個(gè)作用 所長的問題版主答了。:) 我零地址不用,但沒想過把地址歸零來保護(hù)其他EEPROM。 又受教了。 |
17樓: | >>參與討論 |
作者: zsmbj 于 2005/11/9 18:30:00 發(fā)布:
新的版本的沒有0地址的問題了。 To kokan:如果有頻繁的中斷,會(huì)增加EEPROM寫錯(cuò)的幾率。建議還是加上中斷處理吧。 如果是winavr則是有中斷處理的?.lss就知道了。 |
18樓: | >>參與討論 |
作者: qjy_dali 于 2005/11/9 19:10:00 發(fā)布:
AVR的地址變來變?nèi)?一點(diǎn)規(guī)劃都沒有 |
19樓: | >>參與討論 |
作者: ipman 于 2005/11/9 23:54:00 發(fā)布:
感謝各位關(guān)愛,解決了我的一大難題 |
20樓: | >>參與討論 |
作者: zsmbj 于 2005/11/10 8:59:00 發(fā)布:
嚴(yán)重同意qjy_dali。 |
21樓: | >>參與討論 |
作者: hudaidai 于 2005/11/11 15:31:00 發(fā)布:
去下載最新版本的avr-libc源碼,自己編譯生成庫 m48的EEPROM寄存器地址在新版avr-libc中已經(jīng)對了,但EEPROM的庫還是不能用。 其實(shí),avr-libc有個(gè)很簡單的辦法解決m48的EEPROM操作問題,只要設(shè)計(jì)2個(gè)版本的EEPROM庫,然后在頭文件中這樣寫: #ifdef __ATMEGA48__ #define EEPROM_read_byte EEPROM_read_byte_m48 #else #define EEPROM_read_byte EEPROM_read_byte_normal #endif |
22樓: | >>參與討論 |
作者: laoshan 于 2005/11/12 20:21:00 發(fā)布:
我用MEGA88,自己寫一個(gè)讀寫函數(shù),很好用! |
23樓: | >>參與討論 |
作者: zsmbj 于 2005/11/12 20:43:00 發(fā)布:
其實(shí),gcc就應(yīng)該把EEPROM定義在單獨(dú)每個(gè)芯片的頭文件中。 而不應(yīng)該統(tǒng)一定義在io.h中,還有SP,SREG都應(yīng)該在每個(gè)芯片的頭文件中自己定義。說不定ATMEL改來改去的,把這些地址也給改了。那豈不更麻煩呢。 io.h中只有: ………… #elif defined (__AVR_ATmega8__) # include <avr/iom8.h> #elif defined (__AVR_ATmega48__) # include <avr/iom48.h> ………… 這樣不就更清晰了嗎! |
24樓: | >>參與討論 |
作者: AIRWILL 于 2005/11/13 23:29:00 發(fā)布:
我下載到的 2005.10.16版的gccavr 沒有了不支持芯片的這個(gè)說明了,建議大家升級一下 |
25樓: | >>參與討論 |
作者: kokan 于 2005/11/15 18:18:00 發(fā)布:
請問 各位 高手 我這樣做“寫EE”,對不對!// void WR_EE(unsigned int addr, unsigned CHAR *data, unsigned CHAR length) { while(length) { while(EECR&(1<<EEWE)); EEAR = addr; EEDR = *data; cSREG=SREG; //關(guān)閉 CLI(); EECR|= (1<<EEMWE); EECR|= (1<<EEWE); SREG=cSREG; //再打開 addr++; data++; length--; } } |
26樓: | >>參與討論 |
作者: hudaidai 于 2005/11/16 16:58:00 發(fā)布:
To zsmbj: 關(guān)于“其實(shí),gcc就應(yīng)該把EEPROM定義在單獨(dú)每個(gè)芯片的頭文件中! 麻煩之處在于,庫是編譯后的目標(biāo)代碼,而這些SFR定義在庫里面也要使用。如果真的不同mcu定義的地址都不一樣,那么只能為每種CPU做一個(gè)單獨(dú)的.a了。 |
27樓: | >>參與討論 |
作者: zsmbj 于 2005/11/16 17:11:00 發(fā)布:
還是ATMEL胡亂定義帶來的后果! 難怪ATMEL說AVR適合C開發(fā),嘿嘿。要是匯編寫的程序,那換來換去的豈不是要累死了。氣也給氣死了。 |
|
|
免費(fèi)注冊為維庫電子開發(fā)網(wǎng)會(huì)員,參與電子工程師社區(qū)討論,點(diǎn)此進(jìn)入 |
Copyright © 1998-2006 www.udpf.com.cn 浙ICP證030469號 |