|
發布時間: 2019-7-25 15:37
正文摘要:STC89C52和AT24C02進行I2C通訊時,STC89C52主機向從機AT24C02隨便發個設備地址,都能讀寫數據,是怎么回事喔? 具體情況:我的AT24C02的設備地址線A0 A1 A2都接地了的,數據手冊上說的AT24C02的設備地址格式:(前 ... |
Y_G_G 發表于 2019-8-3 16:22 感謝你的耐心回復喔!不準備糾結這個問題了,感覺還是我買的芯片有問題,后面有機會再換換芯片試試 |
cjm82 發表于 2019-8-4 02:32 好的,thank you!! |
Y_G_G 發表于 2019-8-3 16:22 我在面包板上接了兩個AT24C02也試了下的,兩片AT24C02芯片的硬件地址A0A1A2設置為不同,我在程序上分別向兩塊芯片發送數據,也是上面那種現象,A0A1A2隨意改變,都能向芯片正確寫入數據,并且正確讀出。 同時我又發現一個詭異的現象,就是向第一塊芯片的一個固定地址(程序里我選的儲存地址是0x01,比如寫個數據為0x27)寫入數據,但是我沒有向第二塊芯片的儲存地址0x01寫入數據,接下來我直接讀第二塊芯片儲存地址0x01里的數據,讀出來的數據居然和我剛剛向第一塊芯片儲存地址0x01寫入的數據相同(為了避免巧合我多次改變向第一塊芯片寫入的數據,發現實驗現象和上面相同),也就是在向一塊芯片寫入數據時,兩塊芯片的相同儲存地址里的內容都被寫入數據了(A0A1A2隨意改變也是這樣)。 |
張松松 發表于 2019-7-30 14:05 #define SCK_High GPIO_SetBits(GPIOA,GPIO_Pin_1) #define SCK_Low GPIO_ResetBits(GPIOA,GPIO_Pin_1) #define SDA_High GPIO_SetBits(GPIOA,GPIO_Pin_3) #define SDA_Low GPIO_ResetBits(GPIOA,GPIO_Pin_3) #define SCK_read GPIOA->IDR & GPIO_Pin_1 #define SDA_read GPIOA->IDR & GPIO_Pin_3 typedef enum { FALSE = 0, TRUE = !FALSE } bool; void I2C_delay() { u8 i=100; while(i) { i--; } } bool I2C_Start() { SDA_High; SCK_High; I2C_delay(); if(!SDA_read) { return FALSE; //SDA線為低電平則總線忙,退出 } SDA_Low; I2C_delay(); if(SDA_read) { return FALSE; //SDA線為高電平則總線出錯,退出 } SDA_Low; I2C_delay(); return TRUE; } void I2C_Stop() { SCK_Low; I2C_delay(); SDA_Low; I2C_delay(); SCK_High; I2C_delay(); SDA_High; I2C_delay(); } void I2C_Ack() { SCK_Low; I2C_delay(); SDA_Low; I2C_delay(); SCK_High; I2C_delay(); SCK_Low; I2C_delay(); } void I2C_NoAck() { SCK_Low; I2C_delay(); SDA_High; I2C_delay(); SCK_High; I2C_delay(); SCK_Low; I2C_delay(); } bool I2C_WaitAck() //返回TRUE有ACK,FALSE無ACK { SCK_Low; I2C_delay(); SDA_High; I2C_delay(); SCK_High; I2C_delay(); if(SDA_read) { SCK_Low; return FALSE; } SCK_Low; return TRUE; } void I2C_SendByte(u8 SendByte) //數據從高位到低位// { u8 i=8; while(i--) { SCK_Low; I2C_delay(); if(SendByte&0x80) { SDA_High; } else { SDA_Low; } SendByte<<=1; I2C_delay(); SCK_High; I2C_delay(); } SCK_Low; } u8 I2C_ReadByte(void) //數據從高位到低位// { u8 i=8; u8 data=0; SDA_High; while(i--) { data<<=1; SCK_Low; I2C_delay(); SCK_High; I2C_delay(); if(SDA_read) { data|=0x01; } } SCK_Low; return data; } //===================24C02 讀寫程序=========================== bool AT24C02_WriteByte(u8 SendByte, u8 Address) { if(!I2C_Start()) { return FALSE; } I2C_SendByte(0xa0); if(!I2C_WaitAck()) { I2C_Stop(); return FALSE; } I2C_SendByte(Address); I2C_WaitAck(); I2C_SendByte(SendByte); I2C_WaitAck(); I2C_Stop(); Delay(15); //加個延時等待寫完 return TRUE; } bool AT24C02_ReadByte(u8* data,u8 Adress) { if(!I2C_Start()) //如果總線忙,則返回失敗. return FALSE; I2C_SendByte(0xa0); if(!I2C_WaitAck()) //如果沒有得到應答,則返回失敗. { I2C_Stop(); return FALSE; } I2C_SendByte(Adress); I2C_WaitAck(); I2C_Start(); I2C_SendByte(0xa1); I2C_WaitAck(); *data = I2C_ReadByte(); I2C_Stop(); return TRUE; } 這個是我以前學I2C時的程序,和24C02的程序,不過是32的,你稍微改下,用在51也很簡單,24C02的兩個函數也就學習的時候用過下,后面基本沒碰過.但前面的I2C程序我用過好幾次,沒發現問題.你可以參考下. |
| 硬件電路上傳看一下了 |
張松松 發表于 2019-8-3 10:09 你能寫入和讀取,就說明讀寫的函數是正確的了 A0 A1 A2 這幾個位在多個24C02并聯使用時才會用到的,在24C02中,你只能改動R/W位,其它位是不能動的,1010是固定不變的,A0 A1 A2 這個是和24C02三個引腳的邏輯對應的,你接地了,就是000了,不能改,改了就找不到地址了 如果你是A0接了高電平,那么這三個應該就是:100 |
Y_G_G 發表于 2019-7-31 08:41 對了,我用的芯片型號是,ATMEL 711 24C02 PU27 D |
Y_G_G 發表于 2019-7-31 08:41 你好,我用程序驗證時,在I2C總線上只用一個AT24C02芯片,用的模擬I2C通訊;先寫入一個數據到一個固定的地址,然后讀取并顯示在數碼管上,下載運行時發現讀取的結果正常,斷電再上電,結果依然正常,然后去掉寫入數據程序部分,只留下讀取數據程序部分,再下載到開發板,發現讀取的數據還是和之前寫入的一樣,斷電再上電,讀取結果依然正常,<<同時我又嘗試將發送的器件地址改變,僅改變A0/A1/A2三位的數值,使它和硬件上連接的地址不相同,我開發板上的AT24C02芯片的A0A1A2都接地了的,重復上面的驗證過程,發現結果還是一樣,寫入的數據和讀取的數據相同, 但是 “將器件地址的高四位,也就是AT24C02固定的那四位1010, 1010 A0 A1 A2 R/W 也改變的話,就會讀取和寫入失敗。” >> |
|
芯片有問題的情況并不多 你得寫一個驗證的程序,兩個按鍵:寫入并顯示,讀取并顯示,地址可以是固定的某個地址 先向一個地址寫入一個數據并顯示 然后,斷電,開機,不要寫入,直接讀取,數據是對的話,你的IIC代碼就是對的 驗證好程序之后,其它的再說 |
yzwzfyz 發表于 2019-7-26 09:18 不能確定是不是目標設備發出的0/1, 我總線上就用了一個AT24C02芯片,這樣是不是可以懷疑是芯片有問題 |
cjm82 發表于 2019-7-25 21:58 /** * @brief 主機檢測從機應答 * @param none * @retval return(1)應答,return(0)非應答 */ bit Test_ACK() { SCL=1; //拉高SCL線 Delay_5us(); if(SDA==1) //如果為1,則非應答 { SCL=0; //拉低SCL線,使SDA線可以發送停止信號 _nop_(); I2C_Stop(); //發送停止信號 return (0); //非應答 } else { SCL=0; //拉低SCL線 _nop_(); return (1); //應答 } } 應答程序部分就是這樣寫的,隨便發個設備地址(A0A1A2三個引腳都接地了的),發現SDA都會被拉低。 |
|
當你序讀取每一位的時候,總會認定的一個值,非0即1! 只不過讀到的0/1是不是“目標設備”發出來的,就不好說了。 |
| 看看你程序里應答部分是怎么寫的 |