PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : I2C Problem



tristate
30.10.2005, 16:50
Kann mir mal jemand erläutern wie ich meinen µc von einem MasterTransmitter in einen MasterReceiver umschalt??
irgendwie will der bei mir nicht...bleibt immer im Sendemode.
Atmel schreibt da von einem write/read bit aber gefunden hab ich das auch noch nicht :-s
oder hat des mit der slave adresse was zu tun?? weil es ja heisst sla+w, sla+r??? blos ist die doch die selbe wenn ich einmal lesen und danach schreiben will..kein plan..
muss ich eigentlich immer ein stop vorm wechseln von w/r machen??
geht das nicht irgendwie in einem rutsch? also zB 1byte senden und 4 byte emfangen ohne den bus runterzufahren?
da ja die code schnipsel die es überall gibt nur über das Senden viel erzählen (und das funzt gottseidank!) bin ich echt am ende... ](*,)
mfg

SprinterSB
30.10.2005, 17:32
Das Write/Read Bit wird in der Slave-Adresse übertragen. Die ersten 7 Bits selektieren den Slave bzw 0000000 für Global Call, danach kommt das ersehnte Bit. 1 für Read und 0 für Write.

Nach dem Schreiben von Daten musst du die Richtung umschalten auf Lesen. Allerdings kein STOP, sindern mit REPEATED_START, damit dir kein anderer Master dazwischen funkt. Teilweise muss ein 'Dummy Write' gemacht werden, wo nur die Adresse übertragen wird aber keine Nutzdaten. Danach wird dann gelesen.

tristate
30.10.2005, 17:43
so?:
TWDR = (adresse<<1) + 1;
??? //zum emfangen
wer hat n sich das ausgedacht???
ich dacht das general call bit ist dazu da alle geräte anzusprechen??
na werd mich morgen mal ransetzen..
danke schon mal wenns so gehen sollte!
mfg

SprinterSB
30.10.2005, 17:56
so?:
TWDR = (adresse<<1) + 1;

Yepp. Oder

TWDR = (adresse<<1) | 1;

Ist nun mal so in der IIC-Spez. General Call wird AFAIK nicht über ein Bit geregelt, sondern über Adresse 0. Da ist übrigens nur Schreiben sinnvoll.

tristate
30.10.2005, 18:07
ok danke
werds mal morgen testen heut hab ich echt keine nerven mehr dafür..
mfg
woher weisst du das?? steht doch nirgends!

SprinterSB
30.10.2005, 18:20
*kopfkratz* eigentlich steht das überall, bin immer ganz erstaunt wie beredt manche Datenblätter sind

Bisher hab ich fast in jeden Datenblatt zu nen IIC-Teilchen auch ne Darlegung des IIC-Protokolls gesehen. Jedenfalls so weit, wie es vom Bauteil gebraucht wird. Bei den AVRs mit TWI-Hardware steht auch was im Manual: wie Master funktioniert, Arbitration, Global Call, wer wann warum die Arbitration verlieren kann, etc. Probeweise hab ich mal die i2c-Library (meint: Quellpaket) von Peter Fleury getestet. Geht ganz gut. Ist allerdings nur für single Master, hard bzw soft. Nen Multimasterfähigen Slave hab ich mal angefangen, aber ich hab noch sooo viel andere Dinge im Kopf...

--> http://homepage.sunrise.ch/mysunrise/peterfleury/avr-software.html

tristate
30.10.2005, 23:49
hab es doch nicht mehr ausgehalten
ES LÄUFT!!!! GEIL! \:D/
hab gleich mal noch ne "transceive" routine geschrieben..
von den routinen ala fleury hat ich nicht wirklich viel schreib sowas lieber selber..
bin überglücklich jetzt kanns weitergehen...
also danke nochmal
mfg

michaelb
31.10.2005, 10:34
Hi Tristate,
Glückwunsch!!! Mach weiter so!
Kannste mal deinen Code posten(Slave und Master)?
Darüber würde ich mich voll freuen!
Gruß Michi

tristate
31.10.2005, 17:05
MASTER sendet 1byte:

#include <avr/io.h>
#include <compat/twi.h>
#include <avr/signal.h>
#include <avr/interrupt.h>
#include <avr/delay.h>

#define master_adresse 0x01

void I2C_init(void);

void I2C_MASTER_TRANSCEIVE_ERROR(void);
void I2C_ERROR(void);
unsigned char transceive(unsigned char, unsigned char);
void main(void);

void I2C_init(void)
{
TWAR = (master_adresse<<1); //TWI-Addresse des Masters festlegen
TWSR &= 0b11111100; //Prescaler auf 1 setzen, Bit 1 und 0 auf 0
TWBR = 0xD; //Bitrate auf 12 setzen
sei(); //Interrupts global aktivieren
TWCR=(0<<TWINT)|(1<<TWEA)|(1<<TWEN);
}

void I2C_MASTER_TRANSCEIVE_ERROR(void)
{
PORTE=0x02;
I2C_ERROR();
}

void I2C_ERROR(void)
{
//STOP
TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
TWCR=(0<<TWEN);
//neu initialisieren
I2C_init();
}

unsigned char transceive(unsigned char slave_adresse,unsigned char transmit_data)
{
unsigned char received_data=0x00;

TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); //START senden
while (!(TWCR & (1<<TWINT))); //warten bis TWINT gesetzt
if ((TWSR & 0xF8) != 0x08) {I2C_MASTER_TRANSCEIVE_ERROR();} //warten auf start
//Addresse des Slaves angeben
TWDR = (slave_adresse<<1);
TWCR = (1<<TWINT) | (1<<TWEN); //Addresse senden
while (!(TWCR & (1<<TWINT))); //warten bis TWINT gesetzt
if ((TWSR & 0xF8) != 0x18) {I2C_MASTER_TRANSCEIVE_ERROR();} //master transmit slave adresse ack
TWDR = transmit_data;
PORTE =transmit_data; //DATEN senden
TWCR = (1<<TWINT) | (1<<TWEN);

while (!(TWCR & (1<<TWINT))); //warten bis TWINT gesetzt
if ((TWSR & 0xF8) != 0x28) {I2C_MASTER_TRANSCEIVE_ERROR();} //master transmit slave daten ack


TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); //REPEATED START senden
while (!(TWCR & (1<<TWINT))); //warten bis TWINT gesetzt
if ((TWSR & 0xF8) != 0x10) {I2C_MASTER_TRANSCEIVE_ERROR();} //warten auf rep start
TWDR = (slave_adresse<<1) | 1;
//Addresse des Slaves angeben
TWCR = (1<<TWINT) | (1<<TWEN) | (0<<TWSTA) | (0<<TWSTO);
while (!(TWCR & (1<<TWINT))); //warten bis TWINT gesetzt
if ((TWSR & 0xF8) != 0x40) {I2C_MASTER_TRANSCEIVE_ERROR();}

TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN);
while (!(TWCR & (1<<TWINT))); //warten bis TWINT gesetzt
if ((TWSR & 0xF8) != 0x50) {I2C_MASTER_TRANSCEIVE_ERROR();}

TWCR = (1<<TWINT) | (0<<TWEA) | (1<<TWEN);
while (!(TWCR & (1<<TWINT))); //warten bis TWINT gesetzt
if ((TWSR & 0xF8) != 0x58) {I2C_MASTER_TRANSCEIVE_ERROR();}
received_data = TWDR;

TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO); //STOP
return received_data;
}

void main(void)
{
unsigned char slave_adresse,daten;
slave_adresse =0x02;
daten=0x01;
DDRB=0xFF;
DDRE=0xFF;
I2C_init();

_delay_loop_1(1);


PORTB=transceive(slave_adresse,daten);
_delay_loop_1(15);


}

slave emfängt byte und sendet 1byte zurück:


#include <avr/io.h>
#include <compat/twi.h>
#include <avr/interrupt.h>
#include <avr/signal.h>

#define slave_adresse 0x02

void init(void)
{
TWAR = (slave_adresse<<1);
TWCR = 0b11000101;
TWBR = 0xC;
TWSR &= 0b11111100;
sei();
TWCR |= 0b10000000;
}
SIGNAL (SIG_2WIRE_SERIAL)
{

switch(TWSR & 0b11111000)
{

case 0x80: PORTB=TWDR; //byte vom master an portb


break;

case 0xB8: //byte zum master
TWDR=0xF0;

PORTE=TWDR;
break;
// default: //TWSR=0xFF;

TWCR |= 0b10000000;
}

void main(void)
{
init();
DDRB=0xFF;
DDRE=0xFF;
for(;;);
}

bittschö nicht schön aber selten...
und nun viel spass beim testen

mfg

michaelb
31.10.2005, 18:58
Hi tristate,
danke danke!!
Gruß Michi

michaelb
31.10.2005, 19:19
Hi,
daaaaaaaaaaaaaaaaaaanke es funzt!!!!!!! Ich bin glücklich! der Twi funzt endlich!
Hab den Code bisschen geändert! ich hab sobald der Slave in die Interruptroutine springt ne LED angemacht!
Hab noch ne Frage:
Geht das überhaupt so:


case 0xB8: //byte zum master
TWDR=0xF0;

dass man einfach in dieses Datenregister schreibt und es automatisch gesendet wird?
Gruß Michi

tristate
31.10.2005, 19:24
das ist ne interupt routine und wenn das tswr den status 0xB8 hat kannst du ihm sagen was er schicken soll..

michaelb
31.10.2005, 19:25
Danke!
Warum hast du 2 Threads ma laufen? Einmal Assembler und einmal C?
Gruß Michi

tristate
31.10.2005, 19:26
also du soltest nicht ewig langen code in die interrupt routine reinschreiben dann lieber irgend ein flag dir setzen und später bearbeiten

tristate
31.10.2005, 19:29
wollt es erst mal mit assembler versuchen und nun mit c da ich bei meinem bot nicht um c drumrum komm.. würde in assembler zu komplex werden zumindest für mich...da reg ich mich schon über ne simple floating addition auf... :cheesy: so un nu noch viel spass mit dem code is eigentlich ziemlich simpel...

tristate
31.10.2005, 19:37
ps: wenn du nur ne funzel(led) in der interruptroutine an machst hast du aber noch lang nicht die gesendeten daten überprüft...
mfg

michaelb
31.10.2005, 19:39
Hi,
wollt auch erst in Assembler machen aber wenn man da was ausrechenen will und bei der Navigation auch noch vielleicht Trigonometrie einsetzen will bekommt man die Krise!!
Gruß Michi

tristate
31.10.2005, 19:47
na ich denk wenn man den code in assembler einigermasen gut dokumentiert und gliedert dann bekommt man das schon hin.. aber nicht jeder macht sich soviel mühe -> so wie ich! mir haben auch einfach gute libs gefehlt um ein ganzes prog für nen bot in asm zu schreiben na wären vielleicht an die 5000 zeilen geworden...hat ja mal angefangen..aber irgendwann dann doch aufgegeben weil ich keinen überblick mehr hatte und mir es echt zu doof war mein code wieder zu disassembeln...
mfg

michaelb
01.11.2005, 12:10
Hi,
Mist jetzt hab ich ein Problem!! Wenn ich die Daten überprüfe bekomm ich false!! Also kommen nicht die richtigen Daten an! Mit was ist das zu erklären?
Gruß Michi

tristate
03.11.2005, 01:29
mh kommt bei mir nie vor.. kannst ja mal posten was du noch geändert hast
mfg

michaelb
03.11.2005, 11:19
Hi,
was benutzt du für einen Atmega ? Ich einen Atmega16! Kannste mal deine Schaltung posten? Ich hab 10KOhm Pull-ups!
Gruß Michi
P.S. Ich muss meinen Code wohl nochmal durcharbeiten da ich den Teil des Mastercodes entfernt hab der Daten enpfängt und den des Slave der die Daten schickt! Hab also nur Mastertransmitter und Slavereceiver! Muss ich da sonst noch was ändern?

tristate
03.11.2005, 11:41
2x mega128 bei der schaltung kann man nicht viel falsch machen..
mh post mal dein code
wie gesagt wenn ich simulier dann funzt das bei mir
meine schaltung im simulator: (mit pullups funzt der simu nicht wahrscheinlich n bug von proteus)

michaelb
03.11.2005, 12:38
Hi,
ach so du machst das gar nicht mit hardware! sondern du simulierst nur das ganze!! werd mir wahrscheinlich heute oder morgen neue Boards ätzen weil meine alten waren zu unübersichtlich und nicht universell! Damit werd ich mal die ganze TWI Sache nochmal probieren! Läuft bei dir das ganze schon mit Hardware?


Code posten

bevor ich den hier poste muss ich den nochmal überarbeiten da ich jetzt wahrscheinlich schon zu viele Passagen entfernt hab!!
Gruß Michi

tristate
03.11.2005, 12:51
hab keine 2 µc zur verfügung ansonsten würd ich s ja real testen wollen wenn du solche probleme damit hast. allerdings glaub ich auch nicht das mich mein proteus anlügt...
mfg