Forum: Mikrocontroller und Digitale Elektronik XMEGA TWI timing Problem


von Johannes R. (johannes_r96)


Lesenswert?

Hallo,

ich habe mit dem XPLAIN Board(XMEGA128A1) einen i²C  CO2 Sensor 
angesprochen. Funktioniert alles soweit ganz gut, jedoch habe ich das 
Problem, dass nach ein paar korrekten Messwerten entweder eine 0 oder 
eine 10794 übertragen wird, mir schein es fast so, als würde ein Puffer 
überlaufen/leerlaufen......

Da ich recht neu in der uC Welt bin, ist mein Code auch entsprechend 
einfach geschrieben.....in der main.c habe ich die Funktionen mit einem 
Delay versehen, um dem Sensor zeit zum Verarbeiten zu eben, da liegt 
wahrsch das Problem...jetzt suche eine Funktion, mit der mein uC 
erkennt, dass der Controller bereit für das nächste "Gespräch" ist, 
normalerweise ist das ja nach dem Slave ACK der Fall.....vllt kann mir 
ja der eine oder andere helfen.

Hier meine main.c:

int main(void)
{



  PORTC.PIN0CTRL = 0x18;  //Pull Up SDA
  PORTC.PIN1CTRL = 0x18;  //Pull Up CLK
  int i=0;
  int Status = 0;

  int temperature=0;
  unsigned int humi=0;
  char status = 0;
  char lowbyte = 0;
  char highbyte = 0;
  char check = 0;
  int co2_raw = 0;

  TWI_MasterInit(&TWIC);

  //UART initialisieren

  USARTC0.BAUDCTRLB = 0;
  USARTC0.BAUDCTRLA = 0x0C;

  USARTC0.CTRLA = USART_RXCINTLVL_HI_gc;

  USARTC0.CTRLB = USART_TXEN_bm | USART_RXEN_bm;

  USARTC0.CTRLC = USART_CHSIZE_8BIT_gc;

  PORTC.DIR = 0x08;

    while(1)
    {

   // SHT 75 Auslesen!!!
    sht_init();
    sht_start();
    _delay_ms(30);
    sht_write_byte(MEAS_TEMP);
    sht_wait_for_measurement();
    temperature = sht_read_byte(1)<<8;
    temperature |= sht_read_byte(0);
     _delay_ms(5);
     sht_start();
    _delay_ms(30);
    sht_write_byte(MEAS_HUMI);
    sht_wait_for_measurement();
    humi = sht_read_byte(1)<<8;
    humi |= sht_read_byte(0);

    float temp = sht_calc_temp(temperature);
    float feuchte = sht_calc_humi(humi);



    K22_send_byte(&TWIC,K22);
    _delay_ms(20);

     K22_read_Adress(&TWIC,K22);
    _delay_us(500);


    status = K22_read_Data(&TWIC);

    TWIC.MASTER.CTRLC = TWI_MASTER_CMD_RECVTRANS_gc;
    _delay_us(500);


    lowbyte = K22_read_Data(&TWIC);


    TWIC.MASTER.CTRLC = TWI_MASTER_CMD_RECVTRANS_gc;
    _delay_us(500);

    highbyte = K22_read_Data(&TWIC);


    TWIC.MASTER.CTRLC = TWI_MASTER_CMD_RECVTRANS_gc;
    _delay_us(500);

    check = K22_read_Data(&TWIC);
    _delay_us(500);


    TWIC.MASTER.CTRLC = TWI_MASTER_CMD_RECVTRANS_gc;


    co2_raw = lowbyte<<8;
    co2_raw |= highbyte;


    char Buffer[20];
    utoa( temp, Buffer, 10 );


    char Buffer2[20];
    utoa( feuchte, Buffer2, 10 );


    char Buffer3[20];
    utoa( co2_raw, Buffer3, 10 );


    //Daten über UART an BT-Modul senden
     Send_UART("Temp: ");
     Send_UART(Buffer);
      Send_UART("Humi: ");
       Send_UART(Buffer2);
       Send_UART("CO2: ");
       Send_UART(Buffer3);
       if(co2_raw > 2000){
         Send_UART("Achtung! CO2 Konzentration zu hoch!!!");
       }


     _delay_ms(1330);


  }
}


hier die TWI.c:

#include <avr/io.h>
#include "util/delay.h"
#include "TWI.h"



//Funktionen

void TWI_MasterInit(TWI_t *twi){
  twi->MASTER.BAUD = TWI_BAUDRATE;
  twi->MASTER.CTRLA = TWI_MASTER_ENABLE_bm |
  TWI_MASTER_INTLVL_HI_gc |
  TWI_MASTER_RIEN_bm |
  TWI_MASTER_WIEN_bm;
  twi->MASTER.STATUS = TWI_MASTER_BUSSTATE_IDLE_gc;
}

void Send_Address(TWI_t *twi, char Adresse, char RW)
{
  twi->MASTER.ADDR = (Adresse << 1)+RW;
  //twi->MASTER.ADDR = Adresse;
}

void K22_send_byte(TWI_t *twi, char Adresse)
{
  int i = 0;
  Send_Address(twi, Adresse, 0);
  _delay_us(500);
  twi->MASTER.DATA = 0x22;
  _delay_us(500);
  twi->MASTER.DATA = 0x00;
  _delay_us(500);
  twi->MASTER.DATA = 0x08;
  _delay_us(500);
  twi->MASTER.DATA = 0x2A;
  _delay_us(500);
  twi->MASTER.CTRLC = TWI_MASTER_CMD_STOP_gc;


}

char K22_read_Adress(TWI_t *twi, char *Adresse)
{
  Send_Address(twi, Adresse, 1);
  _delay_us(500);
  //twi->MASTER.CTRLC = TWI_MASTER_CMD_STOP_gc;

}

char K22_read_Data(TWI_t *twi)
{

  return twi->MASTER.DATA;
  _delay_us(500);


}

Gruß Johannes

von Thomas F. (tomasf)


Lesenswert?

Schau mal in AVR1308, da ist ein einfach in Betrieb zu nehmenden 
Beispiel für das TWI-Modul, das man leicht an eigene Slaves anpassen 
kann. So wie Du das gemacht hast, geht es nicht.

von Johannes R. (johannes_r96)


Lesenswert?

Das AVR1308 hab ich schon mehrfach durch....da steht zwar alles prima 
erklärt, das hilft mir jedoch nicht wirklich weiter, meinen C-Code zu 
verbessern...wie gesagt der sensor antwortet, nur nach 15-25 Messwerten 
kommt aufeinmal müll raus.....bitte nicht vom C-Code für den SHT75 
Sensor verwirren lassen, das ist kein richtiger i2c da haben wir die 
Kommunikation per Hand durchgeführt laut datenblatt.....funktioniert 
aber auch 1A...

von Thomas F. (tomasf)


Lesenswert?

Dass Dein Code ein bisschen funktioniert, ist sicher nur Zufall, du 
aktivierst z.B. die TWI-Interrupts (CTRLA-Register), hast aber keine 
Handler dafür. Das Atmel-Beispiel zeigt Dir, wie das gemacht werden 
muss.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.