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
  • [issue is solved !!]

    I found my mistake. Here I'm presenting my ( tested on nRF52840-PDK ) corrected version .....

    //-----------------------------------------------------------------------------------------------------------
    
    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(unsigned char nack)
    {
    
        unsigned char data;
        
        if(nack==1)
        {
            NRF_TWI0->TASKS_STOP=1;
        }
    
        while(NRF_TWI0->EVENTS_RXDREADY==0){}  
        NRF_TWI0->EVENTS_RXDREADY=0;
    
        data = NRF_TWI0->RXD;
    
        return data;
    
    }
    
    
    void i2c_stopTX(void)
    {
        NRF_TWI0->TASKS_STOP=1;
        while(NRF_TWI0->EVENTS_STOPPED==0){}
        NRF_TWI0->EVENTS_STOPPED=0;
    }
    
    void i2c_stopRX(void)
    {
        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_stopTX();
    
        nrf_delay_ms(10);  // delay for EEPROM write 
    
        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++)
        {
            if(cntr != 15)
            {
                boo[cntr]=i2c_read(0);
            }
            else
            {
                boo[cntr]=i2c_read(1);
            }
        }
        i2c_stopRX();
    
        serial_write_string(boo);    
        serial_write_string("\n\r");
    
    }
    
    //--------------------------------------------------------------------------------------------------------
    
Reply
  • [issue is solved !!]

    I found my mistake. Here I'm presenting my ( tested on nRF52840-PDK ) corrected version .....

    //-----------------------------------------------------------------------------------------------------------
    
    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(unsigned char nack)
    {
    
        unsigned char data;
        
        if(nack==1)
        {
            NRF_TWI0->TASKS_STOP=1;
        }
    
        while(NRF_TWI0->EVENTS_RXDREADY==0){}  
        NRF_TWI0->EVENTS_RXDREADY=0;
    
        data = NRF_TWI0->RXD;
    
        return data;
    
    }
    
    
    void i2c_stopTX(void)
    {
        NRF_TWI0->TASKS_STOP=1;
        while(NRF_TWI0->EVENTS_STOPPED==0){}
        NRF_TWI0->EVENTS_STOPPED=0;
    }
    
    void i2c_stopRX(void)
    {
        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_stopTX();
    
        nrf_delay_ms(10);  // delay for EEPROM write 
    
        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++)
        {
            if(cntr != 15)
            {
                boo[cntr]=i2c_read(0);
            }
            else
            {
                boo[cntr]=i2c_read(1);
            }
        }
        i2c_stopRX();
    
        serial_write_string(boo);    
        serial_write_string("\n\r");
    
    }
    
    //--------------------------------------------------------------------------------------------------------
    
Children
No Data
Related