Atmega 8 einfaches TWI ( I²C) Programm

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 9 2024  19:30:57      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 ( Vorherige Seite 1 | 2 )      


Autor
Atmega 8 einfaches TWI ( I²C) Programm
Suche nach: atmega (404)

    







BID = 682778

DonComi

Inventar



Beiträge: 8605
Wohnort: Amerika
 

  


So Micha,

was ist draus geworden?

_________________

BID = 683438

gagamicha

Gelegenheitsposter



Beiträge: 58

 

  

Komme nicht weiter das ist mein slave Programm,
er legt sobald was emfpangen wird die 1 auf den Ausgang.

Der 2te AVR sendet dauerhaft die 1 über den Bus aber es funktioniert nicht. Es kommt nichts an.






/* Anfang main.c */
#include "twi.h"
#include <avr/io.h>
#include <avr/interrupt.h>
#include <inttypes.h>
/* eigene Adresse im Bus
* beachte, dass das LSB 0 sein muss! Adresse+1 ist
* für den Lesemodus bestimmt
*/
#define ADRESSE 30

volatile uint8_t i2c_flag;

int main(void)
{
DDRB = 0x01;
PORTB = 0x01;

/* TWI-Slave aktivieren */
(void) i2c_switch_slave(ADRESSE<<1);

asm volatile ( "sei \n\t" ); /* Interrupts global aktivieren */

/* Endlosschleife, z.B. Abfragen des Tasters, globaler Flaggen oder so */
while(1)
{
PORTB = 0;
if( i2c_flag )
{
PORTB = 1;
wait 30;
i2c_flag = 0;
}
}
}


/* Interrupthandler für TWI */
ISR(TWI_vect)
{
/* setze Flagge */
i2c_flag = 1;
}

/* Ende main.c */


[ Diese Nachricht wurde geändert von: gagamicha am 13 Apr 2010  7:57 ]

BID = 683439

gagamicha

Gelegenheitsposter



Beiträge: 58

Hier das programm des masters!

/* Anfang main.c */
#include "twi.h"
#include <avr/io.h>
#include <avr/interrupt.h>
#include <inttypes.h>
/* eigene Adresse im Bus
* beachte, dass das LSB 0 sein muss! Adresse+1 ist
* für den Lesemodus bestimmt
*/
#define ADRESSE 54
#define EVENT_KEY_PRESSED 0x01


volatile uint8_t i2c_flag;

int main(void)


{



DDRB = 0x01;
PORTB = 0x01;



while(1)

{
i2c_start();
i2c_transmit(30 + 1); /* hier die Adresse des anderen */
i2c_transmit(EVENT_KEY_PRESSED);
i2c_stop();

}


}





/* Interrupthandler für TWI */
ISR(TWI_vect)
{
/* setze Flagge */
i2c_flag = 1;
}

/* Ende main.c */

[ Diese Nachricht wurde geändert von: gagamicha am 13 Apr 2010  7:56 ]

BID = 683567

DonComi

Inventar



Beiträge: 8605
Wohnort: Amerika

Neeene,

Du kannst nicht einfach mein Beispielprogramm 1:1 übernehmen.
wait 30 wird auch eine schöne Fehlermeldung produzieren...

Master:

Frage den Port permanent ab, bei Änderung initiierst du eine I2C-Transaktion:

i2c_switch_master(calc_scl_freq(100000));
i2c_start();
i2c_transmit(SLAVE_ADRESSE<<1); /* ohne +1, es wird ja geschrieben, und nicht gelesen... */
i2c_transmit(EVENT_KEY_PRESSED);
i2c_stop();
i2c_switch_slave(MEINE_ADRESSE<<1);


Es ist ein bischen 'tricky' mit den Adressen: Es ist beidemale der Schiebeoperator << nötig, da das Slave-Adress-Register bei Bit0 den General Call Modus hat und das Bit0 bei der Adressierung bestimmt, ob gelesen oder geschrieben wird.
Deshalb gilt: ungerade Adressen sind nur mit Schiebeoperator möglich, gerade Adressen müssen nicht zwangsweise ein Bit nach links geschoben werden.

Aber schau dir dein Programm nochmals genau an, das würde so auch nicht funktionieren.
PORTB würde sofort wieder ausgeschaltet werden, selbst wenn Daten angekommen wären. Das geht so schnell, dass du das kurze Aufblitzen nicht mal sehen würdest.


Also, mithilfe dieser sehr kurzen Ratschläge solltest du es nochmals probieren! Auch der Verweis aufs Datenblatt kam nicht zufällig.
Leider habe ich momentan viel zu tun, sonst würde ich mehr schreiben.

_________________

BID = 683890

gagamicha

Gelegenheitsposter



Beiträge: 58

Okay THX für die infos nochmal!

Hier mal mein aktuelle programm lässt sich leider nicht compilen :

folgender Fehler: undefined reference to `calc_scl_freq'

Das programm könnte ich theoretisch auf beide AVR`s brennen und halt nur die adressen oben anpassen oder??

erstmal frag ich nur das I²C Flag ab und später noch den event Key wenn alles soweit laufen würde. Den Event key hab ich bewusst Binär "codiert" damit ich ein eindeutiges Byte habe was bedeutet LED EIN.


in der Zeile hat er anscheind das prob:

i2c_switch_master(calc_scl_freq(100000));




/* Anfang main.c */
#include "twi.h"
#include <avr/io.h>
#include <avr/interrupt.h>
#include <inttypes.h>
#define ADRESSE 32
#define SLAVE_ADRESSE 54
#define EVENT_KEY_PRESSED 0b10101010


volatile uint8_t i2c_flag;

int main(void)
{

DDRB = 0b00000001; // Eingänge und Ausgänge definieren
PORTB = 0b00000010; // PORT 0 Ausgang / PORT 1 Eingang BYTE B


for (;;)
{

i2c_switch_slave(ADRESSE<<1); // Slave Modus starten!

if( i2c_flag )
{
PORTB |= (1<<PB0);
i2c_flag = 0;
}

else

{
PORTB &=~(1<<PB0);
}



if (! (PIND & (1<<PB1)))
{
i2c_switch_master(calc_scl_freq(100000));
i2c_start();
i2c_transmit(SLAVE_ADRESSE<<1); /* ohne +1, es wird ja geschrieben, und nicht gelesen... */
i2c_transmit(EVENT_KEY_PRESSED);
i2c_stop();
i2c_switch_slave(ADRESSE<<1);
}

}

}


/* Interrupthandler für TWI */
ISR(TWI_vect)
{
/* setze Flagge */
i2c_flag = 1;
}

/* Ende main.c */












BID = 683907

DonComi

Inventar



Beiträge: 8605
Wohnort: Amerika


Zitat :

folgender Fehler: undefined reference to `calc_scl_freq'


Ich sachte doch: schau in den Header twi.h!
Dort steht das Makro, 'scl' muss groß geschrieben werden.
calc_SCL_freq.



Zitat :

Den Event key hab ich bewusst Binär "codiert" damit ich ein eindeutiges Byte habe was bedeutet LED EIN.


Nicht gut! Das macht man nicht, C kennt keine Dualzahlen, ob also das Präfix 0b für Binärzahlen hinhaut liegt am Compiler. Statt 0b10101010 kannst du auch 0xAA sagen, ist das gleiche. Das mit 'eindeutig' verstehe ich nicht, macht aber auch nichts.


Zitat :

for (;;)
{

(* Anm. 1) i2c_switch_slave(ADRESSE<<1); // Slave Modus starten!


if( i2c_flag )
{
PORTB |= (1<<PB0);
i2c_flag = 0;
}

else

{
(* Anm. 1) PORTB &=~(1<<PB0);
}

Pack das i2c_switch_slave mal vor die Endlosschleife. Das wird sonst ein paar tausend bis zehntausendmal pro Sekunde ausgeführt... (Anm. 1)
PORTB nicht in der else-Anweisung ausschalten! Überlege dir mal, was passiert, wenn die Flagge gesetzt wird: PORTB wird aktiviert, und in der nächsten Auswertung von if( i2c_flag ) ... wird die else-Anweisung abgearbeitet, also der Port sofort gelöscht. Da das alles so dermaßen schnell geht, wirst du auch hier nicht sehen, dass die LED gaaanz kurz angeht.

Mache lieber sowas:
PORTB ^= 1<<PB0;

Das invertiert bei jedem Ereignis das Bit, sie blinkt also, wobei jeder Flankenwechsel bedeutet, dass ein Ereignis stattfand.
Außerdem solltest du dafür sorgen, dass der Prozessor nur ein Paket schickt, wenn die Taste gedrückt wird. Tasten können prellen, das würde demnach zu mehreren paketen führen.

_________________


Vorherige Seite      
Gehe zu Seite ( Vorherige Seite 1 | 2 )
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 17 Beiträge im Durchschnitt pro Tag       heute wurden bisher 26 Beiträge verfasst
© x sparkkelsputz        Besucher : 182090458   Heute : 4939    Gestern : 6155    Online : 568        28.9.2024    19:30
4 Besucher in den letzten 60 Sekunden        alle 15.00 Sekunden ein neuer Besucher ---- logout ----viewtopic ---- logout ----
xcvb ycvb
0.0780048370361