Ceci est une ancienne révision du document !
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.
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).
/*
* 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;
}
/*
* 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;
}