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/09/27 15:49] ldo [Slave] |
robotics:computing:communication_twi_entre_atmega [2013/09/27 15:56] (Version actuelle) ldo [Master] |
||
---|---|---|---|
Ligne 169: | 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 178: | 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> |