Outils pour utilisateurs

Outils du site


robotics:computing:communication_twi_entre_atmega

Différences

Cette page vous affiche les différences entre la révision choisie et la version actuelle de la page.

Lien vers cette vue comparative

robotics:computing:communication_twi_entre_atmega [2010/03/16 18:33]
gdo
robotics:computing:communication_twi_entre_atmega [2013/09/27 15:56] (Version actuelle)
ldo [Master]
Ligne 25: Ligne 25:
 ====== Implémentation ====== ====== Implémentation ======
 ===== Registres TWI ===== ===== Registres TWI =====
-TWCR contient tous les bits de controle de la communication :+== TWCR registre de controle== 
 +Il contient tous les bits de controle de la communication :
   * TWINT : c'est le flag d'​interruption   * TWINT : c'est le flag d'​interruption
   * TWEA : ce bit permet d'​activer l'​envoie des bits d'​acquittement.   * TWEA : ce bit permet d'​activer l'​envoie des bits d'​acquittement.
Ligne 33: Ligne 34:
   * TWEN : Ce bit permet d'​activer la communication TWI   * TWEN : Ce bit permet d'​activer la communication TWI
   * TWIE : Ce bit permet d'​activer les interruptions TWI.   * TWIE : Ce bit permet d'​activer les interruptions TWI.
-TWAR contient l'​adresse esclave+==TWAR registre d'​adresse == 
 +Il contient l'​adresse esclave
   * TWA6-TWA0 : Ces bits contiennent l'​adresse esclave.   * TWA6-TWA0 : Ces bits contiennent l'​adresse esclave.
   * TWGCE : Ce bit indique si l'​esclave répond ou ignore la requête générale émise par un maitre.   * TWGCE : Ce bit indique si l'​esclave répond ou ignore la requête générale émise par un maitre.
-TWDR contient l'​octet reçu ou envoyé.  +==TWDR registre de données == 
-TWSR est le registre de status+Il contient l'​octet reçu ou envoyé. 
 +==TWSR registre de status==
   * TWS7-TWS3 : contient le code qui détermine l'​état dans lequel se trouve la communication (adresse reçue ou donnée envoyée).   * TWS7-TWS3 : contient le code qui détermine l'​état dans lequel se trouve la communication (adresse reçue ou donnée envoyée).
   * TWPS1-TWPS0 : contient le prescaler qui détermine la fréquence d'​horloge SCL.   * TWPS1-TWPS0 : contient le prescaler qui détermine la fréquence d'​horloge SCL.
-TWBR est le registre qui contient la valeur de la fréquence d'​horloge SCL. +==TWBR == 
-FSCL FCPU/​(16+(2*TWBR*Prescaler))+C'est le registre qui contient la valeur de la fréquence d'​horloge SCL. 
 +SCLfreq ​CPUfreq/​(16+(2*TWBR*Prescaler)) 
 + 
 +Exemple : On travaille avec un ATMEGA cadencé à 16MHz et on souhaite une vitesse de 100Kz. 
 +TWBR*Prescaler = (CPUfreq - 16 * SCLfreq)/​(2*SCLfreq) = (16MHz - 16 * 100KHz) / (2 * 100 KHz) = 72 
 +Si on prend un prescaler de 1, on a TWBR = 72.
 ===== Slave ===== ===== Slave =====
 L'​implémentation de la communication twi sur l'​esclave va utiliser les interruptions. A chaque fois que l'​esclave va recevoir un octet, la routine d'​interruption va être appelée. Dans cette routine, nous allons tester le registre TWSR qui va nous renseigner sur le type d'​information qu'il vient de recevoir et pouvoir la traiter correctement. L'​implémentation de la communication twi sur l'​esclave va utiliser les interruptions. A chaque fois que l'​esclave va recevoir un octet, la routine d'​interruption va être appelée. Dans cette routine, nous allons tester le registre TWSR qui va nous renseigner sur le type d'​information qu'il vient de recevoir et pouvoir la traiter correctement.
  
-<​code>​+<​code ​c>
 /* /*
- ​* ​twislave.c+ ​* ​twi_slave.c
  *  *
  ​* ​ Created on: 26 févr. 2010  ​* ​ Created on: 26 févr. 2010
Ligne 53: 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 = (<< ​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) | (<< ​TWEN) | (<< ​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) | (<< ​TWSTA) | (<< ​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); 
 +}
  
- while (1) +int 
-+main(void) 
-+
- return ​1;+  setup(); 
 + 
 +  ​while (1) 
 +    
 +      if (rb[0]==0x41) 
 +      { 
 +        tb[0] = 0x47; 
 +        tb[1] = 0x49; 
 +      ​
 +      ​else 
 +      { 
 +        tb[0] = 0x27; 
 +        tb[1] = 0x29; 
 +      } 
 +   }
 } }
 </​code>​ </​code>​
  
 ===== Master ===== ===== Master =====
-Ce code permet d'​envoyer une donnée à un esclave +Ce code permet d'​envoyer une donnée à un esclave
-<​code>​+ 
 +Dans un premier temps, on va définir la vitesse de communication en initialisant TWBR et le prescaler dans twi_master_setup(). 
 +<​code ​c>
 /* /*
  * twiMaster.c  * twiMaster.c
Ligne 145: 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 bitRateunsigned char prescaler)+volatile uint8_t *twi_transmit_buffer;​ 
 +volatile uint8_t twi_i = 0; 
 + 
 +uint8_t twi_mode; 
 +uint8_t twi_nb_data_to_transmittwi_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) | (<< ​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) | (<< ​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 slaveAddressunsigned char data)+twi_write_bytes(uint8_t adduint8_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(0x200x05); //write 0x05 @0x20 +
- } +  uint8_t * buf; 
- return 1;+  setup(); 
 +  ​while (1) 
 +    
 +      ​twi_read_bytes(0x680x42, 1, buf); 
 +    }
 } }
 </​code>​ </​code>​
robotics/computing/communication_twi_entre_atmega.1268760821.txt.gz · Dernière modification: 2012/09/20 10:52 (modification externe)