Atmega16 mit THMOD-I2C als Slave... keine Rückmeldung

Im Unterforum Microcontroller - Beschreibung: Hardware - Software - Ideen - Projekte

Elektronik Forum Nicht eingeloggt       Einloggen       Registrieren




[Registrieren]      --     [FAQ]      --     [ Einen Link auf Ihrer Homepage zum Forum]      --     [ Themen kostenlos per RSS in ihre Homepage einbauen]      --     [Einloggen]

Suchen


Serverzeit: 28 11 2024  09:49:38      TV   VCR Aufnahme   TFT   CRT-Monitor   Netzteile   LED-FAQ   Osziloskop-Schirmbilder            


Elektronik- und Elektroforum Forum Index   >>   Microcontroller        Microcontroller : Hardware - Software - Ideen - Projekte

Gehe zu Seite ( 1 | 2 Nächste Seite )      


Autor
Atmega16 mit THMOD-I2C als Slave... keine Rückmeldung
Suche nach: atmega16 (131) i2c (581)

    







BID = 833303

1ncept10n

Gerade angekommen


Beiträge: 8
Wohnort: regensburg
 

  


Guten Tag,

in einem Projekt ist ein Aufgabenteil zu lösen, indem eine Temperatur mit Hilfe vom Thermoelement Modul THMOD-IC2 gemessen werden soll.

Das ganze läuft wie im Namen bereits enthalten über ein IC2-Bus, der im Atmega16 über TWI realisiert wird.

In meinem Fall, so denk ich mir ist die Konfiguration als Master-Receiver sinnvoll.

Nun zum Problem: In jedem Source-Code den ich finde, wie auch in diesem Forum fängt es immer mit den selben Anweisungen an:



Code :


#include <avr/io.h>
#include <inttypes.h>
#include <avr/interrupt.h>
#include <util/twi.h>

/* Für 100 kHz, hoffe das stimmt... */
#define F_CPU 4000000UL
TWBR = 12;
TWSR = 0;

DDRC &= ~((1<<DD0) | (1<<DD1));
PORTC |= (1<<DD0) | (1<<DD1);

TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
while (!(TWCR & (1<<TWINT)));
/* Diese Schleife wird nie verlassen...
...
...
... */


Der Bus ist wie im Datenblatt beschrieben aufgebaut.. ich habe hier einfach für SDA und SCL jeweils einen 5,6 kOhm zu Vcc (5V) platziert.

Aus dem Dateblatt:
"When an event requiring the attention of the application occurs
on the TWI bus, the TWI Interrupt Flag (TWINT) is asserted..."

Ich frag mich eh wie und was hier ohne eine Adressierung passiert ?

Ich wäre sehr dankbar wenn mir hier jemand weiter helfen könnte.[/code]

BID = 833368

1ncept10n

Gerade angekommen


Beiträge: 8
Wohnort: regensburg

 

  

Mir ist aufgefallen das TWSTA im TWCR nicht gesetzt wurde, also probierte ich es mit:

TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);

Doch wieder verweilt er in dieser Schleife hier

while (!(TWCR & (1<<TWINT)));


Hat jemand eine Idee ?

BID = 833370

DonComi

Inventar



Beiträge: 8605
Wohnort: Amerika

Hallo 1ncept10n,

mit dem Code kann man so erst mal nicht viel anfangen.
Was soll diese Zeile denn bewirken?
Eine Initialisierung als Master Receiver darf nur aus einem gesetzten Bit TWEN bestehen, sonst nichts weiter!

TWINT wird immer dann gesetzt, wenn auch eine konkrete Transaktion auf dem Bus vom Master ausgelöst werden soll, das ist hier ja noch gar nicht der Fall. TWEA bewirkt, dass nach einem empfangenen Byte ein ACK zurückgegeben wird, hier ebenfalls nicht sinnvoll.

Also: was willst du erreichen?


Der normale Fall sieht so aus:
Der Master beginnt als Master Transmitter und erzeugt zunächst eine Start-Kondition auf dem Bus, sendet dann die Adresse des Slaves (das letzte Bit der Transaktion gibt an, ob im Folgenden gelesen oder geschrieben werden soll). Der Slave sendet nach Empfang ein ACK.

Alle Bus-Transaktionen werden von der TWI-Hardware überwacht und alle möglichen Zustände, die dabei eintreten können sind nach einer abgeschlossenen Transaktion im TWI-Statusregister abgelegt.


Das ist alles bis ins kleinste Detail im Datenblatt beschrieben.

Du musst jetzt nur das im Datenblatt des Slaves angegebene Protokoll implementieren, dann klappt das auch.

Schreibe dazu am besten einen Satz von Funktionen zum Erzeugen von Start-, Stop-, Lesen- und Schreiben-Transaktionen.

Je nachdem, welche Anforderungen an die Stabilität gestellt werden, musst du auch berücksichtigen, dass der Slave mal nicht antwortet und entsprechend eine Timeout-Bedingung einbauen, denn wenn der Slave mal nicht reagiert, wartest du Ewigkeiten auf TWINT.
Alternativ macht man das asynchron mit Interrupts, denn sobald TWINT eine Änderung erfährt, wird ein Interrupt ausgelöst. Anhand des Statusregisters und des Status deiner eigenen Routinen kann man dann ermitteln, was als nächstes zu tun ist (endlicher Zustandsautomat).

Einen Satz Routinen kann ich dir geben, gib mir am besten per Mail deine Emailadresse.


_________________

BID = 833372

DonComi

Inventar



Beiträge: 8605
Wohnort: Amerika

Hier müsste der Ablauf etwa so aussehen:

Master <- Transmitter
Master: Start-Kondition
Master: Slave-Adresse 0x78 + 1; /* Bit0=1: lesen, Bit0=0: schreiben */
Slave: antwortet i.d.R. mit NACK, da es das letzte gelesene Byte war, kann hier aber auch ACK sein, ausprobieren!
Master <- Receiver
Master: lese Byte0, sende ACK
Master: lese Byte1, sende ACK
Master: lese Byte2, sende ACK,
Master: lese Byte3, sende NACK
Master: Stop-Kondition


Fertig.


_________________

BID = 833374

DonComi

Inventar



Beiträge: 8605
Wohnort: Amerika

Habe mal den alten Source rausgekramt, bitte schön.

Mein Tipp: implementiere ein Softwaremodul (am besten so nennen, wie den Temperaturchip), indem du die Kommunikation abwickelst.
Dort musst du dann twi.h inkludieren.

Beispiel:

/* Initialisierung, Angabe der Taktgeschwindigkeit in Hz, hier 100kHz */
i2c_switch_master(i2c_sclclock(100000));



Beispiel: Lese Daten von einem DS1377 (Echtzeit-Uhr)

static uint8_t
ds1377_read_data(void)
{
	i2c_start();
	i2c_transmit(DS1337_ADDR + 1);
	register uint8_t ret = i2c_receive(NACK);
	i2c_stop();
	return ret;
}


So ähnlich wird deines auch aussehen .


_________________

BID = 833383

1ncept10n

Gerade angekommen


Beiträge: 8
Wohnort: regensburg

Herzlichen Dank für deine Bemühungen !

Danke für die Routinen, sehr ordentlich programmiert!
Jetzt hab ich zwar verstanden wie es mit der Abfolge des Senden und Empfangen aussieht.. jedoch besteht das selbige Problem weiterhin:

void main()
{
/* LEDs zum testen */
DDRB = 0xFF;
PORTB = 0xB;

i2c_switch_master(i2c_sclclock(100000));

/* Aus der i2c_start */

/* Startkondition erzeugen */
TWCR = 1<<TWINT|1<<TWEN|1<<TWSTA;
/* Warten, bis TWINT gesetzt ist */

while(!(TWCR & (1<<TWINT)));
PORTB = 0x00;
}

Die LEDs leuchten dauerhaft.. TWINT bleibt immer 0.

BID = 833389

DonComi

Inventar



Beiträge: 8605
Wohnort: Amerika

Benutze bitte direkt die Aufrufe wie i2c_start() usw, das macht es für mich leichter.

Beim Mega16 sind die Pins nicht auf 4,5 sonder 0,1; ändere mal in i2c_switch_master() den IO-Teil auf


	/* IO einrichten */
	DDRC &= ~(1<<0|1<<1);
	PORTC |= (1<<0|1<<1);


Daran wird es vermutlich nicht liegen, aber dennoch machen.

Ich vermute immer noch, dass die Hardware nicht korrekt angeschlossen ist.
Wenn der Slave nicht reagiert, kann der TWI-Bus das ganze Programm blockieren.


_________________

BID = 833392

1ncept10n

Gerade angekommen


Beiträge: 8
Wohnort: regensburg

Danke,

ouh das habe ich übersehen, schon geändert.. ohne Auswirkungen.
Stromlaufplan habe ich hochgeladen...

Betriebsspannung am Modul ist 16V (Datenblatt: 6...24V)

Ansonsten kann man nicht viel falsch machen denk ich...
USART und alles andere habe ich bereits aus Verzweiflung abgeklemmt..


EDIT: Bilddatei nochmal hochgeladen.


[ Diese Nachricht wurde geändert von: 1ncept10n am  9 Jun 2012 22:04 ]

BID = 833427

DonComi

Inventar



Beiträge: 8605
Wohnort: Amerika

Auf dem Bild hast du SCL und SDA vertauscht.
Ist das auch so implementiert oder hast du dich versehen?

Edit:
Da ich den Rahmen des Projekts sowie dein Elektrotechnik-Wissen nicht kenne, frage ich vorsichtshalber mal nach: beide Bausteine, also µC und Sensor, liegen hoffentlich auf gleichem GND-Potential und alle ICs sind mit 100nF gestützt?


_________________


[ Diese Nachricht wurde geändert von: DonComi am 10 Jun 2012  6:14 ]

BID = 833428

Her Masters Voice

Inventar


Avatar auf
fremdem Server !
Hochladen oder
per Mail an Admin

Beiträge: 5308
Wohnort: irgendwo südlich von Berlin

vielleicht vergessen JTAG abzuschalten? Der liegt doch beim M16 auf Port C wenn ich mich recht erinnere.

BID = 833450

1ncept10n

Gerade angekommen


Beiträge: 8
Wohnort: regensburg

Ach das tut mir leid, ich hab den Plan zum Posten erstellt und auch noch die 2 Pins vertauscht.. Auf dem Steckbrett ist aber alles in Ordnung...
JTAGEN ist aus, danke.

Ich hab jetzt den ATmega16 getauscht und die Start-Kondition läuft
Wirklich eigenartig... ich hab alle Timer, USART, ADC usw am laufen gehabt ... naja, wie auch immer es läuft.

Ich werde jetzt mit Hilfe den Routinen von dir versuchen etwas auszulesen.
Melde mich dann, vielen Dank !

BID = 833517

DonComi

Inventar



Beiträge: 8605
Wohnort: Amerika

Nein, JTAG liegt darüber, beginnt also bei PC2.

Was allerdings schon häufig passiert ist, dass der Watchdog aktiviert war und regelmäßig ein Reset ausgeführt hat. Ist hier aber nicht der Fall, das Verhalten wäre anders.


P.S.: wenn ich mich nicht täusche, kann man sich die IO-Initialisierung auch sparen.
Das Einzige Interessante, was dann bleibt, ist, dass man sich externe Pullups spart. Allerdings sollten die für hohe Geschwindigkeiten deutlich kleiner als 10kΩ.

_________________

BID = 833520

1ncept10n

Gerade angekommen


Beiträge: 8
Wohnort: regensburg

Ich bin nun wieder an einem Punkt angelangt, an dem ich nicht weiterkomme...
Einmal mit folgender TWDR: 0x78 + 1

    register uint8_t received_data;
    DDRB = 0xFF;
    PORTB = 0xB;

    i2c_switch_master(i2c_sclclock(100000));

    i2c_start();
    USARTWriteChar(TWSR & 0xF8); /* Status: 0x08 */

    i2c_transmit(0x78 + 1);
    USARTWriteChar(TWSR & 0xF8); /* Status: 0x48 */

    received_data = i2c_receive(NACK); /* Verbleibt hier... */
    USARTWriteChar(TWSR & 0xF8);

    i2c_stop();
    USARTWriteChar(TWSR & 0xF8);

    PORTB = 0x0A; [/code]/* LED */
    USARTWriteChar(received_data);



Und nach einem Tutorial dieser TWDR: 0x78 << 1

    register uint8_t received_data;
    DDRB = 0xFF;
    PORTB = 0xB;

    i2c_switch_master(i2c_sclclock(100000));

    i2c_start();
    USARTWriteChar(TWSR & 0xF8); /* Status: 0x08 */

    i2c_transmit(0x78 << 1 | TW_WRITE);
    USARTWriteChar(TWSR & 0xF8); /* Status: 0x20 */

    received_data = i2c_receive(NACK);
    USARTWriteChar(TWSR & 0xF8); /* Status: 0x30 */

    i2c_stop();
    USARTWriteChar(TWSR & 0xF8); /* Status: 0x30 */

    PORTB = 0x0A; /* LED */
    USARTWriteChar(received_data); /* received_data = 0xF0 */

Wobei ( 0x78 << 1 ) der Ausgabe 0xF0 entspricht !?
Ich habe es mit NACK und ACK probiert.. selbes Ergebnis

Edit: i2c_stop() und register nachgetragen. ( Kein Unterschied )

[ Diese Nachricht wurde geändert von: 1ncept10n am 10 Jun 2012 18:08 ]

BID = 833533

DonComi

Inventar



Beiträge: 8605
Wohnort: Amerika

Das mit der Adresse ist immer so eine Sache...
Die ersten 7 Bits, die übertragen werden, entsprechen der Adresse. Das letzte Bit dem Lese- oder Schreibbit.

Nun muss die Adresse ein Bit nach links geschoben werden und das LSB entsprechend gesetzt oder gelöscht werden.

Es gibt demnach zwei gängige Methoden, die Adresse eines Slaves anzugeben.
1. Man gibt tatsächlich eine Adresse an, die max. 7 Bit groß ist. Man muss sie selbst eine Stelle nach links schieben und das Lese-/Schreibbit anhängen, oder
2. Es werden zwei Adressen bekanntgegeben, einmal die Schreibadresse und einmal die Leseadresse. Hier also Schreibadresse 0xF0 und Leseadresse 0xF1.


Da die TWI-Geschichte nun offenbar funktioniert, musst du das im Datenblatt angegebene Protokoll implementieren. Dort werden nacheinander vier Bytes gelesen.


Im Datenblatt fehlt eigentlich ein Timingdiagramm einer gesamten Lesetransaktion.
Da musst du einfach probieren, bist aber auf dem richtigen Weg.

Du musst im Datenblatt gucken, wie du die empfangenen Bytes in die gewünschten Daten umrechnen musst.


_________________


[ Diese Nachricht wurde geändert von: DonComi am 10 Jun 2012 19:17 ]

BID = 833536

1ncept10n

Gerade angekommen


Beiträge: 8
Wohnort: regensburg

Danke,
nun ich finde den Fehler einfach nicht...

Habe jetzt eben zum Lesen i2c_transmit(0xF1) verwendet.
Ergebnis:
/* A START condition has been transmitted */
/* SLA+R has been transmitted; NOT ACK has been received */
Doch kommt er aus dem i2c_receive(NACK) nicht raus..

Mit 0xF0 bleibt die Adresse bis zur Rückgabe im TWDR...
Jetzt weiß ich wirklich nich mehr weiter...



      Nächste Seite
Gehe zu Seite ( 1 | 2 Nächste Seite )
Zurück zur Seite 0 im Unterforum          Vorheriges Thema Nächstes Thema 


Zum Ersatzteileshop


Bezeichnungen von Produkten, Abbildungen und Logos , die in diesem Forum oder im Shop verwendet werden, sind Eigentum des entsprechenden Herstellers oder Besitzers. Diese dienen lediglich zur Identifikation!
Impressum       Datenschutz       Copyright © Baldur Brock Fernsehtechnik und Versand Ersatzteile in Heilbronn Deutschland       

gerechnet auf die letzten 30 Tage haben wir 19 Beiträge im Durchschnitt pro Tag       heute wurden bisher 3 Beiträge verfasst
© x sparkkelsputz        Besucher : 182416662   Heute : 1159    Gestern : 7490    Online : 352        28.11.2024    9:49
4 Besucher in den letzten 60 Sekunden        alle 15.00 Sekunden ein neuer Besucher ---- logout ----viewtopic ---- logout ----
xcvb ycvb
0.0973801612854