Moin Leute,
ich habe folgendes Problem. Derzeit habe ich zwei RN-Control Boards
basierend auf ATMega32. Für das eine Board habe ich eine I2C-Master
Software geschrieben, für das zweite die I2C-Slave Software.
Lasse ich beides laufen funktioniert es problemlos. Der Master schiebt
zwei Bytes zum Slave und der führt dann etwas aus. Soweit so gut.
Eigetnlich soll aber ein ATMega8 als Slave verwendet werden. Hier habe
ich ein Prototyp-Board gebaut. Das funktioniert auch soweit. Wenn ich
jetzt die I2C-Slave-Software installiere funktioniert das Ganze nicht
mehr.
Entweder der Master kann sich nicht mit dem Slave syncen (erst nach zig
mal Reset - bekommt Fehler das Slaveadresse mit NACK beantwortet wird)
oder er sendet zwei Bytes und bleibt dann hängen. Der Slave funzt
ebenfalls nicht, er kriegt irgendwie nicht das Stop-Signal vom Master.
Es sieht für mich so aus, als ob der Slave NACK sendet.
Wie gesagt mit den RN-Boards (gleiche Software) funktioniert es
einwandfrei. Nur nicht mit meinem ATMega8-Board.
Abschlußwiderstände sind auf dem RN-Board, das RN-Board und das ATMega8
board haben auch die gleiche Masse.
Ich bin ratlos - hat jemand eine Idee - was ich noch untersuchen kann?
Danke
Bernd
Hmm, in den Atmega32 RN-Boards und in dem Atmega8 Board (Eigenbau) kann
doch nicht die gleiche Software drin sein.
Die Atmega8 Software muss mindestens neu übersetzt sein, wahrscheinlich
sind auch Konstanten auf den anderen µC angepasst. Hier wäre
nachzuforschen, ob die Änderungen OK sind und ob sie zum Eigenbauboard
passen, d.h. man bräuchte einen Quellcode.
Und der Schaltplan des Eigenbauboards wäre bei der Fehlersuche auch
nützlich. Die Schaltpläne der RN-Boards kann sich der Hilfegeber zur Not
aus dem Netz suchen, in der Hoffnung die gleiche Revision wie dein
RN-Board zu finden.
Hat man beide Schaltpläne braucht man zum Schluß auch noch Infos, wie
die beiden Boards jeweils miteinander verbunden sind.
Wenn man im Quellcode oder im Schaltplan entdeckt, dass das Atmega8
Board mit externer Taktquelle laufen soll, wäre darüberhinaus auch
hilfreich zu wissen, wie die AVR Fuses programmiert sind.
Klar die Software ist natürlich für den ATMega8 kompiliert, die
notwendigen Anpassungen sind auch drin.
Als Anhang schon mal den Schaltplan - nun muss ich aber sagen, der erste
Prototyp ist OHNE den 4051 - Mir kam es im ersten Step lediglich auf die
Servos an.
Dann hab ich mal die Hauptdateien angehängt (ok nicht komplett das
Projekt aber hoffentlich ausreichend für eine Analyse).
Mit den Fuses hast Du mich stutzig gemacht, was könnte denn da nicht
korrekt sein?
Schaun wir mal ob Ihr mir helfen könnte.
Gruß
Bernd
Auf die Schnelle...
Bufferoverflow
#define I2C_RECEIVE_DATA_BUFFER_SIZE 0x10
uint8_t localbuffer[] = "1234567890";
for (int x = 0; x < I2C_RECEIVE_DATA_BUFFER_SIZE; x++) {
localbuffer[x] = 0;
Abhilfe:
uint8_t localbuffer[I2C_RECEIVE_DATA_BUFFER_SIZE];
Beim Beschreiben des
I2cReceiveData[I2cReceiveDataIndex++] = TWDR;
I2cReceiveDataLength++;
sollte man auch prüfen, ob Bufferoverflow auftritt. Wo setzt du
I2cReceiveDataLength auf 0 zurück, brauchst du die Variable überhaupt?
cli und sei und TWCR in ISR
Würde ich nicht machen. Du beschwörst Probleme mit Interrupts im
Interrupt herauf.
Fuses
Nicht primär relevant, du arbeitest mit internem Takt. Wie schnell läuft
dein I2C Bus in etwa? Nicht dass da ein 16 MHz Atmega32 einen 1 MHz
Atmega8 füttert.
Schaltplan
AREF an AVcc, d.h. externen +5V , würde ich nicht machen. Grund wird
öfters im Forum diskutiert.
Ist das das RN-Board:
http://www.shop.robotikhardware.de/shop/catalog/product_info.php?products_id=10
Konnte mich erst heute wieder melden - bin viel unterwegs und schaffe es
dann häufig nicht eher.
Schaltplan:
Yeap, ich nutze das RN-Control V. 1.4.1
CLI/SEI im ISR
hab ich mal ausgebaut, brachte aber leider auch keine Änderung
Bufferoverflow:
Das hätte in der Tat zu einem Bufferoverflow führen können. Die Variable
wird jetzt resetet wenn der Slave angesprochen wird.
1
ISR(TWI_vect)
2
{
3
staticbytei2c_state;
4
bytetwi_status;
5
//cli();
6
// Disable Global Interrupt
7
//uart_puts("ISR ");
8
// Get TWI Status Register, mask the prescaler bits (TWPS1,TWPS0)
9
twi_status=TWSR&0xF8;
10
11
switch(twi_status){
12
caseTW_SR_SLA_ACK:// 0x60: SLA+W received, ACK returned
13
i2c_state=0;// Start I2C State for Register Address required
Nach wie vor passiert folgendes:
Der Master sendet die Adresse des Slaves. Slave zeigt auf UART "-1" (ok)
Master sendet 1. Byte - Slave zeigt auf UART "-2" (ok)
Master sendet 2. Byte - Slave zeigt auf UART "-2" (ok)
Master sollte STOP sende - Beim Slave passiert irgend wie nix - alles
steht.
INFO1:
Der ATMega8 läuft mit internen 8Mhz Takt
INFO2:
Sobald ich den Code für das RN-Control kompiliere und drauf spiele -
funktioniert es einwandfrei
?????? - sehr eigenartig -
Kann es daran liegen, dass ich beim ATMega8 eine interne Taktquelle
(8Mhz) verwende?
Gruß
Bernd
> CLI/SEI im ISR> hab ich mal ausgebaut, brachte aber leider auch keine Änderung
Offen ist noch: Warum löschst du manuell das TWINT Flag?
Wenn der Slave länger braucht als der Master und sich ein TWI Interrupt
aufstaut, wird dieser dadurch weggeworfen!
Und du hast auf deinem 8 MHz Slave an deinem 16 MHz Master Probleme,
dass ein Interrupt mit der STOP Bedingung nicht kommt... richtig?
> Die Variable> wird jetzt resetet wenn der Slave angesprochen wird.
Offen ist noch: Wie groß ist localbuffer?
> Offen ist noch: Warum löschst du manuell das TWINT Flag?
Tja, das hab ich in allen Beispielen so gelesen - ohne nachzudenken
übernommen ;-)
In einem anderen Beispiel für einen Slave habe ich folgendes gelesen und
auch mal ausprobiert
Hilft aber auch nix :-(
>Und du hast auf deinem 8 MHz Slave an deinem 16 MHz Master Probleme,>dass ein Interrupt mit der STOP Bedingung nicht kommt... richtig?
Yeap, so sieht es aus
>Offen ist noch: Wie groß ist localbuffer?
10Bytes
> Tja, das hab ich in allen Beispielen so gelesen - ohne nachzudenken> übernommen ;-)
Dann teile die Beispiele in diejenigen auf die
TWI per Software-Polling ohne TWI-Interrupt machen. Von denen solltest
du nicht abschauen.
und diejenigen die
TWI per Hardware mit TWI-Interrupt machen. Das sind die für dich
interessanten. Wenn du da eins findest, welches manuell in der ISR TWINT
löscht, bitte verlinken :-)
> Offen ist noch: Wie groß ist localbuffer?> 10Bytes> Also weiterhin zu klein.
?? Warum das denn? Ich übertrage doch nur zwei Bytes und dann fängt der
Buffer beim nächsten START wieder bei 0 an.
>Wenn du da eins findest, welches manuell in der ISR TWINT>löscht, bitte verlinken :-)http://www.rn-wissen.de/index.php/TWI_Slave_mit_avr-gcc#Slave_sourcecode
Bei SLAVE-Sourcecode
Abgesehen davon, erklärt das Ganze aber immer noch nicht, warum es auf
dem RN-Control-Board als SLAVE funktioniert und auf dem ATMega8 nicht
oder?
Nochmals ein Nachtrag.
Ich habe jetzt mal beim MASTER (RN-Control) etwas geändert. Er sendet
jetzt 6 Datenbytes - alles kommt auch beim Slave an - fehlerfrei -
sobald der Master aber jetzt das stop-signal senden möchte ist schluss
mit lustig.
Nicht geht mehr :-(
Ich versteh es einfach nicht.
Gruß
Bernd
Bernd Klein schrieb:> Der ATMega8 läuft mit internen 8Mhz Takt
...
> Kann es daran liegen, dass ich beim ATMega8 eine interne Taktquelle> (8Mhz) verwende?
Irgendwas passt da nicht zusammen.
Der interne Takt eines Mega8 ist 1MHz.
Aber mir ist mittlerweile noch was aufgefallen.
Ich habe am MASTER mal vor dem STOP und NACH dem STOP eine UART-Ausgabe
gemacht - siehe da - ich bekomme beides angezeigt. Soll heißen, STOP
wurde gesendet aber der Slave kann wohl nicht damit umgehen - warum auch
immer.
Naja, vielleicht kriege ich es ja mit einem von Euch noch hin :-)
Bernd Klein schrieb:> ????> die interene kalibrierte Oszillator kann auf 8Mhz gesetzt werden
Mist, da hab ich mich im Datenblatt vertan :(
Du hast natürlich Recht.
Moin,
Ich hatte schon mal ein ähnliches Problem mit einem Tiny45 als I2C
Slave.
Bei mir half am Ende eine andere Version von WinAVR. Ich weiß nicht
mehr, welche Version nicht ging, aber die 20070525 hat funktioniert.
Vielleicht hilft Dir das weiter, Gruß
Mühsam ernährt sich das Eichhörnchen. Ich bin schon wieder einen Schritt
weiter :-)
Habe unter folgendem Link: http://www.schatenseite.de/i2c-ledmatrix.html
Eine ATMega8 Version gefunden - auf mein Prototyp-Board gespielt und
-siehe da es funktioniert.
Mhm, jetzt weiß ich zwar das in meinem Code (Slave) irgendwo der Fehler
steckt, aber leider nicht wo :-(
Ok, die Suche geht weiter...
in i2cSlaveReceiveService sollte dann die eigentliche Bearbeitung meiner
Daten erfolgen.
Aber irgendwas habe ich falsch gemacht - und jetzt bin ich müde und kann
micht auch nicht mehr konzentrieren - vielleicht morgen.
Fakt ist: der Fehler ist gefunden !
Erstmal an Alle DANKE
Gruß
Bernd
Noch'n Tip (ohne den Code gesehen zu haben):
Gerne wird der "Error" Status beim Slave übersehen. Das führt dann zum
hängen vom ganzen I2C Bus (SDA und SCL beine auf Low).
Stefan B. schrieb:> TWI per Hardware mit TWI-Interrupt machen. Das sind die für dich> interessanten. Wenn du da eins findest, welches manuell in der ISR TWINT> löscht, bitte verlinken :-)
Verstehe ich nicht. Wieso sollte man TWINT nicht in der ISR löschen?
Wenn man z.B. das Senden eines Buffers komplett von der ISR machen
lässt, muss man TWINT sogar in der ISR löschen, denn
> The TWINT Flag must be cleared by software by writing a logic one to> it. Note that this flag is not automatically cleared by hardware when> executing the interrupt routine.
So steht es jedenfalls im Datenblatt vom ATmega 164P/324P/644P und ich
nehme an, dass es bei den anderen AVRs genauso ist.
Gruss
Andreas
@ Andreas
Mein Fehler. Sorry, wenn ich Verwirrung gestiftet habe. Bei üblichen
ISRs lässt man i.d.R. das Interruptflag in Ruhe.
TWI-Interrupts sind anders als übliche Interrupt-ISRs zu betrachten. Bei
TWI wird in der ISR ggf. eine Antwort (z.B. ACK) an den Auslöser des
Interrupts gesendet (TWCR = ...). Und dabei ist das Setzen des TWINT
Flags Bestandteil des Antwortmechanismus.
Im Zweifelsfall immer ans Datenblatt oder Atmel Beispielcode halten.