Atmega 8 einfaches TWI ( I²C) Programm Im Unterforum Microcontroller - Beschreibung: Hardware - Software - Ideen - Projekte
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.
_________________
|
|
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 20 Beiträge im Durchschnitt pro Tag heute wurden bisher 12 Beiträge verfasst © x sparkkelsputz Besucher : 182399418 Heute : 6616 Gestern : 7548 Online : 767 25.11.2024 20:56 12 Besucher in den letzten 60 Sekunden alle 5.00 Sekunden ein neuer Besucher ---- logout ----viewtopic ---- logout ----
|
xcvb
ycvb
0.0636999607086
|