This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

i2c driver from scratch using direct register access

//-----------------------------------------------------------------------------------------------
        void i2c_init(unsigned char addr)
        { 
        
          NRF_TWI0->PSELSCL=27;
          NRF_TWI0->PSELSDA=26;
        
          NRF_TWI0->ADDRESS=addr;
        
          //TWSR = 0x00;
          //NRF_TWI0->FREQUENCY = 0x01980000;   //100 KHz 
          NRF_TWI0->FREQUENCY = 0x06680000;     //400 Khz
        
          NRF_TWI0->ENABLE = 0x00000005;
        }
        
        
        void i2c_startTX() 
        { 
          NRF_TWI0->TASKS_STARTTX=1; 
        }
        
        
        void i2c_startRX() 
        { 
          NRF_TWI0->TASKS_STARTRX=1;
        }
        
        void i2c_write(unsigned char data)
        { 
          NRF_TWI0->TXD=data;
          while(NRF_TWI0->EVENTS_TXDSENT==0){}
          NRF_TWI0->EVENTS_TXDSENT=0;
        }
        
        unsigned char i2c_read(void)
        {
        
         unsigned char data;
        
         while(NRF_TWI0->EVENTS_RXDREADY==0){}  
         NRF_TWI0->EVENTS_RXDREADY=0;
        
         data = NRF_TWI0->RXD;
        
         return data;
        
        }
        
        
        void i2c_stop(void)
        {
          NRF_TWI0->TASKS_STOP=1;
          while(NRF_TWI0->EVENTS_STOPPED==0){}
          NRF_TWI0->EVENTS_STOPPED=0;
        }
    
    //-----------------------------------------------------------------------------------------------
    
        void eeprom_init()
        {
          unsigned char cntr;
        
          i2c_init(0x50);  // EEPROM i2c address
          
          i2c_startTX();
          i2c_write(0x00);
        
          for(cntr=0;cntr<=15;cntr++)
          {
            i2c_write('A' + cntr);
          }
        
          i2c_stop();
        
          nrf_delay_ms(10);
        
          serial_write_string("EEPROM initialisation completed !!\n\r");
        }
        
        void eeprom_read(unsigned char addr)
        {
          unsigned char boo[17]={'\0'};
          unsigned char cntr;
          int data;
        
          i2c_startTX();
          i2c_write(addr);
          //i2c_stop();
        
          i2c_startRX();
          for(cntr=0;cntr<=15;cntr++)
          {
            boo[cntr]=i2c_read();
          }
          i2c_stop();
        
          serial_write_string(boo);     //<-- I'm talking about this 
          serial_write_string("\n\r");
          
        }
    
    //-------------------------------------------------------------------------------------------

I've written basic i2c functions as mentioned above to access AT24C04 EEPROM.

This EEPROM drivers works for me but "serial_write_string(boo)" from eeprom_read() prints -> PABCDEFGHIJKLMNO.

Ideally it should print -> ABCDEFGHIJKLMNOP

I used same code on Arduino & it give me correct output. Why nrf52840-pdk is giving me such strange output ?

I've already solved this issue by modifying my eeprom_read() function as follow

void eeprom_read(unsigned char addr)
{
  unsigned char boo[17]={'\0'};
  unsigned char cntr;
  int data;

  i2c_startTX();
  i2c_write(addr);
  //i2c_stop();

  i2c_startRX();
  for(cntr=0;cntr<=14;cntr++) 
  {
    boo[cntr]=i2c_read();
  }
  i2c_stop();                      
  boo[15]=i2c_read();       // read last byte after sending i2c_stop()

  serial_write_string(boo);
  serial_write_string("\n\r");
  
}

This function accurately prints what I'm expecting that is "ABCDEFGHIJKLMNOP"

could someone explain me, why this so ?

How to send NACK with last byte while reading multiple bytes from i2c device ? (Generally we send ACK when reading byte is not last byte & send NACK when we request last byte to read)

nrf528xx data-sheet does not allow me to do this. Why ?

I don't wanna use APIs provided by SDK. So kindly don't give me that solution.

Thank You !!

Parents Reply Children
No Data
Related