Skriva/läsa I2C eeprom med MSSP

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
MH100
Inlägg: 81
Blev medlem: 10 juni 2005, 23:54:53

Skriva/läsa I2C eeprom med MSSP

Inlägg av MH100 »

Hej! Nu har jag en ny fråga :D

Försöker läsa/skriva till ett I2C eeprom (Mircochip 24LC16B/P) med MSSP-enheten på en PIC18F458. Har kopplat in den och försökt få till en kod enligt Microchips appnotes.
http://ww1.microchip.com/downloads/en/A ... 00991A.pdf


Jag får det dock inte att funka. Om jag provar att skriva nåt och sedan läsa det så får jag alltid '255' tillbaka.
Allt är kopplat som på bilden på sida 1 i appnoten oven.
Jag gör en liten delay på 10ms innan jag läsar så att eepromet skall hinna skriva klart.
Det lär ju vara någon här på forumet som hållt på med I2C eeprom som har skrivit kod för detta. Skulle nån vilja slänga ett öga på koden å se om jag gjort nåt fel!
Tack!
Kör PIC:en på 4MHz


Kod: Markera allt

void i2c_put_eeprom(char page , char addr, char data)   
// skriva en byte till EEPROM
{
    //sätter control_byten som är första byta att skickas
    //bit 1 till 3 är vilken PAGE
    char control_byte;
    control_byte = 0b1010.000.0;
    control_byte.3 = page.2;
    control_byte.2 = page.1;
    control_byte.1 = page.0;
    
    //initierar I2C, master.
    SSPSTAT = 0x80;
    SSPADD = 0x09;            // Fosc = 4 Mhz
    SSPCON1 = 0x28;
    SSPCON2 = 0x00;
    TRISC.3 = 1;
    TRISC.4 = 1;
    SSPIF = 0;
    
    SEN = 1;                       // START.
    while(!SSPIF);               // Vänta tills SSPIF är SET, dvs. klart.
    SSPIF = 0;                    // nollställ SSPIF.
    SSPBUF = control_byte;  // sänd controlbyten.
    while(!SSPIF);               // -"-,
    SSPIF = 0;          
    SSPBUF = addr;            // sänd adressbyten.
    while(!SSPIF);
    SSPIF = 0;
    SSPBUF = data;            // sänd databyten.
    while(!SSPIF);
    SSPIF = 0;
    PEN = 1;                      // STOP
    while(!SSPIF);
    SSPIF = 0;
}


char i2c_get_eeprom(char page , char addr)
// läsa en byte från eeprom
{
    char control_byte, data;

    //sätter control_byten som är första byta att skickas
    //bit 1 till 3 är vilken PAGE, bit 0 är R/!W 
    control_byte = 0b1010.000.0;
    control_byte .3 = page.2;
    control_byte .2 = page.1;
    control_byte .1 = page.0;

    //initierar I2C, master.
    SSPSTAT = 0x80;
    SSPADD = 0x09;             // Fosc = 4 Mhz
    SSPCON1 = 0x28;
    SSPCON2 = 0x00;
    TRISC.3 = 1;
    TRISC.4 = 1;
    SSPIF = 0;

    SEN = 1;                        // START
    while(!SSPIF);                // Vänta tills SSPIF är SET, dvs. klart.
    SSPIF = 0;                     // nollställ SSPIF.
    SSPBUF = control_byte;   //sänd controlbyte
    while(!SSPIF);                // -"-
    SSPIF = 0;  
    SSPBUF = addr;             // sänd adressbyte;
    while(!SSPIF);
    SSPIF = 0;
    
    control_byte.0 = 1;        //ändra controlbyten till READ.
    RSEN = 1;                     // RESTART
    SSPBUF = control_byte;  //sänd controlbyte
    while(!SSPIF);
    SSPIF = 0;
    ACKDT = 1;                   // not acknowledge
    RCEN = 1;                     // recive enabled
    while(!SSPIF);
    SSPIF = 0;
    data = SSPBUF;              //hämta data
    ACKEN = 1;                    // acknowlede enabled
    PEN = 1;                        // STOP
    while(!SSPIF);
    SSPIF = 0;
    return data;             
}
Senast redigerad av MH100 27 juni 2005, 18:55:18, redigerad totalt 2 gånger.
MH100
Inlägg: 81
Blev medlem: 10 juni 2005, 23:54:53

Inlägg av MH100 »

Snääälla finns det inte som kan hjälpa mig... :cry:
Måste ju finnas nån som användt I2C eeprom här!
TAck!
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

Med din beskrivning av problemet så är det väll inte så konstigt att det inte har blivit några svar... :-)

Du kan börja med att komplettera med vilken utvecklingsmiljö du kör, samt vad som händer. Eller med andra ord, hur *vet* du att det inte funkar ?

Och när du säger "Microchips datablad & appnotes", så ange också VILKA.
D.v.s nummer på dokumentet, sida, bildnummer o.s.v. Exakt angivet så att den som är intresserad kan hitta samma schema och instruktioner utan att behöva gissa. Eller lägg med länkar.

Och att posta okommenterad källkod, tja...
Som man frågar får man svar. :-)
MH100
Inlägg: 81
Blev medlem: 10 juni 2005, 23:54:53

Inlägg av MH100 »

Oook .. håller väl med om att frågan inte var så bra ställd.
Jag har redigerat inlägget lite nu.

Skulle vara väldigt tacksam om någon kunde kolla lite på koden å se vad som kan vara fel... Eller om någon har lite kod som jag kan få kika på.
Tyvärr så kan jag inte ge en bättre felbeskrivning. Jag har inte riktigt kunskaperna för att analysera felet.

Vore fint om nån kunde hjälpa.. börjar bli kris nämligen.
Användarvisningsbild
PaNiC
Inlägg: 2610
Blev medlem: 15 augusti 2003, 22:16:15
Ort: Skånelandet

Inlägg av PaNiC »

Jag har använt 24C16 men förstår inte koden. Det är något av ett dilemma.
MH100
Inlägg: 81
Blev medlem: 10 juni 2005, 23:54:53

Inlägg av MH100 »

ok...haha.. låter ju bra för min del 8)

du har inte lite kod man kan få kika på?
Användarvisningsbild
PaNiC
Inlägg: 2610
Blev medlem: 15 augusti 2003, 22:16:15
Ort: Skånelandet

Inlägg av PaNiC »

Jodå, det kan vi ordna.

Delvis min, delvis lånad kod.

Kod: Markera allt

;----------------------------------------------------------------- 
; 
; ReadMem 
; 
; Reads external memory at X, and increments X 
; Byte is returned in register 

ReadMem: 
   rcall   I2CStart 
   
   ldi   rPARAM1,(ADDR24LC16|I2CWRITE) 
   oraddr ;macro för att ora rparam1 med adressen skiftad ett steg vänster


   rcall   I2CSendAddress 
   brne   ReadMemError   ; No ack! 
    
    
   mov   rPARAM1,XL 
   rcall   I2CSendByte 

   rcall   I2CStop 

   I2CDelay 

   rcall   I2CStart 
    
   ldi   rPARAM1,(ADDR24LC16|I2CREAD) 
   oraddr
   rcall   I2CSendAddress 
   brne   ReadMemError   ; No ack! 
    
   ldi   rPARAM1,1   ; Don't send ack 
   rcall   I2CReadByte 
    
   rcall   I2CStop 
    
   incx
   ret

ReadMemError: 
   rcall   I2CStop 
   ;rcall lcd_clear
   ;ldi temp, 'd' 
   ;rcall lcd_sendchar 
   ;ldi temp2, 100
   ;rcall bigdelay
   clr   rLOOPI 
ReadMemErrorDelay: 
   dec   rLOOPI 
   brne   ReadMemErrorDelay 
    
   rjmp   ReadMem   ; and try again 

;----------------------------------------------------------------- 
; 
; Writeloop 
; 
; Writes number of bytes as stored in temp2 to EEPROM from SRAM 
; and writes ascii code 32 to last address and stores number after 
; last in EEPROM addresses 0x00 (low byte) and 0x01 (high byte) 
; Assumes beginning address is stored in X and for SRAM in Z 

Writeloop: 
	ld rparam1, z+
	rcall writemem
	;rcall usart_sendxl
	;rcall usart_sendxh
	dec temp2
	brne writeloop
	rcall ee_writeaddr
	ret 

ee_writeaddr:
	sbic eecr, eewe
	rjmp ee_writeaddr
	push temp
	ldi temp, 0x05
	out eearl, temp
	out eedr, XL
	sbi eecr, eemwe
	sbi eecr, eewe
	nop
	nop
	nop
	nop
ee_writeaddragain:
	sbic eecr, eewe
	rjmp ee_writeaddragain
	ldi temp, 0x06
	out eearl, temp
	out EEDR, XH
	sbi eecr, eemwe
	sbi eecr, eewe
	nop
	nop
	nop
	nop
	pop temp
	ret


;----------------------------------------------------------------- 
; 
; WriteMem 
; 
; Writes rPARAM1 to external memory at X, and increments X 

WriteMem: 
   mov   rPARAM2,rPARAM1   ; save value 

   rcall   I2CStart 
    
   ldi   rPARAM1,(ADDR24LC128|I2CWRITE) 
   oraddr

   rcall   I2CSendAddress 
   ;brne   WriteMemError   ; No ack! 
    
    
   mov   rPARAM1,XL 
   rcall   I2CSendByte 

   mov   rPARAM1,rPARAM2 
	out udr, rparam1

   rcall   I2CSendByte 

   rcall   I2CStop 
	
   incx
   ret

   ; Increment X by 1    


WriteMemError: 
   rcall   I2CStop 
	;rcall lcd_clear
	;ldi temp, 'e'
	;rcall lcd_sendchar
	;ldi temp2, 100
	;rcall bigdelay
   clr   rLOOPJ 
WriteMemErrorDelay: 
   dec   rLOOPJ 
   brne   WriteMemErrorDelay 
    
   mov   rPARAM1,rPARAM2 ; restore data value 
   rjmp   WriteMem   ; and try again 



;----------------------------------------------------------------- 
; 
; I2C Routines 
; 
;----------------------------------------------------------------- 

;----------------------------------------------------------------- 
; 
; I2CInit 
; Initialize I2C interface, ports, etc. 

I2CInit: 
   cbi   PORTd,bSDA   ; Data line always drives low if driven 
   cbi   DDRd,bSDA   ; SDA as input to start with - floats high 

   cbi   PORTd,bSCL   ; Set SCL low to try and avoid... 
   sbi   DDRd,bSCL   ; ...false start transitions 

   I2CDelay 
    
   rjmp   I2CStop      ; Stop any erroneous transfer 

;----------------------------------------------------------------- 
; 
; I2CStart 
; Send I2C start condition 
; Assumes SCL and SDA are high to start with. 
; Leaves SCL and SDA low 

I2CStart: 
   I2CDelay    

   sbi   DDRd,bSDA   ; Drive data line low (start bit) 
    
   I2CDelay 

   cbi   PORTd,bSCL   ; Clock line low (ready to start) 
   ret 
    
;----------------------------------------------------------------- 
; 
; I2CStop 
; Send I2C stop condition 
; Assumes SCL is low to start with, SDA may be in either state 
; Leaves SCL and SDA high 

I2CStop: 
   sbi   DDRd,bSDA   ; SDA driven low 

   I2CDelay    

   sbi   PORTd,bSCL   ; Clock line high (ready to stop) 
    
   I2CDelay    

   cbi   DDRd,bSDA   ; Data line floats high (stop bit) 
    
   I2CDelay 

   ret 
    
;----------------------------------------------------------------- 
; 
; I2CSendByte 
; Sends 8 bits of data from rPARAM1 and listens for an ACK at the 
; end. Returns Z if ack received, else NZ. 
; Assumes a start condition has already been sent, and SDA and SCL 
; are low 
; Leaves SCL low, SDA not driven. 
; Uses rLOOPJ and rPARAM1. 

I2CSendAddress: 
I2CSendByte: 
   ldi   rLOOPJ,8 
I2CSendBits: 
   add   rPARAM1,rPARAM1 
   brcc   I2CSendBits0 
    
   cbi   DDRd,bSDA   ; send 1 (floats high) 
   rjmp   I2CSendBits1 

I2CSendBits0: 
   sbi   DDRd,bSDA   ; send 0 (drives low) 

I2CSendBits1:    
   I2CDelay 
   sbi   PORTd,bSCL   ; clock high 
   I2CDelay 
   cbi   PORTd,bSCL   ; clock low 
    
   dec   rLOOPJ 
   brne   I2CSendBits 
    
   cbi   DDRd,bSDA   ; stop driving data bus 
   I2CDelay 

   sbi   PORTd,bSCL   ; clock high 
   I2CDelay 
   in   rPARAM1,PINd   ; sample data bus 

   cbi   PORTd,bSCL   ; clock low 
   I2CDelay 
    
   andi   rPARAM1,mSDA   ; check ack bit (z set if OK) 
   ret 

;----------------------------------------------------------------- 
; 
; I2CReadByte 
; Read a byte from the I2C bus and acknowledge 
; If rPARAM1 is zero, acknowledge is sent, otherwise not. 
; Byte is returned in rRETURN 
; Leaves SCL low, I2C bus not driven. 

I2CReadByte: 
   ldi   rLOOPJ,8 
   clr   rRETURN 

   cbi   DDRd,bSDA   ; release bus (floats high) 
    
I2CReadBits: 
   sbi   PORTd,bSCL   ; clock high 
   I2CDelay 
    
   add   rRETURN,rRETURN 
    
   sbic   PINd,bSDA   ; if SDA clear, skip increment 
   inc   rRETURN 
    
   cbi   PORTd,bSCL   ; clock low 
   I2CDelay 

   dec   rLOOPJ 
   brne   I2CReadBits 
    
   tst   rPARAM1      ; Send an ACK...? 
   brne   I2CReadBitsNack    
    
   sbi   DDRd,bSDA   ; yes... drive data bus low 

I2CReadBitsNack: 
   sbi   PORTd,bSCL   ; clock high 
   I2CDelay 
   cbi   PORTd,bSCL   ; clock low 
   I2CDelay 
   cbi   DDRd,bSDA   ; release bus (floats high) 
   ret 


MH100
Inlägg: 81
Blev medlem: 10 juni 2005, 23:54:53

Inlägg av MH100 »

Tack!

ook...

Kanske ska förtydliga att jag försöker använda MSSP enheten i PIC:en för att kommunicera med eeprom:et.
http://ww1.microchip.com/downloads/en/D ... 41159d.pdf Sida 145.
Kanske därför min kod inte känndes bekant.
MH100
Inlägg: 81
Blev medlem: 10 juni 2005, 23:54:53

Inlägg av MH100 »

Snääääälla!! :roll: Ingen som kan hjäpla mig lite på traven?... jag kommer ingen vart å det börjar bli kris.. måste få detta att funka!
Användarvisningsbild
strombom
Inlägg: 3305
Blev medlem: 27 maj 2003, 10:50:20
Ort: Västra Götaland
Kontakt:

Inlägg av strombom »

Bygg ihop en JDM-programmerare eller liknande och programmera eepromet med. Sedan kan du testa dina läs- och skrivrutiner separat. Kolla att alla elektriska kopplingar är rätt också...

/Johan
MH100
Inlägg: 81
Blev medlem: 10 juni 2005, 23:54:53

Inlägg av MH100 »

Har skrivit om koden från början igen... denna gång har jag översatt direkt från koden i Microchips AppNote989 till 'C'.

Kod från AppNotehttp://www.isk.kth.se/~mhenriks/Bilder/AN989.asm

I 'C' http://www.isk.kth.se/~mhenriks/Bilder/i2c_ee.c

Det funkar fortrfarande inte. Lär ju inte vara fel på AppNoten eller?
Finns det några kopplingmässiga fällor att gå i vad det gäller I2C.
Har kopplat precis som i AppNoten.
Börjar tro att mina 24LC16b är trasiga!
Skriv svar