Problems with TWI peripheral
Discussion in "8051 Discussion Forum" started by Nals99 Jul 3, 2015.
Fri Jul 03 2015, 02:22 pm
Hi guys...
I'm having some problems to transmit data to a eeprom with TWi peripherical with AT89C51IC2.
I can read from the EEprom, but I can't write.
Here is my code:
The propose of this code is to use it in a IO expander, but for test only I'm doing this in a EEprom, so i can really check if it Reading/witting correctely or not...
Can anyone help me with last 'switch' in the code?
Thanks in advance.
Regards
Nals
I'm having some problems to transmit data to a eeprom with TWi peripherical with AT89C51IC2.
I can read from the EEprom, but I can't write.
Here is my code:
#define N 128 unsigned char code addrRead[] = { 0xA0, 0x00, 0xA1}; unsigned char code addrWrite[] = { 0xA1, 0x00, 'T', 'e', 's', 't', 'e', ' ', 'n', 'r', '1', '!'}; unsigned char xdata rBuffer[N], wBuffer[N]; unsigned char bufferIndex, addrIndex; volatile bit completed, RW; union int_char{ int i; char ch[2]; }; void TWI_Master_Read() { RW = 0; bufferIndex = 0; addrIndex = 0; SSCON |= 0xC1; /* habilitar TWI; bit freq: 100kHz; enable TWI */ IEN1 |= 0x02; /* habilitar interrupt TWI */ SSCON |= 0x20; } void TWI_Master_Write() { RW = 1; bufferIndex = 0; addrIndex = 0; SSCON |= 0xC1; /* habilitar TWI; bit freq: 100kHz; enable TWI */ IEN1 |= 0x02; /* habilitar interrupt TWI */ SSCON |= 0x20; } void printMessage() { unsigned char i; com_initialize(); // CONFIGURO PORTA SERIE BAUDRATE: 9600bps EA = 1; /* habilitar interrupçoes */ TWI_Master_Write(); while (!completed); TWI_Master_Read(); while (!completed); printf ("Message: "); delay_ms(100); putchar('\n'); putchar('\r'); for(i=0; i<N; i++){ putchar(rBuffer[i]); } putchar('\n'); putchar('\r'); } void main() { printMessage(); printf ("Message successfull read!!!"); putchar('\n'); putchar('\r'); while (1); } static void twi_isr() interrupt 8 { ////////////////////////////////////////////////////////////////////////////////////// // // // READ // // // ////////////////////////////////////////////////////////////////////////////////////// if (RW==0){ switch (SSCS) { case (0x08): SSCON &= ~0x20; // desabilitar flag start SSDAT = addrRead[addrIndex++]; break; case (0x18): SSDAT = addrRead[addrIndex++]; break; case (0x28): SSCON |= 0x20; // habilitar flag start break; // para assim enviar repeated start case (0x10): SSCON &= ~0x20; // desabilito flag start SSDAT = addrRead[addrIndex++]; break; case (0x38): addrIndex=0; break; case (0x40): SSCON |= 0x04; // activar acknowledge break; case (0x48): addrIndex=0; break; case (0x50): rBuffer[bufferIndex++] = SSDAT; if (bufferIndex < N - 1) SSCON |= 0x04; //enquanto nao leu tudo, continuo a retornar ack else SSCON &= ~0x04; completed = 1; break; case (0x58): rBuffer[bufferIndex] = SSDAT; completed = 1; SSCON |= 0x10; break; } SSCON &= ~0x08; /* clear interrupt flag */ } ////////////////////////////////////////////////////////////////////////////////////// // // // WRITE // // // ////////////////////////////////////////////////////////////////////////////////////// else{ switch (SSCS){ case (0x08): SSCON &= ~0x20; // clear flag start SSDAT = addrWrite[addrIndex++]; break; case (0x10): SSCON &= ~0x20; // clear flag start addrIndex=0; SSDAT = addrWrite[addrIndex++]; break; case (0x18): SSDAT = addrWrite[addrIndex++]; break; case (0x20): SSCON |= 0x20; break; case (0x28): SSDAT = addrWrite[bufferIndex++]; if ((bufferIndex < N - 1) && (addrWrite[bufferIndex] != NULL)) ; else SSCON |= 0x10; delay_ms(5); break; case (0x30): break; case (0x38): break; } SSCON &= ~0x08; /* clear interrupt flag */ } }
The propose of this code is to use it in a IO expander, but for test only I'm doing this in a EEprom, so i can really check if it Reading/witting correctely or not...
Can anyone help me with last 'switch' in the code?
Thanks in advance.
Regards
Nals
Mon Jul 13 2015, 04:08 pm
Your switch case statement looks ok for write, but I don't see "completed" flag getting set anywhere when RW = 1. You need to understand that when writing into EEPROM, you cannot write more than a single page at a time. Also you need to give delay so that after your write cycle finishes, EEPROM starts an internal write operation which takes almost 5ms or more.
I think problem is in the write address your passing:
Read more about i2c/twi in tutorial section http://www.8051projects.net/wiki/
I think problem is in the write address your passing:
unsigned char code addrWrite[] = { 0xA1, 0x00, 'T', 'e', 's', 't', 'e', ' ', 'n', 'r', '1', '!'}; // Address should be 0xA0 for write and 0xA1 for read. the LSB is for RW, RW = 0 for write and RW = 1 for read
Read more about i2c/twi in tutorial section http://www.8051projects.net/wiki/
Nals99 like this.
Powered by e107 Forum System