I2c communication between Atmel and Arduino.

Go To Last Post
25 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
The Atmega is the master and the Arduino is the slave in i2c. The code below is the code part for Master transmitter of Atmega.  The problem here is the TWI Address/commands,the second parameter. What must I mention for Arduino? In arduino , only the slave address is mentioned. If required I can add my code.

typedef struct {
/* ! TWI chip address to communicate with. */
char chip;
/* ! TWI address/commands to issue to the other chip (node). */
uint8_t addr[3];
/* ! Length of the TWI data address segment (1-3 bytes). */
int addr_length;
/* ! Where to find the data to be written. */
uint8_t *buffer;
/* ! How many bytes do we want to write. */
unsigned int length;

} twi_package_t; 
Last Edited: Fri. Apr 21, 2017 - 10:18 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
 Atmega is the master and the Arduino is the slave

They are both Atmel in case you didn't know. What is you question?

 

And this forum is only for Studio bugs so I'll move the thread.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

Last Edited: Fri. Apr 21, 2017 - 10:18 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It appears you're looking at the TWI driver code from the ASF.

 

Here's the Atmel ASF quick start guide for the TWI driver:

 

http://asf.atmel.com/docs/latest/common.components.crypto.sha204.example_client_host.atxmega128a1_xplain/html/xmega_twi_quickstart.html

 

 

 

 

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

Thanks for the corrections . 

They are both Atmel in case you didn't know

I cannot understand this statement because. My master is ATmega and my Slave is Arduino DUE (Atmel SAM3X8E ARM Cortex-M3) . The ASF wizard which is provided is for Xmega but mine is ATmega. I am new to the AVR controllers , so I dont know whether the API for Xmega can be used for ATmega !! When I started learning, the Atmel studio,I had the option to select the board so I really dont know if both(ATmega Xmega) can be used for my Atmega board ?? In my I2c ,The master AVR is programmed in Atmel studio and My slave is programmed in Arduino IDE. My question is,  I have included  code part earlier. It asks for the "slave address" - this is the general address we assign for slave(DUE board in my case)  and it asks for another parameter called "slave memory address" - it says at which address in the slave should I write my data. Arduino does not have any specification like this. So what should I do in regard to this ? 

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

As for your master code, there's no code, just a structure.  You need only send the slave address and the data. 

 

The slave side seems trivial in Arduino.

https://www.arduino.cc/en/Tutori...

Why do you not use Arduino for the master? What atmega are you using for the master? Do you realise the Arduino tools support quite a few devices - you don't need to have an Arduino board.

 

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

Hi,

 

Atmega used is Atmega128 RFR2. Because, the slave of Atmega has to check the status code everytime and acknowledgements everytime. So Atmega as Master was easy. Arduino master or slave it is very simple design to choose. I have attached the link of the example that I follow: (which I am using as reference to program ,nothing unique in my code) 

 

 

http://asf.atmel.com/docs/latest/mega.drivers.twi.master_example.atmega256rfr2_atmega256rfr2_xplained_pro/html/twi__master__example_8c.html

 

This is At256 but At128 is almost the same for twi driver module. Only this was available.

 

Thank you. 

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

pika wrote:
I am new to the AVR controllers

Do you have experience with any other microcontroller(s) ?

 

, so I dont know whether the API for Xmega can be used for ATmega !!

Assume NO unless specifically stated otherwise!

 

AIUI, Xmega peripherals (such as I2C) are not the same as ATmega.

 

 I really dont know if both(ATmega Xmega) can be used for my Atmega board ??

Almost certainly not.

 

I have included  code part earlier. It asks for the "slave address" - this is the general address we assign for slave(DUE board in my case)  and it asks for another parameter called "slave memory address"

Well, of course it does - because the example you say you're using is for talking to a memory device - specifically, an EEPROM!!

 

 

http://asf.atmel.com/docs/latest...

 

 

Arduino does not have any specification like this. So what should I do in regard to this ? 

  • Either choose a different Master example which more closely matches your Slave
     
  • Or modify your Slave so that it does look like a "memory" device

 

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

 

Yes, I have experience with PIC micro-controller and 8051. But not very much with communication protocols, something with interrupts ,timers, counters. . . 

 

Well, of course it does - because the example you say you're using is for talking to a memory device - specifically, an EEPROM!!

 

The point is Not only this specific example, but the general TWI driver also has the same format,here it is:

 http://asf.atmel.com/docs/latest/mega.drivers.twi.master_example.atmega256rfr2_atmega256rfr2_xplained_pro/html/twi__megarf_8c.html

 

 asking for a specific memory address, so I had got this doubt. To be honest, I thought , add the library and pass the parameters, and the output will be obtained.wink

 

Thank you for the above answers . I will try them. 

 

 

 

Last Edited: Mon. Apr 24, 2017 - 09:23 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Start with two Arduinos. Run one as Master, the other as Slave.
Then replace the Master with regular C code. e.g. Fleury.
.
Note that this strategy can work with most homework problems. Arduino has working code for almost everything.
If you develop on Arduino, you start with success. It is even used by professionals. e.g. write test code in Arduino.
.
Remember that Fleury uses 8-bit Slave address e.g. 0xA0 for 24Cxx. Arduino Wire.h uses 7-bit Slave e.g. 0x50.
.
David.

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

david.prentice wrote:
Remember that Fleury uses 8-bit Slave address e.g. 0xA0 for 24Cxx. Arduino Wire.h uses 7-bit Slave e.g. 0x50.

See: http://www.avrfreaks.net/comment...

 

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

pika wrote:
The point is Not only this specific example, but the general TWI driver also has the same format,here it is:

 http://asf.atmel.com/docs/latest/mega.drivers.twi.master_example.atmega256rfr2_atmega256rfr2_xplained_pro/html/twi__megarf_8c.html 

 

Given the specific mention of "atmega256rfr2_xplained_pro" in that URL, I rather doubt that this is a "general" driver: it looks very much like it is specifically for that particular board - and, thus, for the specific EEPROM on that particular board.

 

But, as David said, why not just use 2 Arduinos??

 

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

awneil wrote :But, as David said, why not just use 2 Arduinos??

 

 

like http://www.gammon.com.au/i2c (an arduino sends "hello world " to his/her slave; the latter displays it ; worked)

Another advantage of this link : you can find the I2C adress  of a device with a scanner -this is very comfortable -; code is given in "Reply 6" n (on rPI, comes from i2c-tools);

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

I guess the other question is: why do you need two boards anyhow?

 

What are you doing that either one of the boards can't do on its on??

 

http://www.catb.org/~esr/faqs/sm...

 

 

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

Yes, I would try with two Arduinos. That would be better ..

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

But why use two of anything?

 

Why can't this be done on just one board??

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

Because that would be seriously difficult.

 

The assignment is for "separate Master and Slave".  

 

I generally suggest:

1.  One Master and One hardware Slave chip e.g. 24Cxxx.

2.  Then try Arduino Master and software Slave (on another Arduino)

3.  Then replace the Arduino Master with Fleury (or similar Master)

4.  Then replace the Arduino Slave with AVR311 (or similar TWI app note)

 

Every step has got something to compare with.

The OP only needs to go as far as (3).

 

I would expect that anyone could write a polled TWI Master.   An interrupt driven Slave is fairly tricky.

It is necessary to understand how Fleury is designed and written.    I see little point in writing it from scratch.

 

The main lesson to be learned is :  "how to use an App Note or Library example"

 

David.

Last Edited: Mon. Apr 24, 2017 - 04:16 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Because that would be seriously difficult.

 

The assignment is for "separate Master and Slave".  

 

I generally suggest:

1.  One Master and One hardware Slave chip e.g. 24Cxxx.

2.  Then try Arduino Master and software Slave (on another Arduino)

3.  Then replace the Arduino Master with Fleury (or similar Master)

4.  Then replace the Arduino Slave with AVR311 (or similar TWI app note)

 

Every step has got something to compare with.

The OP only needs to go as far as (3).

 

I would expect that anyone could write a polled TWI Master.   An interrupt driven Slave is fairly tricky.

It is necessary to understand how Fleury is designed and written.    I see little point in writing it from scratch.

 

The main lesson to be learned is :  "how to use an App Note or Library example"

 

David.

I almost tried this.

 

I tried with two arduinos .One master and one as slave. It was fine and easy.  i only have atmega 256rfr and 2 arduinos. So basically i want to establish i2c between atmega and arduino. After many attempts, I fixed Arduino as master and Atmega as slave. With Atmega , I have read the slave example from the library of Atmel studio . I have added code below:
 

/

/**
 * \mainpage
 *
 * \section intro Introduction
 * This is the documentation for the data structures, functions, variables,
 * defines, enums, and typedefs for the TWI slave mode example.
 *
 * \section files Main Files
 * - twi_slave_example.c: example application.
 * - conf_board.h: board configuration
 * - conf_twi.h: TWI slave configuration used in this example
 *
 * \section driverinfo twi slave Driver
 * The twi driver can be found \ref group_megarf_drivers_twi "here".
 *
 * \section deviceinfo Device Info
 * AVR MEGARF device can be used.
 *
 * \section exampledescription Description of the example
 * The given example uses one kit as a TWI slave:
 *    - the TWI slave gets data for the a write request from TWI master,
 *    - the TWI slave send data for the a read request from TWI master,
 *
 * Yellow LED , Green LED gives the result of the test:
 * Green LED is ON when transmission is success.
 * Yellow LED is ON when reception is success.
 *
 * \section compinfo Compilation Info
 * This software was written for the GNU GCC and IAR for AVR.
 * Other compilers may or may not work.
 *
 * \section contactinfo Contact Information
 * For further information, visit
 * <A href="http://www.atmel.com/avr">Atmel AVR</A>.\n
 */
/*
 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
 */
#include "asf.h"
#include <conf_twi.h>

/** \name Slave memory Test Pattern Constants */
/** @{*/

#define PATTERN_TEST_LENGTH     sizeof(test_pattern)
const uint8_t test_pattern[] = {
    0x05,
    0x15,
    0x25,
    0x35,
    0x45,
    0x55,
    0x65,
    0x75,
    0x85
};

uint8_t data_received[PATTERN_TEST_LENGTH] = {0};

/** @}*/

#define SLAVE_BUS_ADDR       0xB0        /* !< TWI slave bus address */
#define TWI_GCE              0x01        /* !< TWI slave general call enable */

static void twi_Transmission_Failure(void);
static void twi_Transmit_Success(void);
static void twi_Receive_Success(void);

/**
 * \brief TWI Slave Example Main
 */
int main(void)
{
    /* Initialize the common clock service, board-specific initialization,
     * and
     * interrupt vector support prior to using the TWI master interfaces.
     */
    sysclk_init();

    board_init();

    /* Enable the peripheral clock for TWI module */
    sysclk_enable_peripheral_clock(&TWBR);

    /* Initialize the TWI Slave driver. */
    twi_slave_init(SLAVE_BUS_ADDR | TWI_GCE);

    /* Enable global interrupt */
    cpu_irq_enable();

    slave_data_buffer_t data_buffer = {
        .rx_buffer = (void *)data_received, /* transfer data source
                                             * buffer */
        .tx_buffer = (void *)test_pattern
    };

    /* Start the TWI slave Transceiver */
    twi_slave_start(&data_buffer);

    /* Wait in infinite loop and check for TWI status */
    while (1) {
        if (twi_slave_state_get() == TWI_IDLE) {
            switch (twi_slave_status_get()) {
            case TWI_STATUS_TX_COMPLETE:
                twi_Transmit_Success();
                break;

            case TWI_STATUS_RX_COMPLETE:
                twi_Receive_Success();
                break;

            case TWI_STATUS_NO_STATE:
                break;

            default:
                twi_Transmission_Failure();
                break;
            }
        }
    }
}

/**
 * \brief TWI transmission failure indication through red LED On
 */
static void twi_Transmission_Failure(void)
{
    /* Red LED ON */
    LED_On(LED_RED_GPIO);

    twi_slave_status_reset();
}

/**
 * \brief TWI transmit success indication through green LED On
 */
static void twi_Transmit_Success(void)
{
    /* Green LED ON */
    LED_On(LED_GREEN_GPIO);

    twi_slave_status_reset();
}

/**
 * \brief TWI receive success indication through yellow LED On
 */
static void twi_Receive_Success(void)
{
    /* Yellow LED ON */
    LED_On(LED_YELLOW_GPIO);

    twi_slave_status_reset();
}

 

This is the example code. If I want to use this example with the Arduino. I removed the receiving part and did only the transmitting part . My edited code is below:


#include "asf.h"
#include <conf_twi.h>

#define SLAVE_BUS_ADDR      0x03 

const uint8_t test_sample[] = {0xBB};
static void twi_Transmission_Failure(void);
static void twi_Transmit_Success(void);

int main(void)
{
	/ * Initialize the common clock service, board-specific initialization,
	 * and
	 * interrupt vector support prior to using the TWI master interfaces.
	 * /
	sysclk_init();

	board_init();

	/ * Enable the peripheral clock for TWI module * /
	sysclk_enable_peripheral_clock(&TWBR);

	/ * Initialize the TWI Slave driver. * /
	twi_slave_init(SLAVE_BUS_ADDR);

	/ * Enable global interrupt * /
	cpu_irq_enable();

	slave_data_buffer_t data_buffer = {

		.tx_buffer = (void *)test_sample
	};

   / * Start the TWI slave Transceiver * /
   twi_slave_start(&data_buffer);

	while (1) {}

		twi_slave_data_write(&data_buffer);
		if (twi_slave_state_get() == TWI_IDLE) {
			switch (twi_slave_status_get()) {
				case TWI_STATUS_TX_COMPLETE:
				twi_Transmit_Success();
				break;

				case TWI_STATUS_NO_STATE:
				break;

				default:
				twi_Transmission_Failure();
				break;
			}
		}
	}
	}

	static void twi_Transmit_Success(void)
{

	twi_slave_status_reset();
}

static void twi_Transmission_Failure(void)
{

	twi_slave_status_reset();
}

The link below gives the drivers used and the functions. The example is also found here. I pasted it for convenience

http://asf.atmel.com/docs/3.21.0/mega.drivers.twi.slave_example.atmega128rfa1_stk600-rc128x_rfx/html/twi__slave__example_8c.html#func-members

 

But the Arduino did not receive anything.

My arduino mastr reader code works as I checked the code with other arduino:

#include <Wire.h>

void setup() {
  // put your setup code here, to run once:
Wire.begin();        // join i2c bus (address optional for master)
Serial.begin(9600);  // start serial for output

}
void PrintHex8(int num,int precision)
{
  char tmp[16];
  char format[128];
  sprintf(format, "0x%%.%dX",precision);

  sprintf(tmp,format,num);
  Serial.println(tmp);
  }

void loop() {
  // put your main code here, to run repeatedly:
Wire.requestFrom(0x03, 8);    // request 6 bytes from slave device #2

  while(Wire.available())    // slave may send less than requested
  {
   Serial.println("Receiving");

   uint8_t i  = Wire.read();
   char c = Wire.read();
    PrintHex8(i,1);
    PrintHex8(c,1);
    delay(500);
 }

}

 any help is appreciable.

 

This link might be more easy to handle : https://github.com/avrxml/asf/blob/master/mega/drivers/twi/slave_example/twi_slave_example.c

 

Whenever i Tried using slave_data_write - it always said implicit declaration of function. So i really have no idea to use / test this.

 

thank you all.

Last Edited: Wed. Apr 26, 2017 - 12:19 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think you missed my point.

 

My question is: why do you need two separate boards?

 

ie, why can't you just do it all on one board?

 

This would remove the need for any form of inter-processor communications - I2C or otherwise!

Last Edited: Wed. Apr 26, 2017 - 12:24 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As,I said my aim is i2c between arduino and avr , hence I am trying with two boards. Hence I need them.

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

So this is purely a learning exercise in I2C ?

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

Yes, to be precise with two different IDE'S:

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

For someone with "not very much" experience with communication protocols, that does seem like an extremely - and unnecessarily - complicated way to start!!

 

surprise

 

Surely, a more sensible approach would be:

 

  1. Gain familiarity in one IDE;
  2. Gain familiarity in the other IDE;
  3. Get the two talking.

 

Also, since by far the commonest use-case is for the microntroller to be the Master, I would suggest that you start with examples of using the microcontroller as Master with a well-known and widely-supported slave - such as an EEPROM or a PCF8574 IO expander.

 

As well as just getting the code to work, you should practice using debug & test tools - you should know what "good" signals look like on the line.

 

And don't just concentrate on the "working" case - investigate what happens in common failure cases; eg,

  • No slave connected;
  • Wrong slave address;
  • no pullups;
  • clock line disconnected;
  • data line disconnected;
  • etc, etc, ...

 

Think about how you can detect these conditions in your code, and give useful & meaningful error indications.

 

Then, when you have a good, working Master implementation, try making a slave for it to talk to...

Last Edited: Wed. Apr 26, 2017 - 01:01 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:
when you have a good, working Master implementation, try making a slave for it to talk to...

 

1+

 

Jim

 

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

@pika,

 

I am impressed.   Creating a Slave with ASF would do my head in.    I would have started with AVR311.

 

I would definitely choose to implement a polled Master first.   e.g. with Fleury.

And it is very easy to understand how Fleury works.   The TWI version runs on any Mega with TWI.   The bit-bashed version works on Tiny, Mega, Xmega.

 

Keep up the good work.   Develop a Test Suite to put your code through its paces.

 

David.

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

The fun part is making it reliable. I2c has a nasty habit of 'locking up' - if the state machines at both ends get of of sync then the party stops. You need timers to detect the lockup and to initiate recovery.