Cette page vous affiche les différences entre la révision choisie et la version actuelle de la page.
|
robotics:computing:communication_twi_entre_atmega [2013/03/12 11:01] ldo [Master] |
robotics:computing:communication_twi_entre_atmega [2013/09/27 15:56] (Version actuelle) ldo [Master] |
||
|---|---|---|---|
| Ligne 55: | Ligne 55: | ||
| <code c> | <code c> | ||
| /* | /* | ||
| - | * twislave.c | + | * twi_slave.c |
| * | * | ||
| * Created on: 26 févr. 2010 | * Created on: 26 févr. 2010 | ||
| Ligne 61: | Ligne 61: | ||
| */ | */ | ||
| - | /* ATMEGA48 @20MHz | + | volatile uint8_t twi_flag_read_complete = 1; |
| - | * LOW FUSE : F7 | + | volatile uint8_t twi_flag_write_complete = 1; |
| - | * 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> | + | volatile uint8_t *twi_receive_buffer; |
| - | #include<util/twi.h> | + | volatile uint8_t *twi_transmit_buffer; |
| + | volatile uint8_t twi_i = 0; | ||
| - | void twiSlaveInitialise(unsigned char myAddress); | + | uint8_t twi_nb_data_to_transmit; |
| ISR(TWI_vect) | ISR(TWI_vect) | ||
| { | { | ||
| - | switch (TWSR) | + | uint8_t status; |
| - | { | + | |
| - | /* 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 */ | + | status = TWSR & 0xF8; |
| - | case (TW_SR_SLA_ACK):/* 0x60 : SLA+W received, ACK returned */ | + | switch (status) |
| - | break; | + | { |
| - | case (TW_SR_ARB_LOST_SLA_ACK):/*0x68 : arbitration lost in SLA+RW, SLA+W received, ACK returned */ | + | /* Slave Receiver */ |
| - | break; | + | case (TW_SR_SLA_ACK):/* 0x60 : SLA+W received, ACK returned */ |
| - | case (TW_SR_GCALL_ACK): /*0x70 : general call received, ACK returned */ | + | break; |
| - | break; | + | case (TW_SR_ARB_LOST_SLA_ACK):/*0x68 : arbitration lost in SLA+RW, SLA+W received, ACK returned */ |
| - | case (TW_SR_ARB_LOST_GCALL_ACK): /* 0x78 : arbitration lost in SLA+RW, general call received, ACK returned */ | + | break; |
| - | break; | + | case (TW_SR_GCALL_ACK): /*0x70 : general call received, ACK returned */ |
| - | case (TW_SR_DATA_ACK): /* 0x80 : data received, ACK returned */ | + | break; |
| - | break; | + | case (TW_SR_ARB_LOST_GCALL_ACK): /* 0x78 : arbitration lost in SLA+RW, general call received, ACK returned */ |
| - | case (TW_SR_DATA_NACK): /* 0x88 : data received, NACK returned */ | + | break; |
| - | break; | + | case (TW_SR_DATA_ACK): /* 0x80 : data received, ACK returned */ |
| - | case (TW_SR_GCALL_DATA_ACK): /* 0x90 : general call data received, ACK returned */ | + | twi_receive_buffer[0] = TWDR; |
| - | break; | + | break; |
| - | case (TW_SR_GCALL_DATA_NACK):/* 0x98 : general call data received, NACK returned */ | + | case (TW_SR_DATA_NACK): /* 0x88 : data received, NACK returned */ |
| - | break; | + | break; |
| - | case (TW_SR_STOP):/* 0xA0 : stop or repeated start condition received while selected */ | + | case (TW_SR_GCALL_DATA_ACK): /* 0x90 : general call data received, ACK returned */ |
| - | break; | + | 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 */ | ||
| + | twi_flag_write_complete = 1; | ||
| + | break; | ||
| - | default: | + | /* Slave Transmitter */ |
| - | break; | + | case (TW_ST_SLA_ACK): /* 0xA8 : SLA+R received, ACK returned*/ |
| - | } | + | twi_i = 0; |
| + | TWDR = twi_transmit_buffer[twi_i]; | ||
| + | twi_i++; | ||
| + | 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 */ | ||
| + | TWDR = twi_transmit_buffer[twi_i]; | ||
| + | twi_i++; | ||
| + | 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; | ||
| - | TWCR = (1 << TWINT); // TWINT flag bit is cleared | + | default: |
| + | break; | ||
| + | } | ||
| + | |||
| + | TWCR |= (1 << TWINT); // TWINT flag bit is cleared | ||
| } | } | ||
| - | void twiSlaveInitialise(unsigned char myAddress) | + | /* TWI slave setup */ |
| + | void | ||
| + | twi_slave_setup(uint8_t address, volatile uint8_t * buffer, | ||
| + | volatile uint8_t *receive_buffer) | ||
| { | { | ||
| - | PRR = (0 << PRTWI); // the PRTWI bit in PRR must be written to zero to enable the TWI | + | TWAR = (address << 1); // Set own TWI slave address. Accept TWI General Calls. |
| - | TWAR = myAddress + 1; // Set own TWI slave address. Accept TWI General Calls. | + | twi_transmit_buffer = buffer; |
| - | /* TWINT = 0 : | + | twi_receive_buffer = receive_buffer; |
| - | * TWEA = 1 : enable ACK | + | TWCR = (1 << TWEA) | (1 << TWEN) | (1 << TWIE); |
| - | * TWSTA = 0: start condition | + | SREG |= (1 << SREG_I); |
| - | * 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) | + | volatile uint8_t tb[3], rb[3] ; |
| + | |||
| + | void | ||
| + | setup(void) | ||
| { | { | ||
| - | twiSlaveInitialise(0x20); | + | DDRD = 0xFF; |
| - | SREG = (1 << SREG_I); /* The Global Interrupt Enable bit must be set for the interrupts to be enabled */ | + | DDRC = 0x00; |
| + | twi_slave_setup(0x68, tb, rb); | ||
| + | } | ||
| + | |||
| + | int | ||
| + | main(void) | ||
| + | { | ||
| + | setup(); | ||
| - | while (1) | + | while (1) |
| - | { | + | { |
| - | } | + | if (rb[0]==0x41) |
| - | return 1; | + | { |
| + | tb[0] = 0x47; | ||
| + | tb[1] = 0x49; | ||
| + | } | ||
| + | else | ||
| + | { | ||
| + | tb[0] = 0x27; | ||
| + | tb[1] = 0x29; | ||
| + | } | ||
| + | } | ||
| } | } | ||
| </code> | </code> | ||
| Ligne 146: | Ligne 169: | ||
| Ce code permet d'envoyer une donnée à un esclave. | Ce code permet d'envoyer une donnée à un esclave. | ||
| - | Dans un premier temps, on va définir la vitesse de communication en initialisant TWBR et le prescaler dans twiMasterInitialise(). | + | Dans un premier temps, on va définir la vitesse de communication en initialisant TWBR et le prescaler dans twi_master_setup(). |
| <code c> | <code c> | ||
| /* | /* | ||
| Ligne 155: | Ligne 178: | ||
| */ | */ | ||
| - | /* ATMEGA48 @20MHz | + | volatile uint8_t slave_address; |
| - | * 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> | + | volatile uint8_t twi_flag_read_complete = 1; |
| + | volatile uint8_t twi_flag_write_complete = 1; | ||
| - | //sets bitrate and prescaler | + | volatile uint8_t *twi_receive_buffer; |
| - | void twiMasterInitialise(unsigned char bitRate, unsigned char prescaler) | + | volatile uint8_t *twi_transmit_buffer; |
| + | volatile uint8_t twi_i = 0; | ||
| + | |||
| + | uint8_t twi_mode; | ||
| + | uint8_t twi_nb_data_to_transmit, twi_nb_data_to_receive; | ||
| + | |||
| + | ISR(TWI_vect) | ||
| { | { | ||
| - | PRR = (0 << PRTWI); // the PRTWI bit in PRR must be written to zero to enable the TWI | + | uint8_t status; |
| - | TWSR = prescaler & 0x03; | + | |
| - | TWBR = bitRate; | + | status = TWSR & 0xF8; |
| + | switch (status) | ||
| + | { | ||
| + | case (TW_START): /* 0x08 : start condition transmitted */ | ||
| + | case (TW_REP_START): /* 0x10 : repeated START condition transmitted */ | ||
| + | twi_address(); | ||
| + | twi_i = 0; | ||
| + | break; | ||
| + | case (TW_MT_ARB_LOST): /* 0x38 : arbitration lost in SLA+RW, SLA+R received, ACK returned */ | ||
| + | break; | ||
| + | |||
| + | /* Master Transmitter */ | ||
| + | case (TW_MT_SLA_ACK): /* 0x18 : SLA+W transmitted; ACK received */ | ||
| + | case (TW_MT_SLA_NACK): /* 0x20 : SLA+W transmitted; NACK received */ | ||
| + | TWDR = twi_transmit_buffer[0]; | ||
| + | TWCR = (1 << TWEA) | (1 << TWEN) | (1 << TWIE) | (1 << TWINT); | ||
| + | twi_i++; | ||
| + | break; | ||
| + | |||
| + | case (TW_MT_DATA_ACK):/* 0x28 : data has been transmitted; ACK has been received */ | ||
| + | case (TW_MT_DATA_NACK): /* 0x30 : data has been transmitted; NACK has been received */ | ||
| + | if (twi_i == twi_nb_data_to_transmit) | ||
| + | { | ||
| + | if (twi_mode == WRITE) | ||
| + | { | ||
| + | twi_stop(); | ||
| + | twi_flag_write_complete = 1; | ||
| + | } | ||
| + | else // READ | ||
| + | { | ||
| + | slave_address++; | ||
| + | twi_start(); | ||
| + | } | ||
| + | } | ||
| + | else | ||
| + | { | ||
| + | twi_data(twi_transmit_buffer[twi_i]); | ||
| + | twi_i++; | ||
| + | } | ||
| + | break; | ||
| + | |||
| + | /* Master Receiver */ | ||
| + | case (TW_MR_SLA_ACK):/* 0x40 : SLA+R has been transmitted; ACK has been received */ | ||
| + | |||
| + | case (TW_MR_SLA_NACK): /* 0x48 : SLA+R has been transmitted; NACK has been received */ | ||
| + | if (twi_nb_data_to_receive == 1) | ||
| + | { | ||
| + | TWCR &= ~(1 << TWEA); /* desactiver ACK pour la derniere demande */ | ||
| + | } | ||
| + | break; | ||
| + | case (TW_MR_DATA_ACK):/* 0x50 : data received, ACK transmitted */ | ||
| + | case (TW_MR_DATA_NACK): /* 0x58 : data received, NACK transmitted */ | ||
| + | twi_receive_buffer[twi_i] = TWDR; | ||
| + | twi_i++; | ||
| + | |||
| + | if (twi_i == (twi_nb_data_to_receive - 1)) | ||
| + | { | ||
| + | TWCR &= ~(1 << TWEA); /* desactiver ACK pour la derniere demande */ | ||
| + | } | ||
| + | if (twi_i == twi_nb_data_to_receive) | ||
| + | { | ||
| + | twi_flag_read_complete = 1; | ||
| + | twi_stop(); | ||
| + | } | ||
| + | break; | ||
| + | |||
| + | default: | ||
| + | break; | ||
| + | } | ||
| + | |||
| + | TWCR |= (1 << TWINT); // TWINT flag bit is cleared | ||
| } | } | ||
| - | void twiError(void) | + | /* |
| + | * twi master setup | ||
| + | * SCLfreq = CPUfreq / (16 + 2 * TWBR * presc) | ||
| + | * */ | ||
| + | void | ||
| + | twi_master_setup(void) | ||
| { | { | ||
| + | PORTC = (1 << PC5) | (1 << PC4); // activate internal pull_ups for twi | ||
| + | TWSR = 0x00; // no prescaler | ||
| + | TWBR = 72; // 100kHz @16Mhz | ||
| + | //TWBR = 0x0C; // 400 KHz @16MHz | ||
| + | TWCR = (1 << TWEA) | (1 << TWEN) | (1 << TWIE) | (1 << TWINT); | ||
| + | SREG |= (1 << SREG_I); | ||
| } | } | ||
| - | void twiWait(unsigned char myStatus) | + | void |
| + | TWI_wait(void) | ||
| { | { | ||
| - | while (!(TWCR & (1 << TWINT))) | + | while (!(TWCR & (1 << TWINT))) |
| - | ; | + | ; |
| - | if ((TWSR & 0xF8) != myStatus) | + | |
| - | { | + | |
| - | twiError(); | + | |
| - | } | + | |
| } | } | ||
| - | /* send START condition bit */ | + | /* transmit START condition */ |
| - | void twiStart(void) | + | void |
| + | twi_start(void) | ||
| { | { | ||
| - | /* TWINT : TWI interrupt flag | + | TWCR = (1 << TWEA) | (1 << TWEN) | (1 << TWIE) | (1 << TWINT) | (1 << TWSTA); /* send start condition */ |
| - | * 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 */ | + | /* transmit slave address SLA */ |
| - | void twiAddress(unsigned char myAddress) | + | void |
| + | twi_address(void) | ||
| { | { | ||
| - | TWDR = myAddress; | + | TWDR = slave_address; /* load SLA into TWDR */ |
| - | TWCR = (1 << TWINT) | (0 << TWSTA) | (0 << TWSTO) | (1 << TWEN); | + | |
| - | twiWait(TW_MT_SLA_ACK); // 0x18, 0x20 or 0x38 | + | TWCR &= ~(1 << TWSTA); /* desactivate START */ |
| } | } | ||
| - | /* send data */ | + | /* transmit data */ |
| - | void twiData(unsigned char myData) | + | void |
| + | twi_data(uint8_t data) | ||
| { | { | ||
| - | TWDR = myData; | + | TWDR = data; |
| - | TWCR = (1 << TWINT) | (0 << TWSTA) | (0 << TWSTO) | (1 << TWEN); | + | |
| - | twiWait(TW_MT_DATA_ACK); | + | |
| } | } | ||
| - | /* send STOP condition bit */ | + | /* transmit STOP condition */ |
| - | void twiStop(void) | + | void |
| + | twi_stop(void) | ||
| { | { | ||
| - | TWCR = (1 << TWINT) | (0 << TWSTA) | (1 << TWSTO) | (1 << TWEN); | + | TWCR |= (1 << TWSTO); /* STOP */ |
| } | } | ||
| - | /* write data to slaveAddress */ | + | void |
| - | void twiWriteData(unsigned char slaveAddress, unsigned char data) | + | twi_write_bytes(uint8_t add, uint8_t nb_bytes, volatile uint8_t *buffer) |
| { | { | ||
| - | twiStart(); | + | if (twi_flag_write_complete == 1) |
| - | twiAddress(slaveAddress); | + | { |
| - | twiData(data); | + | twi_flag_write_complete = 0; |
| - | twiStop(); | + | slave_address = add << 1; |
| + | twi_transmit_buffer = buffer; | ||
| + | twi_start(); | ||
| + | } | ||
| } | } | ||
| + | void | ||
| + | twi_read_bytes(uint8_t add, volatile uint8_t *reg, uint8_t nb_bytes, | ||
| + | volatile uint8_t *buffer) | ||
| + | { | ||
| + | if (twi_flag_read_complete == 1) | ||
| + | { | ||
| + | twi_flag_read_complete = 0; | ||
| + | twi_flag_write_complete = 0; | ||
| - | int main(void) | + | slave_address = add; |
| + | |||
| + | twi_transmit_buffer = reg; | ||
| + | |||
| + | twi_mode = READ; | ||
| + | twi_nb_data_to_transmit = 1; | ||
| + | twi_nb_data_to_receive = nb_bytes; | ||
| + | |||
| + | twi_receive_buffer = buffer; | ||
| + | |||
| + | twi_start(); | ||
| + | while (twi_flag_read_complete == 0) | ||
| + | ; | ||
| + | } | ||
| + | } | ||
| + | |||
| + | void | ||
| + | setup(void) | ||
| { | { | ||
| - | twiMasterInitialise(92, 0); //set TWBR = 92 for 100kHz SCL @ 20MHz | + | twi_master_setup(); |
| + | } | ||
| - | while (1) | + | int |
| - | { | + | main(void) |
| - | twiWriteData(0x20, 0x05); //write 0x05 @0x20 | + | { |
| - | } | + | uint8_t * buf; |
| - | return 1; | + | setup(); |
| + | while (1) | ||
| + | { | ||
| + | twi_read_bytes(0x68, 0x42, 1, buf); | ||
| + | } | ||
| } | } | ||
| </code> | </code> | ||