Hallo.
Ich sitze hier und versuche eine Kommunikation zwischen einem DRM-Modul
( SLAVE) und einem AVR ATMEL8L (MASTER) über die I2C-Schnittstell zu
realisieren. Habe mich anhand des Forums und etlichen Beispielen bis zu
einem Fehler/Problem vorgearbeitet bei dem mir jetzt nichts mehr
einfällt.
Problem:
Es tritt kein ACK-Befehl vom Modul auf.
Dabei habe ich folgendes ausprobiert.
1. Beim ersten Versuch habe ich meinen ATMEL mit ca. 3,7MHz angesteuert.
2. Mit einem Logic-Analyzer habe ich mir die Datenleitung und die
Taktleitung betrachtet und habe festgestellt das die ACK-Sequenzen immer
zeitversetzt ankommen und somit nicht übernommen wurden.
Laut ATMEGA8L Handbuch muss das TWBR-Register > 10 sein, da es sonst zur
Problemen bei der Übertragung mit dem SLA_W kommt.
Laut Formel komme ich mit dem Quarz genau auf 10,4 was wohl dann auf
ganze 10 abgerundet wird. Deswegen entschloss ich mich den Quarz auf
6MHz aufzustocken.
Das hat zur Folge das nun überhaupt keine ACK-Sequenzen mehr angezeigt
werden.
Mein Code sieht wie folgt aus:
1 | #include <avr/io.h>
|
2 | #include <stdint.h>
|
3 | #include <compat/twi.h>
|
4 | #include <timer.h>
|
5 | #include <i2cmaster.h>
|
6 |
|
7 | #define adresse 0x58; //RS500-Adresse (Slave)
|
8 | #define data1 0x03; //RS500 Mute Befehl High-Byte
|
9 | #define data2 0x04; //RS500 Mute Befehl Low-Byte
|
10 |
|
11 |
|
12 | void ERROR()
|
13 | {
|
14 | wait(50);
|
15 | TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
|
16 | }
|
17 |
|
18 |
|
19 | /* define CPU frequency in Mhz here if not defined in Makefile */
|
20 | #ifndef F_CPU
|
21 | #define F_CPU 6000000UL
|
22 | #endif
|
23 |
|
24 | /* I2C clock in Hz */
|
25 | #define SCL_CLOCK 400000L
|
26 |
|
27 |
|
28 | /*************************************************************************
|
29 | Initialization of the I2C bus interface. Need to be called only once
|
30 | *************************************************************************/
|
31 | void i2c_init(void)
|
32 | {
|
33 | /* initialize TWI clock: 100 kHz clock, TWPS = 0 => prescaler = 1 */
|
34 |
|
35 | TWSR = 0; /* no prescaler */
|
36 | TWBR = ((F_CPU/SCL_CLOCK)-16)/2; /* must be > 10 for stable operation */
|
37 | }
|
38 |
|
39 | int main()
|
40 | {
|
41 | i2c_init();
|
42 | TWCR = (1<<TWINT)| (1<<TWSTA)|(1<<TWEN); //Senden der START Prozedur
|
43 | while (!(TWCR & (1<<TWINT))); //Warten bis das TWINNT-Flag gesetzt ist.Dieser bestätigt das die START Prozedur übermittelt würde
|
44 | if ((TWSR & TW_NO_INFO) != TW_START) ERROR(); //TWI Status Register überprüfen und Prescaler Bits maskieren. Sind die Informationen verschieden zu der START Prozedur führe ERROR aus
|
45 | TWDR = adresse; //Den SLA_W Wert in das TWDR Register laden
|
46 | TWCR = (1<<TWINT) | (1<<TWEN); //TWINT (Interrupt) Bit rücksetzen um die transmission der Adresse mit TWEN auszuführen
|
47 | while (!(TWCR & (1<<TWINT))); //Warten bis das TWINNT-Flag gesetzt ist.Dieser bestätigt das die Adresse übermittelt würde und eine ACK/NACK empfangen wurde
|
48 | if ((TWSR & TW_NO_INFO) != TW_MT_SLA_ACK) ERROR(); //TWI Status Register überprüfen und Prescaler Bits maskieren. Sind die Informationen verschieden zu der TW_MT_SLA_ACK [0x18] Prozedur führe ERROR aus
|
49 | TWDR = data1; //Den DATA1 Wert in das TWDR Register laden
|
50 | TWCR = (1<<TWINT) | (1<<TWEN); //TWINT (Interrupt) Bit rücksetzen um die transmission der Adresse mit TWEN auszuführen
|
51 | while (!(TWCR & (1<<TWINT))); //Warten bis das TWINNT-Flag gesetzt ist.Dieser bestätigt das die Adresse übermittelt würde und eine ACK/NACK empfangen wurde
|
52 | if ((TWSR & TW_NO_INFO) != TW_MT_DATA_ACK) ERROR(); //TWI Status Register überprüfen und Prescaler Bits maskieren. Sind die Informationen verschieden zu der TW_MT_DATA_ACK [0x28] Prozedur führe ERROR aus
|
53 | TWDR = data2 //Den DATA2 Wert in das TWDR Register laden
|
54 | TWCR = (1<<TWINT) | (1<<TWEN); //TWINT (Interrupt) Bit rücksetzen um die transmission der Adresse mit TWEN auszuführen
|
55 | while (!(TWCR & (1<<TWINT))); //Warten bis das TWINNT-Flag gesetzt ist.Dieser bestätigt das die Adresse übermittelt würde und eine ACK/NACK empfangen wurde
|
56 | if((TWSR & TW_NO_INFO) != TW_MT_DATA_ACK) ERROR(); //TWI Status Register überprüfen und Prescaler Bits maskieren. Sind die Informationen verschieden zu der TW_MT_DATA_ACK [0x28] Prozedur führe ERROR aus
|
57 | TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO); //Senden der STOP Prozedur
|
58 | while(1)
|
59 | {
|
60 | }
|
61 | }
|
In der Methode i2c_init() steht die Formel wie laut Datenblatt der
Faktor berechnet wird der hier 22 beträgt und für den ersten Fall mit
dem Quarz ~10.
Ich hoffe einer hat von euch einen Rat oder sieht sogar meinen Fehler.