Advertisement
Guest User

AT24C04-I2C PROJECT

a guest
Nov 29th, 2011
571
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 16.29 KB | None | 0 0
  1. Hello there I have almost completed coding interfacing with EEPROM - AT24C04 using I2C protocol,But using this I am able to perform a "READ" operation but not a WRITE.
  2.  
  3. I have checked for the WP(write protect pin) and its alright - connected to ground.  
  4.  
  5. I am using a similar kind of program( found on this forum ) for interfacing the EEPROM using I2C and this program works!!.
  6.  
  7. This program that I found can do both READ/WRITE....
  8.  
  9. But when I burn my program on the MC ..it cannot write but it can read the values stored at addresses 0x000,0x001,0x002 using the program found on this forum.
  10.  
  11. <pre>
  12. /*
  13.   AT24C04 EERPOM HEADER FILE
  14.  
  15. */
  16. #include <reg51.h>
  17. #include <intrins.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include "AT24C04-EEPROM.h"
  21. #include "AT24C04-LCD.h"
  22. #include "AT24C04-I2C.h"
  23.  
  24. /*********************************************************************************
  25. AT24C04 - C FILE MAIN FUNCTION
  26. *********************************************************************************/
  27. void main()
  28. {
  29.     unsigned char value2;
  30.     lcdinitialize();
  31.     EEPROMwrite( 0x000,'Z' );
  32.     lcddata('M');  
  33.     value2 = EEPROMread( 0x000 );
  34.     Delay(150);
  35.     lcddata(value2);
  36. }
  37.  
  38. </pre>
  39.  
  40. <pre>
  41. /*********************************************************************************
  42.   AT24C04 I2C BUS HEADER FILE - ROUTINE/FUNCTION DECLARATIONS
  43. *********************************************************************************/
  44.  
  45. #ifndef __I2C_H
  46. #define __I2C_H
  47.  
  48. void I2C_delay(void);           //Delay needed while doing I2C related coding
  49.  
  50. void I2C_clock(void);
  51.                        
  52. void I2C_start(void);
  53.  
  54. void I2C_stop(void);
  55.  
  56. void I2C_write( unsigned char );
  57.  
  58. unsigned char I2C_read( void );
  59.  
  60. void I2C_ackpolling(void);
  61.  
  62. void I2C_check_NACK(void);
  63.  
  64. void I2C_ack(void);                   //master sending the acknowlege to slave
  65.  
  66. void I2C_nack(void);
  67.  
  68. #endif
  69. </pre>
  70.  
  71.  
  72. <pre>
  73.  
  74. /*********************************************************************************
  75.  
  76. AT24C04 - I2C  C FILE - FUNCTIONS/ROUTINES
  77. *********************************************************************************/
  78. #include <reg51.h>
  79. #include <intrins.h>
  80. #include "AT24C04-LCD.h"
  81. #include "AT24C04-I2C.h"
  82.  
  83. sbit SDA = P3^6;                //refer circuit board schematics for the assignment of SDA & SCL
  84. sbit SCL = P3^7;
  85.  
  86. bit NACK;                       //bit FLAG to set status of NACK
  87.  
  88. void I2C_delay(void)            //Delay needed while doing I2C related coding
  89. {
  90.     _nop_();
  91. }
  92.  
  93. void I2C_clock(void)
  94. {
  95.     //I2C_delay();
  96.     SCL = 1;
  97.     I2C_delay();
  98.     SCL = 0;
  99. }          
  100.            
  101. void I2C_start(void)
  102. {
  103.     SDA = 1;
  104.     I2C_delay();
  105.     SCL = 1;
  106.     I2C_delay();
  107.     SDA = 0;
  108.     I2C_delay();
  109.     SCL = 0;
  110.     I2C_delay();
  111. }
  112.  
  113. void I2C_stop(void)
  114. {
  115.     SCL = 1;
  116.     I2C_delay();
  117.     SDA = 0;
  118.     I2C_delay();
  119.     SDA = 1;
  120.     I2C_delay();
  121.     SCL = 0;
  122. }
  123.  
  124. /*void I2C_ackpolling(void)
  125. {
  126.     SDA = 1;                        //release SDA high
  127.     I2C_delay();
  128.     SCL = 1;                        //release SCL high for acknowledge,start clock
  129.     I2C_delay();
  130.     while( SDA );                   //wait,loop while SDA = 1( HIGH ),if HIGH this means EEPROM is busy,will wait till it pulls SDA low
  131.     SCL = 0;
  132. } */
  133.  
  134. void I2C_check_NACK()
  135. {
  136.     SDA = 1;                             //release SDA high
  137.     I2C_delay();
  138.  
  139.     SCL = 1;                             //release SCL high for acknowledge,start clock
  140.     I2C_delay();
  141.  
  142.     if( !SDA )                           //Check for acknowledge status from slave if SDA == 0,then ACK is 0 & OK from slave
  143.     {  
  144.         SCL = 0;                         // pull down SCL,end the clock for acknowledge
  145.         I2C_delay();
  146.         NACK = 0;
  147.         //lcddata('R');
  148.     }
  149.     else                            // SDA status is still HIGH so NACK ,i.e NACK is 1
  150.     {
  151.         SCL = 0;
  152.         NACK = 1;                   //ACK -acknowledge bit not received from EEPROM(receiver),EEPROM has pulled SDA high
  153.         lcddata('W');               //to indicate on LCD of a possible ACK failure
  154.     }
  155. }
  156.  
  157. void I2C_write( unsigned char userdata )
  158. {
  159.     bit databit;                //bit variable for determining whether bit is 1 or 0
  160.     unsigned char i;            //loop counter variable for a byte received
  161.     unsigned char temp;
  162.     //lcddata( userdata );
  163.    
  164.     SCL = 0;
  165.     for( i = 0; i<8 ;i++)
  166.     {
  167.         databit = SDA = userdata & 0x80;         //store MSB in databit
  168.         temp = (unsigned char )databit + 0x30;                           //assign it to the SDA
  169.         lcddata(temp);
  170.         I2C_delay();                     //clock out the bit,do this for a byte
  171.         I2C_clock();
  172.  
  173.         userdata = userdata << 1;        // left shift to determine next MSB
  174.     }
  175.    
  176. }
  177.  
  178. unsigned char I2C_read( void )
  179. {
  180.     bit read_bit;
  181.  
  182.     unsigned char received_data = 0x00,i;
  183.     SDA = 1;
  184.     SCL = 0;
  185.  
  186.     for( i = 0; i< 8 ;i++)
  187.     {  
  188.        
  189.         SCL = 1;                //set SCL high,start of Clock,SCL = high here since before making it low the ACK is read in
  190.         I2C_delay();
  191.         received_data = received_data << 1;   //left shit,MSB goes in first
  192.         received_data = received_data | (unsigned char )SDA;
  193.  
  194.         SCL = 0;                        //set SCL low,end the clock
  195.         //received_data = received_data | read_bit;    
  196.     }
  197.  
  198.  
  199.     SDA = 0;     
  200. //  received_data = received_data | read_bit;
  201.     lcddata( received_data );
  202.  
  203.  
  204.     //lcddata( received_data );
  205.     return received_data;      
  206. }
  207.  
  208.  
  209. void I2C_ack(void)                    //master sending the acknowlege to slave
  210. {
  211.     SDA = 0;                         //clear SDA
  212.     I2C_delay();
  213.                                      //clock out
  214.     I2C_clock();
  215.     SDA = 1;
  216. }
  217.  
  218.  
  219. void I2C_nack(void)                   //master sending NACK to slave
  220. {
  221.     SDA = 1;                         //set SDA high
  222.     I2C_delay();
  223.    
  224.     I2C_clock();
  225.    
  226.     SDA = 0;                         //set SCL to default high
  227. }
  228.  
  229. </pre>
  230.  
  231. <pre>
  232.  
  233. /*********************************************************************************
  234.   AT24C04 EEPROM HEADER FILE - ROUTINE/FUNCTION DECLARATIONS
  235. *********************************************************************************/
  236.  
  237. #ifndef __EEPROM_H
  238. #define __EERPOM_H
  239.  
  240. #define EEPROM_ID 0xA0          //in binary this would be 10100000 for read,and 0xA1 = 10100001 for write
  241.  
  242. extern bit NACK;
  243. extern SCL;
  244. extern SDA;
  245.  
  246.  
  247. unsigned char EEPROMread( unsigned char );
  248.  
  249. void EEPROMwrite( unsigned char ,unsigned char );
  250.  
  251. #endif
  252. </pre>
  253.  
  254.  
  255. <pre>
  256. /*********************************************************************************
  257.   AT24C04 EERPOM C FILE - ROUTINES/FUNCTIONS
  258.  
  259. **********************************************************************************/
  260. #include <reg51.h>
  261. #include <intrins.h>
  262. #include "AT24C04-I2C.h"                    //HEADER FILE FOR I2C RELATED OPERATIONS
  263. #include "AT24C04-EEPROM.h"
  264. #include "AT24C04-LCD.h"
  265.  
  266. /*PLEASE REFER AT24C04 datasheet's PAGE 12 - FIGURE 11 FOR THIS RANDOM READ IMPLEMENTATION */
  267.  
  268.  
  269. unsigned char EEPROMread( unsigned char eeprom_word_address )
  270. {
  271.     unsigned char received_data;
  272.  
  273.     NACK = 1;
  274.     while(NACK)
  275.     {
  276.         I2C_start();
  277.  
  278.         I2C_write( EEPROM_ID );                 //to identify the particular EEPROM device on I2C bus
  279.         I2C_check_NACK();                   //call function to check for ACK/NACK and set the flag NACK
  280.         if( NACK )
  281.             continue;  
  282.         lcddata('4');
  283.  
  284.         I2C_write( eeprom_word_address );       //write to the word address in that particular EEPROM  device
  285.         I2C_check_NACK();                   //call function to check for ACK/NACK and set the flag NACK
  286.         if( NACK )
  287.             continue;
  288.         lcddata('5');
  289.    
  290.         I2C_start();                        //REPEATED START
  291.    
  292.         I2C_write( EEPROM_ID + 1 );         // EEPROM_ID+1, R/W bit is now 1 for READ,passed to indicate reading from EEPROM device
  293.         I2C_check_NACK();                   //call function to check for ACK/NACK and set the flag NACK
  294.         if( NACK )
  295.             continue;  
  296.         lcddata('6');
  297.        
  298.         received_data = I2C_read();         //read data from that particular word address
  299.         I2C_ack();                          //SEND THE ACKNOWLEDGE TO TRANSMITTER - HERE TRANSMITTER IS EEPROM
  300.  
  301.         lcddata('7');
  302.         //lcddata( received_data );
  303.    
  304.         I2C_nack();                         //MCU sending NOACK because no further reading is to be done,NACK necessary for STOPing condition
  305.        
  306.         I2C_stop();                         // Stop I2C bus operations
  307.  
  308.     }
  309.     return received_data;
  310.  
  311. }
  312.      
  313. void EEPROMwrite( unsigned char eeprom_word_address,unsigned char store_data )
  314. {  
  315.     NACK = 1;                        //NACK intially set to 1 to make sure the while() loops execute,inside while loop it
  316.                                     // may be set to 0 if ACK from transmitter is 0 ..
  317.     while( NACK )                   //NACK global bit variable is set if no ACK in I2C routine..
  318.     {
  319.         I2C_start();                            //start I2C bus operation
  320.  
  321.         //lcddata( EEPROM_ID );
  322.         I2C_write( EEPROM_ID );             //get to interact the particular EEPROM device using its unique address
  323.         I2C_check_NACK();                   //call function to check for ACK/NACK and set the flag NACK
  324.         if( NACK )
  325.             continue;  
  326.         //lcddata('1');                        //PRINT SUCH VALUES TO LCD TO KNOW THE SEQUENCE OF STEPS HAPPENING
  327.        
  328.         I2C_write( eeprom_word_address );     //send particular word address,where data from RAM is to be written in that EEPROM device
  329.         I2C_check_NACK();                   //call function to check for ACK/NACK and set the flag NACK
  330.         if( NACK )
  331.             continue;  
  332.         //lcddata('2');
  333.  
  334.         I2C_write( store_data );
  335.         I2C_check_NACK();                   //call function to check for ACK/NACK and set the flag NACK
  336.         if( NACK )
  337.             continue;    
  338.         //lcddata('3');
  339.  
  340.         I2C_stop();                         //stop I2C bus operations    
  341.    
  342.     }
  343. }
  344.  
  345. </pre>
  346.  
  347. <pre>
  348. /**********************************************************************************
  349. LCD ROUTINES/FUNCTIONS
  350. **********************************************************************************/
  351.     #include "AT24C04-LCD.h"
  352.     #include <intrins.h>
  353.  
  354.  
  355.     void Delay( unsigned int itime)
  356.     {
  357.         int i,j;
  358.         for( i = 0; i < itime ;i++)
  359.             for( j = 0; j < 1275; j++);
  360.     }
  361.  
  362.     void lcdcmd( unsigned char value )
  363.     {
  364.           lcd_port = value;
  365.           RS = 0;       //register select = 0 for command mode
  366.           EN = 1;       //latch enable = HIGH
  367.           _nop_();
  368.           EN = 0;       //latch enable = LOW
  369.           Delay(10);
  370.           return;
  371.     }
  372.  
  373.     void lcddata( unsigned char value )
  374.     {
  375.           lcd_port = value;
  376.           RS = 1;       //register select = 1 for data register
  377.           EN = 1;       //latch enable = HIGH
  378.           _nop_();
  379.           EN = 0;       //latch enable = LOW
  380.           Delay(30);
  381.           return;
  382.     }
  383.  
  384.     void lcdinitialize(void)
  385.     {
  386.         unsigned char l[10] = {0x38,0x0E,0x06,0x01,0x41};
  387.         unsigned char i;
  388.             for(i = 0 ;i <= 3 ; i++)
  389.             lcdcmd(l[i]);       //sending basic LCD commands to LCD
  390.     }
  391.  
  392. </pre>
  393.  
  394. <pre>
  395. /**********************************************************************************
  396.   AT24C04 LCD HEADER FILE - ROUTINE/FUNCTION DECLARATIONS
  397. **********************************************************************************/
  398. #include <reg51.h>
  399.  
  400. #ifndef __LCD_H
  401. #define __LCD_H
  402.  
  403.  
  404.  
  405.  
  406. //SFR names declarations
  407. sfr lcd_port = 0x90;        //address of PORT P1 ,used for data lines to LCD
  408. sbit EN = P3^4;
  409. sbit RS = P3^5;
  410.  
  411. //sbit RW =
  412.  
  413. //ANSI STYLE PROTOTYPE
  414. void lcddata( unsigned char value);
  415.  
  416. void lcdcmd( unsigned char value);
  417.  
  418. void Delay( unsigned int itime );
  419.  
  420. void lcdinitialize(void);
  421.  
  422. #endif
  423.  
  424. </pre>
  425.  
  426.  
  427. /****************************************************************************/
  428.  
  429. /****************************CODE FOUND ON THE FORUM*************************/
  430.  
  431. #include "AT24C04-LCD.h"
  432. #include <reg51.h>
  433. #include <intrins.h>
  434.  
  435.  
  436. sbit sda = P3^6;
  437. sbit sclk = P3^7;
  438.  
  439. /************************** prototypes begin*******************/
  440. void send_byte_s_eeprom(char );
  441. void send_to_mem(unsigned char , unsigned char );
  442. unsigned char get_byte_s_eeprom();
  443. void noacknowledge();
  444. void acknowledge();
  445. unsigned char get_from_mem(unsigned char );
  446. void wait();
  447. void start_s_eeprom();
  448. void stop_s_eeprom();
  449. /************************** prototypes end******************/
  450.  
  451.  
  452.  
  453. void send_to_mem(unsigned char s_address, unsigned char s_data)
  454.  {
  455.     start_s_eeprom();             // sending start condition to eeprom
  456.     send_byte_s_eeprom(0XA0);     // A0 = 10100000 = sending device address word for write
  457.     acknowledge();
  458.     send_byte_s_eeprom(s_address); // sending data address
  459.     acknowledge();
  460.     send_byte_s_eeprom(s_data);   // sending data
  461.     acknowledge();
  462.     stop_s_eeprom();              // sending stop condition to eeprom
  463. //    acknowledge();
  464.    
  465.  }
  466.  
  467.  
  468. // fxn to get the data back frm the serial eeprom
  469. // just give the adress from where the data is to be retrieved
  470.  
  471.  
  472. unsigned char get_from_mem(unsigned char s_address)
  473. {
  474.  unsigned char i;
  475. //-------dummy write seq----+ word address--------------------------------------
  476.     start_s_eeprom();              // sending start condition to eeprom
  477.     send_byte_s_eeprom(0XA0);      // sending A0 = 10100000 = device address word for write
  478.     acknowledge();
  479.     send_byte_s_eeprom(s_address); // sending data address
  480.     acknowledge();
  481. //----------------dummy over----------------------------------------------------
  482.  
  483.     start_s_eeprom();
  484.     send_byte_s_eeprom(0XA1);     // sending A1 =10100001 = device adress word for read
  485.     acknowledge();
  486.     i = get_byte_s_eeprom();       // sending data
  487.     noacknowledge();
  488.     stop_s_eeprom();              // sending stop condition to eeprom
  489.  
  490.    return(i);
  491.  }
  492.  
  493.  
  494. /* fxn to transmit a byte to the eeprom
  495. this fxn just send the 8 bits serialy on the SDA line
  496. just pass the byte to be transmitted as parameter to this fxn */
  497. void send_byte_s_eeprom(char s_byte)
  498. {
  499.     //unsigned  char temp ;
  500.     char i ;
  501.  
  502.    
  503.     for(i = 7 ; i >= 0 ; i--) //scan data do be place in SDA
  504.     {
  505.      /* note SCL is low during transitions on SDA */
  506.         if( ((s_byte >> i) & 0x01) == 0) //check individual bits
  507.         sda =   0;
  508.         else
  509.         sda =   1;
  510.  
  511.         sclk   =   1;
  512.         wait();
  513.         sclk   =   0;
  514.        
  515.     }
  516. }
  517.  
  518.  
  519.  
  520. // fxn to receive 8 bits serialy from sda line
  521. // this is not a fxn to read from eeprom
  522. // it just receives 8 bits serialy and retuns the byte received to the calling fxn
  523.  
  524. unsigned char get_byte_s_eeprom()
  525.  {
  526.     char temp, temp_h, i;
  527.     temp = 0;
  528.     temp_h = 1;    
  529.  
  530.     sda = 1;    // making SDA as input pin for microcontroller
  531.       sclk    =    0;
  532.  
  533.     for(i = 7; i >=0 ; i--)
  534.     {
  535.         sclk = 1;
  536.      
  537.         if(sda == 1)
  538.         {
  539.             temp = temp | temp_h<<i ;                      
  540.         }
  541.         wait();
  542.         sclk = 0;
  543.  
  544.     }
  545.    
  546.     sclk = 0;
  547.     return(temp);
  548.  }
  549.  
  550.  
  551. // fxn to send the start condition
  552.  void start_s_eeprom()
  553.  {
  554.     sda     =   1;
  555.     sclk    =   1;
  556.     wait();
  557.     sda     =   0;
  558.     sclk    =   0;  
  559.  
  560.  }
  561.  
  562.  
  563. // fxn to send stop condition
  564.  void stop_s_eeprom()
  565.  {
  566.     sda     =   0;
  567.     sclk    =   1;
  568.     wait();
  569.     sda     =   1;
  570.     sclk    =   0;  
  571.  }
  572.  
  573.  
  574. // fxn for acknowledging the eeprom
  575. // this fxn actualy does not read the acknowledge signal
  576. // it just waits for sufficient time and assumes that the eeprom has given tha ack by the time the wait gets over
  577.  void acknowledge()
  578.  {
  579.        
  580.      sda  = 0;
  581.      sclk = 1;
  582.        wait();
  583.     sclk = 0;
  584.  }
  585.  
  586.  
  587. //  a small delay fxn to ensure the line settles down after transition
  588.  void wait()
  589.  {
  590.     //char i;
  591.     //for(i=0;i<=20;i++)
  592.     //i++;
  593.  
  594.  }
  595.  
  596. void noacknowledge()
  597. {  
  598.      sda  = 1;
  599.      sclk = 1;
  600.        wait();
  601.     sclk = 0;
  602. }  
  603.  
  604.  
  605. void main()
  606. {
  607.     unsigned char i,location = 0x000;
  608.     unsigned char userdata[7] = {'P','Q','R','S','T','U','G'};
  609.     lcdinitialize();
  610.     send_to_mem(location,userdata[0]);
  611.     for( i = 0; i < 7; i++)
  612.     {
  613.         send_to_mem(location+i,userdata[i]);
  614.         Delay(50);
  615.     }  
  616.  
  617.     Delay(150);
  618.     lcddata(get_from_mem(0x000));
  619.  
  620. }
  621.  
  622.  
  623. //*********************************************************************
  624.  
  625.     #include "AT24C04-LCD.h"
  626.     #include <intrins.h>
  627.  
  628.  
  629.     void Delay( unsigned int itime)
  630.     {
  631.         int i,j;
  632.         for( i = 0; i < itime ;i++)
  633.             for( j = 0; j < 1275; j++);
  634.     }
  635.  
  636.     void lcdcmd( unsigned char value )
  637.     {
  638.           lcd_port = value;
  639.           RS = 0;       //register select = 0 for command mode
  640.           EN = 1;       //latch enable = HIGH
  641.           _nop_();
  642.           EN = 0;       //latch enable = LOW
  643.           Delay(10);
  644.           return;
  645.     }
  646.  
  647.     void lcddata( unsigned char value )
  648.     {
  649.           lcd_port = value;
  650.           RS = 1;       //register select = 1 for data register
  651.           EN = 1;       //latch enable = HIGH
  652.           _nop_();
  653.           EN = 0;       //latch enable = LOW
  654.           Delay(30);
  655.           return;
  656.     }
  657.  
  658.     void lcdinitialize(void)
  659.     {
  660.         unsigned char l[10] = {0x38,0x0E,0x06,0x01,0x41};
  661.         unsigned char i;
  662.             for(i = 0 ;i <= 3 ; i++)
  663.             lcdcmd(l[i]);       //sending basic LCD commands to LCD
  664.     }
  665.  
  666. //********************************************************************************
  667. /*
  668.   AT24C04 LCD HEADER FILE - ROUTINE/FUNCTION DECLARATIONS
  669. */
  670. #include <reg51.h>
  671.  
  672. #ifndef __LCD_H
  673. #define __LCD_H
  674.  
  675.  
  676.  
  677.  
  678. //SFR names declarations
  679. sfr lcd_port = 0x90;        //address of PORT P1 ,used for data lines to LCD
  680. sbit EN = P3^4;
  681. sbit RS = P3^5;
  682.  
  683. //sbit RW =
  684.  
  685. //ANSI STYLE PROTOTYPE
  686. void lcddata( unsigned char value);
  687.  
  688. void lcdcmd( unsigned char value);
  689.  
  690. void Delay( unsigned int itime );
  691.  
  692. void lcdinitialize(void);
  693.  
  694. #endif
  695.  
  696.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement