Hallo,
ich brauche Eure Hilfe bei einer Fehleranalyse, hab im Moment keine Ideen mehr.
Folgendes Problem:
Hardware: ATMEGA16, der über software I2C mit 3 Ultraschallsensoren und einem weiteren Sensor-Board kommuniziert. LCD zum Debuggen im 4-bit Datenmodus.
Setup: externer Quartz mit 18,432 MHz (übertaktet), Fehlerbild ist bei Nutzung des internen RC-Oszillators mit 8 MHz aber identisch.
Software: C-Code anbei, nutzt die I2C Lib (mit Software-TWI und Assembler Source) und LCD Lib (4-bit Datenmodus) von Peter Fleury.
Zuerst wird der I2C Bus initialisiert und die Messungen auf den 3 US-Sensoren wird mit einem General-Schreibbefehl (Adresse 0x00) und das weitere Sensorboard mit einem Schreibbefehl an die I2C Adresse 0xD0) gestartet.
Zum Auslesen der 3 US-Sensoren wird eine For-Schleife benutzt. Je nachdem, an welcher Stelle der Aufruf i2c_stop() plaziert wird innerhalb der Schleife, ergeben sich unterschiedliche Fehlerbilder.
Fall1: i2c_stop(); im Code direkt nach dem Lesen des US-Sensors plaziert. Die 3 Senoren (I2C-Adresse E0, E2 und E4) werden richtig gelesen. Aber danach wird die For-Schleife nicht wie beabsichtigt beendet, sondern es wird versucht, weiter endlos die jeweils um 2 inkrementierten Addressen zu lesen. Die FOR-Schleife wird endlos ausgeführt.
Code:
// select display
lcd_select(0);
// move cursor to position on line 0
lcd_gotoxy(10,0);
for ( i = 0 ; i < 3 ; i++ )
{
// check if ultrasonic sensor is busy
busy_US = i2c_start(US_left + (2*i) + I2C_READ);
// address I2C device ultrasonic sensor with read access
if (busy_US == 0)
{
[i] distance = i2c_readNak(); // read one byte
i2c_stop(); // release I2C bus
[i] utoa(distance, buffer, 10);
// put string to display (line 0)
lcd_puts(buffer);
lcd_puts(" ");
if (i==2)
{
i2c_start(US_general + I2C_WRITE);
// address I2C device ultrasonic sensor with write access
i2c_write(Start_US); //start new ultrasonic measurement
i2c_stop(); // release I2C bus
}
}
else
{
i2c_stop(); // release I2C bus
}
}
Fall2: i2c_stop(); im Code erst nach der LCD Ausgabe weiter hinten plaziert. Nur noch der erste Sensor wird korrekt gelesen. Dann folgt zweimal ein i2c-Schreibbefehl an die I2C Adresse 0x02. Die Schleife wird sodann beendet und das andere Sensorboard wird korrekt ausgelesen (i2c Adresse 0xD0).
Code:
// select display
lcd_select(0);
// move cursor to position on line 0
lcd_gotoxy(10,0);
for ( i = 0 ; i < 3 ; i++ )
{
// check if ultrasonic sensor is busy
[i] busy_US = i2c_start(US_left + (2*i) + I2C_READ);
// address I2C device ultrasonic sensor with read access
[i] if (busy_US == 0)
{
[i] distance = i2c_readNak(); // read one byte
[i] utoa(distance, buffer, 10);
// put string to display (line 0)
lcd_puts(buffer);
lcd_puts(" ");
i2c_stop(); // release I2C bus
if (i==2)
{
i2c_start(US_general + I2C_WRITE);
// address I2C device ultrasonic sensor with write access
i2c_write(Start_US); //start new ultrasonic measurement
i2c_stop(); // release I2C bus
}
}
else
{
i2c_stop(); // release I2C bus
}
}
Fall3: zusätzlich noch 2 (leicht modifizierte) Zeilen zum LCD select und Positionieren des Cursors in die Schleife gezogen vor den Aufruf i2c_stop(); Die I2C Kommunikation läuft korrekt ab. Nur die LCD Ausgabe ist fehlerhaft.
Code:
for ( i = 0 ; i < 3 ; i++ )
{
// check if ultrasonic sensor is busy
[i] busy_US = i2c_start(US_left + (2*i) + I2C_READ);
// address I2C device ultrasonic sensor with read access
[i] if (busy_US == 0)
{
[i] distance = i2c_readNak(); // read one byte
[i] utoa(distance, buffer, 10);
// select display
lcd_select(0);
// move cursor to position on line 0
lcd_gotoxy(10+(4*i),0);
// put string to display (line 0)
lcd_puts(buffer);
lcd_puts(" ");
[i][i] i2c_stop(); // release I2C bus
if (i==2)
{
i2c_start(US_general + I2C_WRITE);
// address I2C device ultrasonic sensor with write access
i2c_write(Start_US); //start new ultrasonic measurement
i2c_stop(); // release I2C bus
}
}
else
{
i2c_stop(); // release I2C bus
}
}
Die betreffenden Ausschnitte der I2C Kommunikation, wie ich sie mit einem Logic Analyser aufgezeichnet habe, seht ihr in den 3 anhängenden Bildern:
i2c_fall1.png
i2c_fall2.png
i2c_fall3.png
Der Code ist auch angehängt.
Folgende Fehlermöglichkeiten habe in bisher in Betracht gezogen:
- Übertaktung (18,432 MHz), kann ich aber ausschließen, da das Fehlerbild mit 8 MHz identisch ist.
- Alterung des Flash, Code wird fehlerhaft gelesen. Unwahrscheinlich, da ich den Chip nun seit 5 Jahren betreibe, aber sicher nur an 30 Tagen im Jahr mit ca. 10 Löschvorgängen pro Tag (macht 1500 Programmierzyklen).
- Compiler-Fehler, dafür hab ich auch die Listings angehängt, evtl mal draufschauen.
Bitte helft mir mit Ideen.
Danke, uffi.
Lesezeichen