i2c problem with EEPROM 24AA128

Discussion in 'Embedded Systems and Microcontrollers' started by ArakelTheDragon, Apr 10, 2017.

  1. ArakelTheDragon

    Thread Starter Active Member

    Nov 18, 2016
    737
    38
    Good day! I am trying to make an "i2c" interface, but I cant seem to get it to work. I read the datasheet, but Its not working.

    Compiler: CCS PIC C v5.061
    Simulator: Proteus 8.5

    Source code
    Code (C):
    1.  
    2. /*
    3. Description:
    4. Second attempt to make an i2c program, examples and others are taken from the CCS forums, file for reference:
    5.  
    6. i2c-PCM-programmer-examples-CCS __ View topic - sensor networks.pdf
    7.  
    8. Original version from PCM programmer, the rest are modified versions
    9. */
    10.  
    11. /*
    12. Description:
    13. Second attempt to make an i2c program, examples and others are taken from the CCS forums, file for reference:
    14.  
    15. i2c-PCM-programmer-examples-CCS __ View topic - sensor networks.pdf
    16. */
    17.  
    18. #include <16F690.h>
    19.  
    20. #define GP0 PIN_C0
    21. #define GP1 PIN_C1
    22. #define GP2 PIN_C2
    23. #define GP3 PIN_C3
    24. #define GP4 PIN_C4
    25. #define GP5 PIN_C5
    26. #define GP6 PIN_C6
    27. #define GP7 PIN_C7
    28.  
    29. #fuses INTRC_IO, NOWDT, NOPROTECT, BROWNOUT /* Ext. oscilator, no watchdog, no code protect, no brownout (until voltage
    30. rises on power up the PIC is held in reset = inactive) reset */
    31.  
    32. #use delay(clock=4M) /* Specify clock frequency, to use "delay_()" function */
    33. #use rs232 (baud=9600, xmit=PIN_B5, rcv=PIN_B7, parity=N, bits=8, errors)
    34. #use i2c (master, sda=PIN_C5, scl=PIN_C4) /* Master mode, SDA pin = RB4, SCL pin = RB6, force hardware i2c functions */
    35.  
    36. #define SLAVE1_WRT_CON_BYTE 0b10100000 /* This byte should contain the control byte from the
    37. datasheet with control code, AN0, AN1, AN2 pins, READ or WRITE bit */
    38. /* bit<0> = 0 for write and 1 for read
    39. bits<1:3> = the values of the AN0:2 pins
    40. bits<4:7> = control code of "1010" for EEPROM24AA128 */
    41. /* !!! Dont forget that these must be put as the most significant bits first,
    42. A0, A1, A2 become A2, A1, A0, making:
    43. 10100000 = control 4 bits/A2, A1, A0,/Read or write */
    44. /* HEX = 0xA0 */
    45.  
    46. #define SLAVE1_READ_CON_BYTE 0b10100001 /* This byte should contain the control byte from the
    47. datasheet with control code, AN0, AN1, AN2 pins, READ or WRITE bit */
    48. /* bit<0> = 0 for write and 1 for read
    49. bits<1:3> = the values of the AN0:2 pins
    50. bits<4:7> = control code of "1010" for EEPROM24AA128 */
    51. /* !!! Dont forget that these must be put as the most significant bits first,
    52. A0, A1, A2 become A2, A1, A0, making:
    53. 10100001 = control 4 bits/A2, A1, A0,/Read or write */
    54. /* HEX = A1 */
    55.  
    56. #define SLAVE1_WRITE_ADDRESS_2_BYTES 0x00A2
    57. #define SLAVE1_READ_ADDRESS_2_BYTES 0x00A3
    58. //====================================
    59.  
    60. void main()
    61. {
    62. int8 data;
    63.  
    64. while(1)
    65. {
    66. printf ("Startin i2c module");
    67. /* to write data */
    68. i2c_start();
    69. i2c_write(SLAVE1_WRT_CON_BYTE); /* 1. Following the start condition, the next byte is control code (1010)\chip select (A2, A1, A0), R/W bit (logic low). This indicates to the addressed slave that the address high byte will follow after it has generated an Acknowledge bit */
    70. delay_ms (10); /* delay 10ms for the acknowledge bit to be sent, because we dont record it with the microcontroller */
    71.  
    72. i2c_write (0x80); /* 2. The next byte is the high order byte of the word address and will be written into the Address Pointer of 24AA128 */
    73.  
    74. i2c_write (0x00); /* 3. The next byte is the least significant address byte */
    75.  
    76. i2c_write (0x01); /* 4. After receiving another acknowledge signal from the 24AA128, the master will transmit tha data word to be written into the addressed memory location */
    77. /* After a byte write command, the internal address counter will point
    78. /* to the address location following the one that was just written */
    79. i2c_write (0x02);
    80. delay_ms (10);
    81. i2c_stop (); /* 5. After another acknowledge bit, the master sends the stop condition */
    82. delay_ms (10);
    83.  
    84. /* to read data subsequently */
    85. i2c_start();
    86. i2c_write(SLAVE1_WRT_CON_BYTE); /* 1. Following the start condition, the next byte is control code (1010)\chip select (A2, A1, A0), R/W bit (logic low). This indicates to the addressed slave that the address high byte will follow after it has generated an Acknowledge bit */
    87. delay_ms (10); /* delay 10ms for the acknowledge bit to be sent, because we dont record it with the microcontroller */
    88.  
    89. i2c_write (0x80); /* 2. The next byte is the high order byte of the word address and will be written into the Address Pointer of 24AA128 */
    90.  
    91. i2c_write (0x00); /* 3. The next byte is the least significant address byte */
    92.  
    93. i2c_write (SLAVE1_READ_CON_BYTE);
    94. delay_ms (10);
    95.  
    96. data = i2c_read(0);
    97. delay_ms (10);
    98.  
    99. data = i2c_read (0);
    100.  
    101. //i2c_stop (); /* 5. After another acknowledge bit, the master sends the stop condition */
    102. //delay_ms (10);
    103.  
    104. printf("read %X \n\r", data);
    105. delay_ms(1000);
    106. }
    107. }

    Schematic

    Arakal_I2C.jpg

    Moderators note : made code and schematic directly viewable
     
    Last edited by a moderator: Apr 10, 2017
  2. JohnInTX

    Moderator

    Jun 26, 2012
    3,322
    1,663
    The wiring on RB4-RB7 is incorrect. SDA and SCL go to the EEPROM, TX,RX to to the terminals. I didn't look further.

    Good luck.
     
    ErnieM likes this.
  3. ArakelTheDragon

    Thread Starter Active Member

    Nov 18, 2016
    737
    38
    Thats only if I use the hardware built-in option. Otherwise I can specify, whichever pin I want. The RS232 is already tested and working, I just dont know if there is anything wrong with the sequence with which I write and read to EEPROM.
     
  4. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,943
    1,816
    It's hard to track down all your errors without knowing what your library code is doing for you. These routines need to be "bit banging" ones where they wiggle the I/O pins directly, and since I2C needs open collector drives they should be hitting the TRIS registers too. Do check that.

    The write sequence you have seems OK, though the only delay you need is after then bytes are sent. Don't delay within the write cycles.

    The read has one obvious problem. Line 92 should be either a RESTART command or a STOP and START sequence. This is not obvious, but you write the address, then read the data there. No delay is needed for reads.

    Do be careful with the START and STOP commands.

    Also check what your library does with the ACK signal. After the master reads a byte it needs to ACK this to advance the memory pointer. No ACK, the slave thinks the transaction is complete.
     
  5. JohnInTX

    Moderator

    Jun 26, 2012
    3,322
    1,663
    If that is the case then what are these two lines doing? To me, it seems that it is using the hardware pins.
    Code (C):
    1. #use rs232 (baud=9600, xmit=PIN_B5, rcv=PIN_B7, parity=N, bits=8, errors)
    2. #use i2c (master, sda=PIN_C5, scl=PIN_C4) /* Master mode, SDA pin = RB4, SCL pin = RB6, force hardware i2c functions */
    Also, RS232 connections usually have PIC TX -> Terminal RX and PIC RX->Terminal TX.

    As @ErnieM says, what it does with ACK is important. I don't understand using a delay() to wait for ACK. The PIC is the master here so it has to generate the I2C clock, something it can't do when using a delay() and bit-banging I2C. If you are able to relocate the I2C pins with the library, you are indeed bit-banging since the 16F690 can't relocate the hardware MSSP pins. In any I2C, you have to pay attention to ACK/NAK, if for no other reason but to see if you actually have addressed the slave EEPROM.

    If it were me, I would wire it up in a more normal manner first i.e.
    SDA/SCL on the specified pins
    TX->RX
    RX<-TX

    If you insist on pioneering with your pinout, I'd at least look at the assembler output of the compiler to see if indeed it is relocating pins or if it's using the MSSP.
    Just thinking out loud..
     
  6. ArakelTheDragon

    Thread Starter Active Member

    Nov 18, 2016
    737
    38
    I need to know if the bytes sent are according to the procedure for the I2C standard, according to the datasheet of EEPROM 24AA128, because despite reading the datasheet, the program does not work.

    The functions do this:

    1. i2c_start(); /* the start condition according to the datasheet of EEPROM 24AA128 is sent to the EEPROM */
    2. i2c_write(SLAVE1_WRT_CON_BYTE); /* just sends a byte on the bus with the value in the brackets */

    3. i2c_write (0x80); /* sends a byte on the bus with the value in the brackets */

    4. i2c_write (0x00); /* sends a byte on the bus with the value in the brackets */

    5. i2c_write (0x01); /* sends a byte on the bus with the value in the brackets */

    6. i2c_write (0x02); /* sends a byte on the bus with the value in the brackets */
    7. delay_ms (10);
    8. i2c_stop (); /* stop condition according to the datasheet of EEPROM 24AA128 */
     
  7. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,943
    1,816
    Put that delay AFTER the stop command.

    Up until the stop is issued the EEPROM Keeps the data in a buffer. It only gets written after the stop.

    Writing takes time, and other commands are basically ignored till it is complete.

    Next, do tell how and what your library does with ACK.

    (Edit to remove horrible auto-correct)
     
    Last edited: Apr 18, 2017
  8. ArakelTheDragon

    Thread Starter Active Member

    Nov 18, 2016
    737
    38
    That will be difficult, since I myslef dont know, but I might be able to find it in the header files.
     
  9. ArakelTheDragon

    Thread Starter Active Member

    Nov 18, 2016
    737
    38
    For theese 2 lines:.
    #use rs232 (baud=9600, xmit=PIN_B5, rcv=PIN_B7, parity=N, bits=8, errors)
    #use i2c (master, sda=PIN_C5, scl=PIN_C4)

    As far as I understand, I can use hardware "i2c" or software "i2c", so if I use the software version, I can pick whichever pins I want. I will try with different pins though.
     
Loading...