I2C communication for Atmega4809

Go To Last Post
25 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello,

I am using Atmega4809 controller to communicate slave device using TWI interfacing.

But getting error in clearing TWI_WIF flag after writing slave address.

 

uint8_t TWI_start(uint8_t deviceAddr)
{
    if ((TWI0.MSTATUS & TWI_BUSSTATE_gm) != TWI_BUSSTATE_BUSY_gc)        
    {
        TWI0.MCTRLB &= ~(1 << TWI_ACKACT_bp);
        TWI0.MADDR = deviceAddr ;
        if (deviceAddr&0x01)    
        {
            while(!(TWI0.MSTATUS & TWI_RIF_bm));
        } 
        else            
        {
            while(!(TWI0.MSTATUS & TWI_WIF_bm));
        } 
        return 0;
    }
    else return 1;                                                         
}

 

This is my master write function where code is getting halted at  "while(!(TWI0.MSTATUS & TWI_WIF_bm)); "

Can you please help me to debug the issue..?

 

Regards,

Ekta

This topic has a solution.
Last Edited: Thu. Feb 18, 2021 - 10:23 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you didn't set the bus to IDLE somewhere, that would be a problem. If you didn't enable the twi that would be a problem. Can't see if you are doing these things or not.

 

This function- checking for not busy state still allows the UNKNOWN state. You can treat MCTRLB as a write only register since a command 0 does nothing, so just write a value (0 in this case). Will assume the address is already shifted with the rw bit included, but check it. If you do a read and are waiting for a RIF, you will be waiting a long time if the address was not ack'd because you get a WIF instead. A write should always result in a WIF, assuming the bus was idle or owned.

 

Here is a twim/s for an avr0/1-

https://github.com/cv007/Avr01Dx...

Its pretty simple, so you can look it over if you want. You will notice that I use the address register once to set an address (shifted into position), and write it while the twi is off so no start frame generated. After that I just use |= 1 on the address register to generate a start read, and &= ~1 to start a write, so then have no need to keep passing an address all around. These are also interrupt driven so can use a callback function or just block with a timeout.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the reply.

 

This is my complete code. What else can I add in this code to make it working.?

 

#define TWI0_BAUD(F_SCL)      ((((float)F_CPU / (float)F_SCL)) - 10 )

void TWI_init()
{
    TWI0.MBAUD = (uint8_t)TWI0_BAUD(100000);            
    TWI0.MCTRLA = 1 << TWI_ENABLE_bp            
    | 0 << TWI_QCEN_bp                    
    | 0 << TWI_RIEN_bp                    
    | 1 << TWI_SMEN_bp                    
    | TWI_TIMEOUT_DISABLED_gc                
    | 0 << TWI_WIEN_bp;                    

    TWI0.MCTRLB |= TWI_FLUSH_bm ;                
    TWI0.MSTATUS |= TWI_BUSSTATE_IDLE_gc ;                
    TWI0.MSTATUS |= (TWI_RIF_bm | TWI_WIF_bm) ;
}

uint8_t TWI_start(uint8_t deviceAddr)
{
    if ((TWI0.MSTATUS & TWI_BUSSTATE_gm) != TWI_BUSSTATE_BUSY_gc)        
    {
        TWI0.MCTRLB &= ~(1 << TWI_ACKACT_bp);
        TWI0.MADDR = deviceAddr ;
        if (deviceAddr&0x01)    
        {
            while(!(TWI0.MSTATUS & TWI_RIF_bm));
        } 
        else            
        {
            while(!(TWI0.MSTATUS & TWI_WIF_bm));
        } 
        return 0;
    }
    else return 1;                                                         
}

uint8_t TWI_read(uint8_t ACK)                            
{

    if ((TWI0.MSTATUS & TWI_BUSSTATE_gm) == TWI_BUSSTATE_OWNER_gc)        
    {
        while(!(TWI0.MSTATUS & TWI_RIF_bm));                
        uint8_t data=TWI0.MDATA;
        if (ACK==1)    
        {
            TWI0.MCTRLB &= ~(1<<TWI_ACKACT_bp);
        }        
        else            
        {
            TWI0.MCTRLB |= (1<<TWI_ACKACT_bp);    
        }    

        return data ;
    }
    else
    return 1;    //Master does not own the bus

}
uint8_t TWI_WRITE(uint8_t write_data)
{
    if ((TWI0.MSTATUS&TWI_BUSSTATE_gm) == TWI_BUSSTATE_OWNER_gc)                           
    {
        TWI0.MDATA = write_data;
        while (!((TWI0.MSTATUS & TWI_WIF_bm) | (TWI0.MSTATUS & TWI_RXACK_bm))) ;        
        return 0;
    }
    else
    return 1;    //Master does not own the bus
}

void TWI_STOP(void)
{
    TWI0.MCTRLB |= TWI_ACKACT_NACK_gc;
    TWI0.MCTRLB |= TWI_MCMD_STOP_gc;
}

 

int main(void)
{    
        SREG = 1;

        TWI_init();
        TWI_start(0x28);
        TWI_WRITE(0x07);
        TWI_STOP();

      while(1);

}

 

ISR(TWI0_TWIM_vect)
{
    TWI0.MSTATUS |= (TWI_RIF_bm | TWI_WIF_bm) ;
}

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello,

 

I have attached I2C waveform of above code.

but it is not as expected. 

Can you please tell me what is actual reason of getting this type of waveforms?

 

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Doesn't your scope have the facility to download a trace? That will give far better results that a photo.

 

Please see Tip #1 in my signature below for how to properly put a picture into your post:

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello,

 

you also can refer to this document :

 

Migration from the megaAVR® to AVR® Dx Microcontroller Families 

AN3731

ink online : http://ww1.microchip.com/downloads/en/Appnotes/Migration-from-megaAVR-to-AVR-DxMCU-Fam-DS00003731A.pdf

 

check the chapter 2.9 about TWI/I2C

 

best regards

Fabrice

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks Fabrice, 

 

Document referred by you is clearly understandable. 

But in Microchip studio IDE, do I need to add any specific include file ? because it is giving error to some unrecognized symbol.

I2C_ACKED

I2C_NACKED

I2C_ERROR

I2C_INIT

I2C_READY

 

Where can I find these symbols in the file?

 

Regards

Ekta

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello, 

I guess that you can assign the values you want to these identifiers.

They are just values to know on the fly the status of the I2C line.

 

by the way here is the code I use and works fine for me, with example of use included :

 

#define TWI0_BAUD(F_SCL)      ((((float)F_CPU / (float)F_SCL)) - 10 )

#define I2C_SCL_FREQ                                    100000

// I2C_base_ADDRESS                                     0b1000000  //address with 7 bits

#define I2C_DIRECTION_BIT_WRITE                         0
#define I2C_DIRECTION_BIT_READ                          1          

void I2C_0_init(void);
uint8_t I2C_0_start(uint8_t baseAddres, uint8_t directionBit);
uint8_t I2C_0_writingPacket (uint8_t data);
uint8_t I2C_0_receivingPacket(uint8_t acknack); 
void I2C_0_stop(void);

/*int main(void)
{
    I2C_0_init();
    
    while (1) 
    {
        I2C_0_start(I2C_BASE_ADDRESS, I2C_DIRECTION_BIT_READ);   //I2C_base_ADDRESS 7 bits
       
        result1 = I2C_0_receivingPacket(0);  //read with ack
        result2 = I2C_0_receivingPacket(1);  //read with nack
        I2C_0_stop();         
            
        I2C_0_start(I2C_BASE_ADDRESS, I2C_DIRECTION_BIT_WRITE);
        I2C_0_writingPacket(0x0D);  //write
        I2C_0_writingPacket(0x02);  //write
        I2C_0_stop();         
               
        _delay_ms(500);
    }
}*/

 void I2C_0_init(void)
{
    TWI0_MBAUD = (uint8_t)TWI0_BAUD(I2C_SCL_FREQ);	// set MBAUD register for I2C_SCL_Freq Hz
    TWI0_MCTRLA = TWI_ENABLE_bm;
    TWI0_MSTATUS = TWI_BUSSTATE_IDLE_gc;
}

uint8_t I2C_0_start(uint8_t baseAddres, uint8_t directionBit)
{
    TWI0_MADDR = (baseAddres<<1) + directionBit;
    while (!(TWI0_MSTATUS & (TWI_WIF_bm | TWI_RIF_bm)));    //wait for write or read interrupt flag
    if ((TWI0_MSTATUS & TWI_ARBLOST_bm)) return 0 ;         //return 0 if bus error or arbitration lost
    return !(TWI0_MSTATUS & TWI_RXACK_bm);                  //return 1 if slave gave an ack
}

uint8_t I2C_0_writingPacket(uint8_t data)
{
    while (!(TWI0_MSTATUS & TWI_WIF_bm));               //wait for write interrupt flag
    TWI0_MDATA = data;
    TWI0_MCTRLB = TWI_MCMD_RECVTRANS_gc;
    return (!(TWI0_MSTATUS & TWI_RXACK_bm));        //returns 1 if slave gave an ack
}

uint8_t I2C_0_receivingPacket(uint8_t acknack)      // 0 -> ack, else nack
{
    while (!(TWI0_MSTATUS & TWI_RIF_bm));               //wait for read interrupt flag
    uint8_t data = TWI0.MDATA;
    if (acknack == 0) {TWI0_MCTRLB = (TWI_ACKACT_ACK_gc  | TWI_MCMD_RECVTRANS_gc); }
    else                {TWI0_MCTRLB = (TWI_ACKACT_NACK_gc | TWI_MCMD_RECVTRANS_gc); }
    return data;
}

void I2C_0_stop(void)
{
    TWI0_MCTRLB = (TWI_ACKACT_NACK_gc | TWI_MCMD_STOP_gc);
}

Best regards

Fabrice

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you so much Fabrice.

 

I was really struggling with I2C library creation for ATMEGA4809 but couldn't get proper reference for TWI interfacing.

This is perfect code and it worked as expected on my slave device.

 

Best Regards,

Ekta Rathod

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ektarathod01 wrote:
This is perfect code and it worked

Please mark the solution - see Tip #5 in my signature, below:

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello,

 

I am trying to interface MFRC522 RFID module with ATMEGA4809 using I2C.

But could not set correct slave address.

RFID module is not giving acknowledgement for 0x50 and 0x28.

Can anyone help me to resolve this issue?

 

Regards,

Ekta Rathod

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

According to the datasheeet, the RC522 IC has its 7-bit I2C address defined according to the logic on the EA pin of the IC.   Is this pin wired to HI or LOW on your module?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

EA pin is connected to the ground

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ektarathod01 wrote:
But could not set correct slave address.

Easiest way is to make a simple program that just scans through all 127 possible slave addresses - then the one which responds is the address of your slave.

 

Also remember the all-too-common confusion between "8-bit" and "7-bit" slave addresses:

 

https://www.avrfreaks.net/commen...

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


ektarathod01 wrote:
RFID module is not giving acknowledgement for 0x50 and 0x28.
Just a minute. Those are 0b01010000 and 0b00101000 yet in the code you have:

// I2C_base_ADDRESS                                     0b1000000  //address with 7 bits

which is neither value ?!? Also even that does not look right because the datasheet actually says:

If pin EA is set LOW, the upper 4 bits of the device bus address are reserved by NXP Semiconductors and set to 0101b for all MFRC522 devices. The remaining 3 bits (ADR_0, ADR_1, ADR_2) of the slave address can be freely configured by the customer to prevent collisions with other I2C-bus devices.

So the address is actually 0b0101nnn where nnn are the start of the ADR_2, ADR_1, ADR_0 pins. So it would only be 0b0101000 if all three of those ADR pins are tied to ground - are they? BTW although only 7 of the 8 bits in the address are significant, because of:

    TWI0_MADDR = (baseAddres<<1) + directionBit;

if one really insists on using the terrible 0b number encoding I would always specify 8 bits so 0b00101nnn.

 

Having said all that:

 

 

shows that you actually have a choice of UART, SPI or I2C made with the I2C and EA pins so why on earth would one choose to torture yourself with I2C when you could be doing th very easy UART or easier still SPI instead?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks Clawson.

In my application, it is required to use I2C communication only.

And slave address detected. Actually I wasn't making NRST pin high.

 

Can I get reference to C library of MFRC522 ?

Because references available on internet are only for Arduino. I want to make c code working in ATmel studio.

 

Regards

Ekta

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ektarathod01 wrote:
Can I get reference to C library of MFRC522 ?

What does the manufacturer's product page say?

 

https://www.nxp.com/products/rfid-nfc/nfc-hf/nfc-readers/standard-performance-mifare-and-ntag-frontend:MFRC52202HN1?tab=Design_Tools_Tab

 

 

Because references available on internet are only for Arduino. I want to make c code working in ATmel studio.

You realise you can import an Arduino "sketch" into Atmel Microchip Studio ... ?

 

But Arduino code is just C++ - so you can look at it, and port that to any standard C++ IDE of your choice - maybe a little more effort to convert to C.

 

EDIT

 

Or just do it the old-school way from the datasheet: http://www.8052mcu.com/forum/rea...

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Mon. Feb 22, 2021 - 11:25 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ektarathod01 wrote:

Can I get reference to C library of MFRC522 ?

Because references available on internet are only for Arduino. I want to make c code working in ATmel studio.

Even though "Arduino code" is C++ you often find that the authors are barely scratching the surface of what is possible in C++ and it will be very easy to convert it to plain C. The only possible stumbling block is where it calls on other "Arduino functions" like millis() or pinMode() or digitalWrite() or whatever. If it uses other bits of Arduino you will need to provide "C equivalents" for those.

 

(or another approach is simply to switch your entire project over to C++ anyway, anything written as C should work just as well as C++ then it can more easily integrate with stiff from Arduino - though you still need to consider how to replace the "other bits of Arduino" unless you simply want to do a complete "project import" as Andy suggested above.

 

PS googling for code (with added -Arduino to exclude anything related to Arduino) hits, for example:

 

http://randomport.com/doxygen/av...

 

Interesting looking API. Dunno yet where the actual code that is documented is located though!

 

EDIT: found the code:

 

https://github.com/matejx/avr_lib

 

That includes mfrc522.c and .h

 

Oh and the file includes:

This file was not written by me from scratch. It was adapted from code by Miguel Balboa at https://github.com/miguelbalboa/...

so probably worth a look too. 

Last Edited: Mon. Feb 22, 2021 - 12:47 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Is it necessary to create constructor instance in C code as created in C++ library?

 

Because I have implemented c code same code as C++ but it is giving timeout error.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ektarathod01 wrote:
Is it necessary to create constructor instance in C code

"constructor instance" doesn't really have any meaning in C code.

 

Of course, you will have to "manually" do all the initialisation, memory allocation, etc that a C++ constructor would do.

 

it is giving timeout error.

So what debugging have you done to find out where it is timing-out, what it's waiting for when it times-out, etc ?

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ektarathod01 wrote:

Is it necessary to create constructor instance in C code as created in C++ library?

 

Because I have implemented c code same code as C++ but it is giving timeout error.

If there is "init" code in a c'tor then if you back port C++ to C you need to do whatever the c'tor was doing in some kind of a XXX-_nit() call instead.

 

But wait a minute - the links I gave in #18 are to mfrc522.c - it is C code already, not C++. What C++ code are you talking about??

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks Clawson.

But provided c code is not working.

Have anyone tested it??

 

Do we need to configure timer interrupt for it?

 

Regards,

Ekta

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ektarathod01 wrote:
Do we need to configure timer interrupt for it?

What does its documentation say?

 

EDIT

 

clawson gave you two links - have you checked them both?

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Tue. Mar 2, 2021 - 09:02 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ektarathod01 wrote:
Yes.

In reply to what?

 

https://www.avrfreaks.net/forum/man-forum-how-reply-post-forum

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Wed. Mar 3, 2021 - 08:16 AM