線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:2156
推到 Plurk!
推到 Facebook!

有關EEPROM M24C16

答題得分者是:DavidLo
scott123
中階會員


發表:19
回覆:66
積分:52
註冊:2011-08-11

發送簡訊給我
#1 引用回覆 回覆 發表時間:2011-10-24 11:50:05 IP:203.73.xxx.xxx 訂閱
請問有關M24C16
它是一個16K bit的EEPROM為2K byte
在DataSheet中我看它的位置只有八個位元,如圖
這樣不是只能定址到256個位址,要定址到2K至少要11個位元
所以Byte Address要輸入11個位元還是16個位元,還是8個位元就好


DavidLo
高階會員


發表:17
回覆:225
積分:168
註冊:2004-07-21

發送簡訊給我
#2 引用回覆 回覆 發表時間:2011-10-24 15:58:52 IP:122.116.xxx.xxx 訂閱
Please see page 5/20 
Table 3. Device Select Code 1
Note: 1. The most significant bit, b7, is sent first.
2. E0, E1 and E2 are compared against the respective external pins on the memory device.
3. A10, A9 and A8 represent high significant bits of the address.
A10 A9 A8 RW
scott123
中階會員


發表:19
回覆:66
積分:52
註冊:2011-08-11

發送簡訊給我
#3 引用回覆 回覆 發表時間:2011-10-24 16:51:08 IP:203.73.xxx.xxx 訂閱
剛剛突然開竅,對喔,device不就有包括位址的三條線
所以剛好是2k,謝謝

另外請問ack和nack是在SCL什麼情況下接收和答覆的
我的ack 是在SCL 0-->1之後去檢查SDA是不是為0的
我的nack是在SCL 0-->1之前先把SDA設為0的
可是我收到的資料都是0

m24c16_start();
m24c16_write(Write); //device
m24c16_ack();
m24c16_write(0x00); //address
m24c16_ack();
m24c16_write(0x50); //data
m24c16_nack();
m24c16_stop();
_NOP();
_NOP();
m24c16_start();
m24c16_write(Write); //device
m24c16_ack();
m24c16_write(0x00); //address
m24c16_ack();
m24c16_start();
m24c16_write(Read); //device
m24c16_ack();
m24c16_read();
m24c16_nack();
m24c16_stop();
_NOP();


編輯記錄
scott123 重新編輯於 2011-10-24 02:59:59, 註解 無‧
DavidLo
高階會員


發表:17
回覆:225
積分:168
註冊:2004-07-21

發送簡訊給我
#4 引用回覆 回覆 發表時間:2011-10-24 21:30:59 IP:122.126.xxx.xxx 訂閱
細節我就不是那麼清楚!我的I2C是內建的
請參考資料:http://ww1.microchip.com/downloads/en/DeviceDoc/61116D.pdf
1.page 24-26
SDA,SCK需要Pull-up電阻
2.page 24-27
Bus protocol 中 24.3.1.5 有敘述ACK/NAK
scott123
中階會員


發表:19
回覆:66
積分:52
註冊:2011-08-11

發送簡訊給我
#5 引用回覆 回覆 發表時間:2011-10-26 14:31:49 IP:203.73.xxx.xxx 訂閱
關於ACK的資料
我只知道接的那一端要在接完一筆資料回一個LO給傳方
只是搞不懂要在SCK什麼時後傳NACK或是檢查ACK
DavidLo
高階會員


發表:17
回覆:225
積分:168
註冊:2004-07-21

發送簡訊給我
#6 引用回覆 回覆 發表時間:2011-10-27 08:49:06 IP:122.116.xxx.xxx 訂閱
提供參考,希望對你有幫助,在說明一下,我用的是有內建I2C功能,程式Read/Write byte範例如下(from Microchip I2C example)
I2C basic functions call are from Microchip library,如果你不是使用跟我一樣的CPUvoid i2c_WriteByte(int pos,char databyte)
{
unsigned char SlaveAddress;
char i2cData[128];
int DataSz;
char buff[80];
SlaveAddress = 0x50; //0b1010000 Serial EEPROM address
// Send Data to eeprom to program one location
i2cData[0] = (SlaveAddress << 1) | 0; //EEPROM Device Address and WR Command
i2cData[1] = (pos>>8); //eeprom location to program (high address byte)
i2cData[2] = (pos&0xFF); //eeprom location to program (low address byte)
i2cData[3] = databyte;
DataSz = 4;
StartI2C1(); //Send the Start Bit
IdleI2C1(); //Wait to complete
int Index = 0;
while( DataSz )
{
MasterWriteI2C1( i2cData[Index ] );
IdleI2C1(); //Wait to complete
DataSz--;
//ACKSTAT is 0 when slave acknowledge. if 1 then slave has not acknowledge the data.
if( I2C1STATbits.ACKSTAT )
break;
}
StopI2C1(); //Send the Stop condition
IdleI2C1(); //Wait to complete
// wait for eeprom to complete write process. poll the ack status
while(1)
{
i2c_wait(10);
StartI2C1(); //Send the Start Bit
IdleI2C1(); //Wait to complete
MasterWriteI2C1( i2cData[0] );
IdleI2C1(); //Wait to complete
if( I2C1STATbits.ACKSTAT == 0 ) //eeprom has acknowledged
{
StopI2C1(); //Send the Stop condition
IdleI2C1(); //Wait to complete
break;
}
StopI2C1(); //Send the Stop condition
IdleI2C1(); //Wait to complete
}
}
char i2c_ReadByte(int pos)
{
unsigned char SlaveAddress;
char i2cData[128];
int DataSz,i;
char buff[80];
SlaveAddress = 0x50; //0b1010000 Serial EEPROM address
i2cData[0] = (SlaveAddress << 1) | 0; //EEPROM Device Address and WR Command (to write the address)
i2cData[1] = (pos>>8); //eeprom location to read (high address byte)
i2cData[2] = (pos&0xFF); //eeprom location to read (low address byte)
DataSz = 3;
StartI2C1(); //Send the Start Bit
IdleI2C1(); //Wait to complete
//send the address to read from the serial eeprom
int Index = 0;
while( DataSz )
{
MasterWriteI2C1( i2cData[Index ] );
IdleI2C1(); //Wait to complete
DataSz--;
//ACKSTAT is 0 when slave acknowledge. if 1 then slave has not acknowledge the data.
if( I2C1STATbits.ACKSTAT )
break;
}
//now send a start sequence again
RestartI2C1(); //Send the Restart condition
//wait for this bit to go back to zero
IdleI2C1(); //Wait to complete
MasterWriteI2C1( (SlaveAddress << 1) | 1 ); //transmit read command
IdleI2C1(); //Wait to complete
unsigned char retByte;
retByte = MasterReadI2C1();
StopI2C1(); //Send the Stop condition
IdleI2C1(); //Wait to complete
return(retByte);
}

scott123
中階會員


發表:19
回覆:66
積分:52
註冊:2011-08-11

發送簡訊給我
#7 引用回覆 回覆 發表時間:2011-10-27 16:04:05 IP:203.73.xxx.xxx 訂閱
雖然還沒控制成功,先放下來改天再來研究手搖i2c到底怎麼用
不過還是謝謝你
DavidLo
高階會員


發表:17
回覆:225
積分:168
註冊:2004-07-21

發送簡訊給我
#8 引用回覆 回覆 發表時間:2011-10-27 17:12:16 IP:122.116.xxx.xxx 訂閱
找到了51控制的I2C方法,請參考,EEPROM is 24C02

bit IRcvStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no)
{
unsigned char i;
Start_I2c(); /*啟動總線*/
SendByte(sla); /*發送器件地址*/
if(ack==0)return(0);
SendByte(suba); /*發送器件子地址*/
if(ack==0)return(0);
Start_I2c(); /*重新啟動總線*/
SendByte(sla 1);
if(ack==0)return(0);
for(i=0;i {
*s=RcvByte(); /*發送數據*/
Ack_I2c(0); /*發送就答位*/
s ;
}
*s=RcvByte();
Ack_I2c(1); /*發送非應位*/
Stop_I2c(); /*結束總線*/
return(1);
}

void Start_I2c()
{
SDA=1; /*發送起始條件的數據信號*/
_Nop();
SCL=1;
_Nop(); /*起始條件建立時間大於4.7us,延時*/
_Nop();
_Nop();
_Nop();
_Nop();
SDA=0; /*發送起始信號*/
_Nop(); /* 起始條件鎖定時間大於4μs*/
_Nop();
_Nop();
_Nop();
_Nop();
SCL=0; /*鉗住I2C總線,準備發送或接收數據 */
_Nop();
_Nop();
}

void SendByte(unsigned char c)
{
unsigned char BitCnt;

for(BitCnt=0;BitCnt<8;BitCnt ) /*要傳送的數據長度為8位*/
{
if((c< else SDA=0;
_Nop();
SCL=1; /*置時鐘線為高,通知被控器開始接收數據位*/
_Nop();
_Nop(); /*保證時鐘高電平週期大於4μs*/
_Nop();
_Nop();
_Nop();
SCL=0;
}

_Nop();
_Nop();
SDA=1; /*8位發送完後釋放數據線,準備接收應答位*/
_Nop();
_Nop();
SCL=1;
_Nop();
_Nop();
_Nop();
if(SDA==1)ack=0;
else ack=1; /*判斷是否接收到應答信號*/
SCL=0;
_Nop();
_Nop();
}

void Ack_I2c(bit a)
{

if(a==0)SDA=0; /*在此發出應答或非應答信號 */
else SDA=1;
_Nop();
_Nop();
_Nop();
SCL=1;
_Nop();
_Nop(); /*時鐘低電平週期大於4μs*/
_Nop();
_Nop();
_Nop();
SCL=0; /*清時鐘線,鉗住I2C總線以便繼續接收*/
_Nop();
_Nop();
}
scott123
中階會員


發表:19
回覆:66
積分:52
註冊:2011-08-11

發送簡訊給我
#9 引用回覆 回覆 發表時間:2011-11-10 16:38:37 IP:203.73.xxx.xxx 訂閱
找到問題了在哪了
接資料應該是以下格式

I2C_Start();
Send_Comm(Write);
Receive_ACK();
Send_Comm(0x00);
Receive_ACK();
I2C_Start(); ///////////這裡
Send_Comm(Read);
Receive_ACK();
data[1] = read_Comm();
Send_ACK(1);
I2C_Stop();

結果是在restart的地方出問題
start是在scl為1的時後,sda由1變0
在restart的時後,sda之前被拉成0了,拉成1之後,再拉成0
I2C誤認為stop,就這樣,改一下順序就好
scl先拉還是sda先拉,也是很重要的
這樣簡單的動作,害我找了兩個禮拜

不過不知道為什麼, 可以連續寫page write,但是只能一筆一筆讀, 連續讀只有第一筆正確,第二筆之後都是0x00,why
系統時間:2024-04-24 8:16:31
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!