www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik I²C problem - Hilflos


Autor: Dondolo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hey ho,
ich wollte endlich mal den i2c bus ausprobieren (aus reinen 
textzwecken).

Situation:
ich habe 2 atmega8, die ich richtig miteinander verbunden habe. im 
internet fand ich eine fertige i²c library, die auch fast funktioniert. 
Die funktionen habe ich bereits durchgeschaut und keine fehler gefunden, 
warum diese nicht ordnungsgemäß funktioniert, aber x*2 augen sehen mehr 
als 2 ;).

die i²c lib:
/* *************************************
   TWI Lib Version 5 oder so
   bhm 2006
  ************************************** */

// bislang keinmultimaster support
// keine Garanie für irgendwas
// Bemerkungen, Fehlerreports usw willkommen


#ifndef _TWILIB_
#define _TWILIB_ 1
                                  //Zugriff auf IO's des Controllers
#include <stdint.h>
#include <compat/twi.h>

void init_Master (void) {
   TWSR &= ~(_BV(TWPS0) | _BV(TWPS1));    //0b11111100: Prescaler auf 1 setzen, Bit 1 und 0 auf 0
   TWBR = 0x0A;                        //Bitrate auf 10 setzen, gibt 220kHz Bustakt bei 8MHz
}

void init_Slave (uint8_t SlvAdd) {
   TWAR = SlvAdd;                         // eigene Address, hier ohne general call
   TWCR = _BV(TWEA) | _BV(TWEN) | _BV(TWINT);   //slave receive, TWEA > ACK,
}


void waitTWINT (void) {
   uint32_t m=0,mmax=8000000; //zZt einfach eine große Zahl

   while (bit_is_clear(TWCR, TWINT)) {
      if (m++ > mmax) return;         // bricht waitTWINT ab, TW_Status enthält dann TW_NO_INFO
   }
}

// *********** MasterTransmitter *************
// Daten in *Data, lenmax #Daten senden, MT #gesendete Daten
uint8_t MT (uint8_t SlvAdd, uint8_t *Data, uint8_t lenmax) {
   uint8_t len=1;
    
   TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN);   //sende start
   waitTWINT();
   if ((TW_STATUS != TW_START) &&   (TW_STATUS != TW_REP_START)){   // chk Start | repeated start
      goto ENDE;
   }

   TWDR = SlvAdd + TW_WRITE;               //Addresse des Slaves angeben, SLA+W
   TWCR = _BV(TWINT) | _BV(TWEN);               // sende sla_w
   waitTWINT();
   if (TW_STATUS != TW_MT_SLA_ACK) {            // chk sla_ack
      goto STOP;
   }

   do {
      TWDR = *Data++;                // Datum laden
      TWCR = _BV(TWINT) | _BV(TWEN);            // sende Datum
      waitTWINT();
      if (TW_STATUS != TW_MT_DATA_ACK) {         // chk data_ack
         goto STOP;
      }
   } while (len++<lenmax);

STOP:
   TWCR = _BV(TWINT) | _BV(TWEN) | _BV(TWSTO);   // sende stop, kein warten auf TWINT

ENDE:
   return len-1;
}

// *********** MasterReceiver *************
// empfangene Daten nach *Data, Speicher muss bereitgestellt sein,
// lenmax #Daten empfangen, MR #empfangene Daten
uint8_t MR (uint8_t SlvAdd, uint8_t *Data, uint8_t lenmax) {
   uint8_t len=1;

   TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN);   //sende start
   waitTWINT();
   if ((TW_STATUS != TW_START) &&   (TW_STATUS != TW_REP_START)){   // chk Start | repeated start
      goto ENDE;
   }

   TWDR = SlvAdd + TW_READ;                  //Addresse des Slaves angeben, SLA+r
   TWCR = _BV(TWINT) | _BV(TWEN);               // sende sla_r
   waitTWINT();
   if (TW_STATUS != TW_MR_SLA_ACK) {            // chk sla_ack
      goto STOP;
   }

   while (1) {          // endlos, verlassen via break in if TW_Status
      if (len<lenmax) {
         TWCR = _BV(TWEA) | _BV(TWEN) | _BV(TWINT);      //receive, ACK,
      } else {
         TWCR =             _BV(TWEN) | _BV(TWINT);      //receive, NACK,
      }
      waitTWINT();
      if (TW_STATUS != TW_MR_DATA_ACK) break;         // LOOP VERLASSEN
      *Data++ = TWDR; len++;                     // Daten verarbeitet
   }

   if (TW_STATUS == TW_MR_DATA_NACK) {
      *Data++ = TWDR; len++;                     // Daten verarbeitet
      goto STOP;
   }

STOP:
   TWCR = _BV(TWINT) | _BV(TWEN) | _BV(TWSTO);   // sende stop, kein warten auf TWINT
ENDE:
   return len-1;
}


// *********** SlaveReceiver *************
// empfangene Daten nach *Data, Speicher muss bereitgestellt sein,
// lenmax #Daten empfangen, SR #empfangene Daten
uint8_t SR (uint8_t *Data, uint8_t lenmax) {
   uint8_t len=1;                  // lenmax >= 1, min ein Byte empfangen!

// auf SLA warten
   while (bit_is_clear(TWCR, TWINT));             // beliebig lange warten oder pollen

// jetzt geht's los
   if (TW_STATUS != TW_SR_SLA_ACK) {            // chk SLA+W
      goto STOP;
   }

   while (1) {          // endlos, verlassen via break in if TW_Status
      if (len<lenmax) {
         TWCR = _BV(TWEA) | _BV(TWEN) | _BV(TWINT);      //slave receive, TWEA > ACK,
      } else {
         TWCR =             _BV(TWEN) | _BV(TWINT);      //slave receive, TWEA > NACK,
      }
      waitTWINT();
      if (TW_STATUS != TW_SR_DATA_ACK) break;         // LOOP VERLASSEN
      *Data++ = TWDR; len++;                     // Daten verarbeitet
   }

   if (TW_STATUS == TW_SR_DATA_NACK) {               // Datum mit NACK beantwortet
      *Data = TWDR; len++;                     // im Prinzip noch ein Datum verfügbar
   }

STOP:   // (TW_STATUS == TW_SR_STOP)  einzig anderer möglicher Status, von ARBs abgesehen
   TWCR = _BV(TWEA) | _BV(TWEN) | _BV(TWINT);   //slave receive, TWEA > ACK,
   return len-1;
}

// *********** SlaveTransmitter *************
// Daten in *Data, lenmax #Daten senden, ST #gesendete Daten
uint8_t ST (uint8_t *Data, uint8_t lenmax) {
   uint8_t len=0;                  // lenmax >= 1, min ein Byte senden!

// auf SLA warten
   while (bit_is_clear(TWCR, TWINT));             // beliebig lange warten oder pollen

// jetzt geht's los
   if (TW_STATUS != TW_ST_SLA_ACK) {            // chk SLA+R
      goto STOP;
   }

   do {
      TWDR = *Data++; len++;
      if (len<lenmax) {
         TWCR = _BV(TWEA) | _BV(TWEN) | _BV(TWINT);
      } else {
         TWCR = _BV(TWEN) | _BV(TWINT);
      }
      waitTWINT();
   } while (TW_STATUS == TW_ST_DATA_ACK);

STOP:
   TWCR = _BV(TWEA) | _BV(TWEN) | _BV(TWINT);   //slave receive, TWEA > ACK,
   return len;
}

#endif


der quelltext vom master:
init_master();
MT(0b11010010, &tosend, 1); 

    MR(0b11010010,cache, 1);
    send(cache[0]); ///send funktion für rs232


der quelltext des slaves:
init_Slave(0b11010010);
SR(&cache,1);
if (cache == 0){ 
cache = 0b10101010;
ST(&cache,1);
}

es müsste also am pc über rs232 immer 170 ankommen,es kommt aber nur in 
ca 70 % der fälle an, die anderen werte sind willkürlcih von 0-255. und 
so hoch kann ja die übertragungsfehlerquote nicht sein oder? die beiden 
atmega werden mit 4 mhz betrieben.

kann mir jemand helfen ich weiß nicht weiter.
Warum werden so viele falsche bytes übertragen?

Autor: Der Einäugige (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> aber x*2 augen

das ist eine Annahme .-)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.