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; }