Outils pour utilisateurs

Outils du site


robotics:computing:communication_twi_entre_atmega

Ceci est une ancienne révision du document !


Introduction

Nous allons faire communiquer 2 atmega48 de chez ATMEL via la communication twi (i2c). Dans un premier temps, nous allons détailler un cas simple : un atmega en mode master et l'autre en mode slave.

Schema

Protocole

Ecriture sur l'esclave

La communication est initiée par le maitre qui envoie d'un bit de START. Ensuite, il envoie l'adresse de l'esclave sur 7 bits. Le 8ème bit sert à indiquer la direction l'échange (écriture ou lecture).

Lecture sur l'esclave

Slave

/*
 * twislave.c
 *
 *  Created on: 26 févr. 2010
 *      Author: gdo
 */

/* ATMEGA48 @20MHz
 * LOW FUSE : F7
 * CKDIV8=1		no divided clock by 8
 * CKOUT=1		no clock output on PORTB
 * SUT1..0=11	slowly rising power
 * CKSEL3..0=0111	full swing crystal oscillator
 */

#include <avr/interrupt.h>
#include<util/twi.h>

void twiSlaveInitialise(unsigned char myAddress);

ISR(TWI_vect)
{
	switch (TWSR)
	{
	/* Slave Transmitter*/
	case (TW_ST_SLA_ACK): /* 0xA8 : SLA+R received, ACK returned*/
		break;
	case (TW_ST_ARB_LOST_SLA_ACK): /* 0xB0 : arbitration lost in SLA+RW, SLA+R received, ACK returned */
		break;
	case (TW_ST_DATA_ACK): /* 0xB8 : data transmitted, ACK received */
		break;
	case (TW_ST_DATA_NACK):/*0xC0 : data transmitted, NACK received */
		break;
	case (TW_ST_LAST_DATA): /* 0xC8 : last data byte transmitted, ACK received */
		break;

		/* Slave Receiver */
	case (TW_SR_SLA_ACK):/* 0x60 : SLA+W received, ACK returned */
		break;
	case (TW_SR_ARB_LOST_SLA_ACK):/*0x68 : arbitration lost in SLA+RW, SLA+W received, ACK returned */
		break;
	case (TW_SR_GCALL_ACK): /*0x70 : general call received, ACK returned */
		break;
	case (TW_SR_ARB_LOST_GCALL_ACK): /* 0x78 : arbitration lost in SLA+RW, general call received, ACK returned */
		break;
	case (TW_SR_DATA_ACK): /* 0x80 : data received, ACK returned */
		break;
	case (TW_SR_DATA_NACK): /* 0x88 : data received, NACK returned */
		break;
	case (TW_SR_GCALL_DATA_ACK): /* 0x90 : general call data received, ACK returned */
		break;
	case (TW_SR_GCALL_DATA_NACK):/* 0x98 : general call data received, NACK returned */
		break;
	case (TW_SR_STOP):/* 0xA0 : stop or repeated start condition received while selected */
		break;

	default:
		break;
	}

	TWCR |= 0b10000000; // TWINT flag bit is cleared
}

void twiSlaveInitialise(unsigned char myAddress)
{
	PRR = (0 << PRTWI); // the PRTWI bit in PRR must be written to zero to enable the TWI
	TWAR = myAddress + 1; // Set own TWI slave address. Accept TWI General Calls.
	/* TWINT = 0 :
	 * TWEA = 1 : enable ACK
	 * TWSTA = 0: start condition
	 * TWSTO = 0 : stop condition
	 * TWEN = 1 : enable the TWI
	 * TWIE = 1 : enable TWI interrupt */
	TWCR = (0 << TWINT) | (1 << TWEA) | (0 << TWSTA) | (0 << TWSTO) | (1
			<< TWEN) | (1 << TWIE);
}

int main(void)
{
	twiSlaveInitialise(0x20);
	SREG = (1 << SREG_I); /* The Global Interrupt Enable bit must be set for the interrupts to be enabled */

	while (1)
	{
	}
	return 1;
}

Master

/*
 * twiMaster.c
 *
 *  Created on: 25 nov. 2009
 *      Author: gdo
 */

/* ATMEGA48 @20MHz
 * pull up resistor 1.5kohm
 * LOW FUSE : F7
 * CKDIV8=1		no divided clock by 8
 * CKOUT=1		no clock output on PORTB
 * SUT1..0=11	slowly rising power
 * CKSEL3..0=0111	full swing crystal oscillator
	*/

#include<util/twi.h>

//sets bitrate and prescaler
void twiMasterInitialise(unsigned char bitRate, unsigned char prescaler)
{
	PRR = (0 << PRTWI); // the PRTWI bit in PRR must be written to zero to enable the TWI
	TWSR = prescaler & 0x03;
	TWBR = bitRate;
}

void twiError(void)
{

}

void twiWait(unsigned char myStatus)
{
	while (!(TWCR & (1 << TWINT)))
		;
	if ((TWSR & 0xF8) != myStatus)
	{
		twiError();
	}
}

/* send START condition bit */
void twiStart(void)
{
	/* TWINT : TWI interrupt flag
	 * TWSTA : TWI START condition bit
	 * TWSTO : TWI STOP condition bit
	 * TWEN : TWI enable bit */
	TWCR = (1 << TWINT) | (1 << TWSTA) | (0 << TWSTO) | (1 << TWEN);
	twiWait(TW_START);
}

/* send slave address */
void twiAddress(unsigned char myAddress)
{
	TWDR = myAddress;
	TWCR = (1 << TWINT) | (0 << TWSTA) | (0 << TWSTO) | (1 << TWEN);
	twiWait(TW_MT_SLA_ACK); // 0x18, 0x20 or 0x38
}

/* send data */
void twiData(unsigned char myData)
{
	TWDR = myData;
	TWCR = (1 << TWINT) | (0 << TWSTA) | (0 << TWSTO) | (1 << TWEN);
	twiWait(TW_MT_DATA_ACK);
}

/* send STOP condition bit */
void twiStop(void)
{
	TWCR = (1 << TWINT) | (0 << TWSTA) | (1 << TWSTO) | (1 << TWEN);
}

/* write data to slaveAddress */
void twiWriteData(unsigned char slaveAddress, unsigned char data)
{
	twiStart();
	twiAddress(slaveAddress);
	twiData(data);
	twiStop();
}


int main(void)
{
	twiMasterInitialise(92, 0);	//set TWBR = 92 for 100kHz SCL @ 20MHz

	while (1)
	{
		twiWriteData(0x20, 0x05); //write 0x05 @0x20
	}
	return 1;
}
robotics/computing/communication_twi_entre_atmega.1267713710.txt.gz · Dernière modification: 2012/09/20 10:52 (modification externe)