Hallo Zusammen, Bin gerade dabei eine Kommunikation zwischen einem AT89C51CC03 und einem ATMEGA64 über I2C zu realisieren. Der 8051 arbeitet als Master und die Steuerung ist über Software gelöst. Im ATMEGA verwende die interne TWI-Hardware und eine Interruptsteuerung. Wenn ich jetzt einen write-befehl an den Slave schicke, erkennt dieser seine eigene Adresse und schickt auch Daten zurück. Das sind wie im Bild zu erkennen zwei Byte (1.Byte: 19; 2.Byte: 27). Dann sollte eigentlich die Stop-Condition kommen. Tut sie aber nicht. Soweit ich erkenne zieht der Slave die Datenleitung auf Masse und unterbricht so eine weitere Kommunikation. Ein anderer Baustein (MAX520) kann problemlos angesteuert werden. Bei dem treten dann auch keine zeitlichen Abstände zwischen den einzelnen Bytes auf. Hoffe mir kann jemand weiter helfen
Guten Morgen, habe hier das Programm vom ATMEGA64:
1 | |
2 | #include "defines.h" |
3 | #include "TWI2/TWI_Slave.h" |
4 | #include "lcd/lcd.h" |
5 | |
6 | //---------------
|
7 | |
8 | volatile uint16_t SWSI[6]; //!< Register fuer AD-Werte (soll alle 100ms neu beschrieben werden) |
9 | |
10 | uint16_t Zaehler=0; |
11 | |
12 | char ausgabe[16]; |
13 | |
14 | volatile uint8_t akt=0; //!< Aktiviert Schreibvorgang des Spannungswerts ins Menue |
15 | |
16 | uint8_t jj=0, SWSIAuswahl=0; |
17 | |
18 | //----------------
|
19 | |
20 | void init_io(void); //!< Initialisierung Allgemein |
21 | void I2Cfkt(uint8_t TWIS_ResonseType); |
22 | |
23 | |
24 | int main(void) |
25 | {
|
26 | uint8_t uebergabe,jj=0,kk=0; |
27 | uint8_t TWIS_ResonseType; |
28 | |
29 | init_io(); |
30 | lcd_init(); |
31 | |
32 | cli(); |
33 | _delay_ms(500); // wait 500ms |
34 | uebergabe = ATMEGA; |
35 | |
36 | if(!(TWIS_Init(uebergabe, 20000))) // IC Slave Einstellungen |
37 | {
|
38 | lcd_string("i2c falsche bitrate"); |
39 | _delay_ms(1000); |
40 | }
|
41 | sei(); |
42 | |
43 | //---------------- P R O G R A M M ------------------
|
44 | |
45 | lcd_string(">>>"); |
46 | while (1) |
47 | {
|
48 | }
|
49 | }
|
50 | |
51 | void I2Cfkt(uint8_t TWIS_ResonseType) |
52 | {
|
53 | uint8_t eingang, uebergabe; |
54 | |
55 | jj++; |
56 | itoa(TWIS_ResonseType,ausgabe,16); |
57 | lcd_string(ausgabe); |
58 | lcd_string(","); |
59 | switch (TWIS_ResonseType) |
60 | {
|
61 | case TWIS_ReadBytes: |
62 | uebergabe=TWIS_ReadAck(); |
63 | itoa(uebergabe,ausgabe,10); |
64 | lcd_string(ausgabe); |
65 | uebergabe=TWIS_ReadAck(); |
66 | itoa(uebergabe,ausgabe,10); |
67 | lcd_string(ausgabe); |
68 | |
69 | TWIS_Stop(); |
70 | break; |
71 | |
72 | case TWIS_WriteBytes: |
73 | TWIS_Write(19); |
74 | TWIS_Write(27); |
75 | |
76 | TWIS_Stop(); |
77 | break; |
78 | |
79 | default:
|
80 | break; |
81 | }
|
82 | }/*I2Cfkt*/ |
83 | |
84 | |
85 | /**
|
86 | * Initialisierung Datenrichtung, Timer0, Timer1, Interruptenable
|
87 | */
|
88 | void init_io() |
89 | {
|
90 | DDRA = 0b00000100; //HW Addresses and LDAC |
91 | DDRB = 0b11110000; //PORT B Outputs |
92 | DDRC = 0x0FF; |
93 | DDRD = 0b01100000; //Enable signals |
94 | DDRE = 0b00000011; |
95 | DDRF = 0b10111111; |
96 | PORTF = 0b01000000; |
97 | }
|
98 | |
99 | ISR (TWI_vect) |
100 | {
|
101 | uint8_t TWIS_ResonseType; |
102 | |
103 | TWIS_ResonseType = TWSR; |
104 | I2Cfkt(TWIS_ResonseType); |
105 | }
|
Die Funktion TWI_Slave.c ist übernommen von Manfred Langemann und abgeändert, damit sie auch mit der ISR läuft.
1 | #include <stdio.h> |
2 | #include <avr/interrupt.h> |
3 | |
4 | #include "TWI_Slave.h" |
5 | |
6 | /**
|
7 | * @brief Initialise the TWI Slave Interface
|
8 | * @param[in] Address Slave address
|
9 | * @param[in] Bitrate TWI_Bitrate (Hz)
|
10 | *
|
11 | * @return FALSE Bitrate too high
|
12 | * @return TRUE Bitrate OK
|
13 | */
|
14 | uint8_t TWIS_Init (uint8_t Address, uint32_t Bitrate) |
15 | {
|
16 | /*
|
17 | ** Set the TWI bitrate
|
18 | ** If TWBR is less 11, then error
|
19 | */
|
20 | TWBR = ((F_CPU/Bitrate)-16)/2; |
21 | if (TWBR < 11) return FALSE; |
22 | /*
|
23 | ** Set the TWI slave address
|
24 | */
|
25 | TWAR = (Address << 1); |
26 | /*
|
27 | ** Activate TWI interface
|
28 | */
|
29 | TWCR = (1<<TWEN)|(1<<TWEA)|(1<<TWIE); |
30 | |
31 | return TRUE; |
32 | }
|
33 | /**
|
34 | * @brief Stop the TWI Slave Interface
|
35 | */
|
36 | void TWIS_Stop (void) |
37 | {
|
38 | TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO)|(1<<TWEA)|(0<<TWSTA)|(1<<TWSTO)|(0<<TWWC)|(1<<TWIE); |
39 | }
|
40 | |
41 | /**
|
42 | * @brief Write a byte to the master
|
43 | *
|
44 | * @param[in] byte to be sent
|
45 | *
|
46 | * @return TRUE OK, Byte sent
|
47 | * @return FALSE Error in byte transmission
|
48 | */
|
49 | void TWIS_Write (uint8_t byte) |
50 | {
|
51 | TWDR = byte; |
52 | TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA); |
53 | while (!(TWCR & (1<<TWINT))); |
54 | }
|
55 | |
56 | /**
|
57 | * @brief Read a byte from the master and request next byte
|
58 | * @return Read byte
|
59 | */
|
60 | uint8_t TWIS_ReadAck (void) |
61 | {
|
62 | TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA); |
63 | while (!(TWCR & (1<<TWINT))); |
64 | return TWDR; |
65 | }
|
66 | |
67 | /**
|
68 | * @brief Read the last byte from the master
|
69 | * @return Read byte
|
70 | */
|
71 | uint8_t TWIS_ReadNack (void) |
72 | {
|
73 | TWCR = (1<<TWINT)|(1<<TWEN); |
74 | while (!(TWCR & (1<<TWINT))); |
75 | return TWDR; |
76 | }
|
77 | |
78 | /**
|
79 | * @brief Get the response type to be performed by slave
|
80 | * @param[in] *TWI_ResonseType Pointer to response type
|
81 | * - TWIS_ReadBytes --> Read byte(s) from master
|
82 | * - TWIS_WriteBytes --> Write byte(s) to master
|
83 | *
|
84 | * @return Response required
|
85 | * - TRUE: Yes, response required
|
86 | * - FALSE: No response required
|
87 | */
|
88 | uint8_t TWIS_ResonseRequired (uint8_t *TWI_ResonseType) |
89 | {
|
90 | *TWI_ResonseType = TWSR; |
91 | return TWCR & (1<<TWINT); |
92 | }
|
So hab mein Problem gelöst. War ein typisches 30cm Problem... Damit andere nicht vlt in die selbe Falle tappen, schreibe ich hier kurz worauf man auf jeden Fall achten sollte: Möchte man mehrere Bytes übertragen sollte man darauf achten, dass nach dem letzten Byte ein NotAck zurück gegeben wird. Tut man das nicht passieren unerwartete Effekte... Dachte man braucht das nur wenn man variable Byte-längen hat.
Hallo, schön das es jetzt geht. Was soll eigentlich das TWIS_Stop() wenn du der Slave bist? - das Stop kommt vom Master! Dieses Stop brauchst du eigentlich nur wenn der Bus einen ungültigen Zustand hat (TWSR=0x00). Und noch was - die Displayausgabe hat in der ISR nichts zu suchen, kein Wunder wenn du in der Übertragung laaaange Pausen hast. Sascha
Hi Sascha, > Was soll eigentlich das TWIS_Stop() wenn du der Slave bist? - das Stop > kommt vom Master! Dieses Stop brauchst du eigentlich nur wenn der Bus > einen ungültigen Zustand hat (TWSR=0x00). Wenn ichs nicht mit rein nehme hängt sich der Bus auf -> nach dem letzten Byte bleiben beide Signale (scl und sda) auf Masse. Die Funktionen habe ich von hier Beitrag "AVR TWI Master und Slave Funtionen in C". Manfred Langemann macht es in dem Beispielcode TWI_Slave_main.c genauso:
1 | main(){ |
2 | //...
|
3 | while(1){ |
4 | |
5 | //Check wether something is to do for the TWI slave interface
|
6 | |
7 | if (TWIS_ResonseRequired (&TWIS_ResonseType)) |
8 | {
|
9 | switch (TWIS_ResonseType) |
10 | {
|
11 | /*
|
12 | ** Slave is requests to read bytes from the master.
|
13 | ** It is expliciltely assumed, that the master sends 8 bytes
|
14 | */
|
15 | case TWIS_ReadBytes: |
16 | for (i=0;i<7;i++) |
17 | {
|
18 | byte[i] = TWIS_ReadAck (); |
19 | printf ("Byte read: %d\n",byte[i]); |
20 | }
|
21 | byte[7] = TWIS_ReadNack (); |
22 | printf ("Byte read: %d\n",byte[7]); |
23 | TWIS_Stop (); |
24 | break; |
25 | /*
|
26 | ** Slave is requested to send bytes to the master.
|
27 | ** It is expliciltely assumed, that the master expects 8 bytes
|
28 | */
|
29 | case TWIS_WriteBytes: |
30 | for (i=0;i<8;i++) |
31 | {
|
32 | TWIS_Write (j++); |
33 | printf ("Byte sent: %d\n", j-1); |
34 | }
|
35 | TWIS_Stop (); |
36 | break; |
37 | }
|
38 | }
|
39 | }
|
40 | }
|
Was die Displayausgabe angeht: Da hast du recht! Hatte sie nur zu Testzwecken drinnen um mir das Statusbyte anzeigen zu lassen. Ohne gehts natürlich deutlich schneller :) wobei 15kHz nicht wirklich schnell ist...
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.