PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Neues TWI Problem!



michaelb
30.12.2005, 17:15
Hi Leuts,
hab ein neues Problem mit meinem TWI!
An dem einen Board(Master) hängt ne LED an PB0 und ein GP2D12 an PA0 an dem anderen nur eine LED an PB0. Der Master wertet den Sensor aus und schickt je nach dem 0x02 oder 0x03 an den Slave! ADC Wert hab ich einzelnd schon getestet an dem liegt's wahrscheinlich net!

So Master Code:




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

#define ADCchannel_init DDRA=0x00 // ADC Port als Eingang deklarieren
#define ADCinit ADCSRA|=_BV(ADEN) // Teilt dem Board mit das der jeweilige Port für ADC verwendet wird
#define ADCdisable ADCSRA &=~_BV(ADEN) // machs das vorherige wieder rückgänig
#define ADCstart ADCSRA|=_BV(ADSC) // startet eine konvertierung auf dem gewünschten Kannal/Pin
#define ADCfree ADCSRA|=_BV(ADATE) // schaltet den freilaufenden Modus ein
#define ADCvintern ADMUX|=_BV(REFS0) // interne Spannungsversorgung
#define ADCinterrupt_on ADCSRA|=_BV(ADIE) // ADC interrupt wird freigeschalten
#define ADCprescaler_2 ADCSRA |=_BV(ADPS0) // gewünschter Teilungsfaktor/Prescaler
#define ADCprescaler_4 ADCSRA|=_BV(ADPS1)
#define ADCprescaler_8 ADCSRA=_BV(ADPS1) | _BV(ADPS0)
#define ADCprescaler_16 ADCSRA|=_BV(ADPS2)
#define ADCprescaler_32 ADCSRA=_BV(ADPS2) | _BV(ADPS0)
#define ADCprescaler_64 ADCSRA=_BV(ADPS2) | _BV(ADPS1)
#define ADCprescaler_128 ADCSRA=_BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0)
#define ADCprescaler_reset ADCSRA = ~_BV(ADPS2) & ~_BV(ADPS1) & ~_BV(ADPS0)
#define ADCchannel_1 //gewünschter Kannal z.B bei ATmega32 PINA0 - PINA7
#define ADCchannel_2 ADMUX|=_BV(MUX0) // bei nicht freilaufen muss ADCchannel_x vor
#define ADCchannel_3 ADMUX|=_BV(MUX1) // ADCstart kommen dann kann man mit getadc() der
#define ADCchannel_4 ADMUX= _BV(MUX1) | _BV(MUX0) // Adcwert des gewählten Kannals auslesen
#define ADCchannel_5 ADMUX|=_BV(MUX2)
#define ADCchannel_6 ADMUX= _BV(MUX2) | _BV(MUX0)
#define ADCchannel_7 ADMUX= _BV(MUX2) | _BV(MUX1)
#define ADCchannel_8 ADMUX= _BV(MUX2) | _BV(MUX1) | _BV(MUX0)
#define ADCchannel_reset ADMUX= ~_BV(MUX2) & ~_BV(MUX1) & ~_BV(MUX0)


unsigned volatile char slave_adresse, daten, error;
unsigned volatile int adc_wert;

int twi_start(void);
int twi_adresse(void);
int twi_daten(void);
void twi_stop(void);
int getadc(void);

int main(void)
{
DDRB = 0xFF;
DDRA = 0x00;
PORTA = 0xFF;
TWAR = 0x01;
TWBR = 0xC;
slave_adresse = 0x02;
daten = 0x03;
ADCinit;
ADCprescaler_16;
for(;;)
{
ADCchannel_1;
ADCstart;
adc_wert = getadc();
if (adc_wert>204)
{
PORTB = (1<<PB0);
daten = 0x03;
}
else
{
PORTB &= ~(1<<PB0);
daten = 0x02;
}
twi_start();
twi_adresse();
twi_daten();
twi_stop();
}
}


int twi_start(void)
{
TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
while (!(TWCR & (1<<TWINT)));
if ((TWSR & 0xF8) == 0x08)
{
return 0;
}
else
{
return 1;
}
}

int twi_adresse(void)
{
TWDR = slave_adresse;
TWCR = (1<<TWINT)|(1<<TWEN);
while(!(TWCR & (1<<TWINT)));
if ((TWSR & 0xF8) == 0x18)
{
return 0;
}
else
{
return 1;
}
}

int twi_daten(void)
{
TWDR = daten;
TWCR = (1<<TWINT)|(1<<TWEN);
while(!(TWCR & (1<<TWINT)))
if ((TWSR & 0xF8) == 0x28)
{
return 0;
}
else
{
return 1;
}
}

void twi_stop(void)
{
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
}


int getadc(void)
{
while (ADCSRA & _BV(ADSC)) {}
return ADC;
}


und Slave:



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

unsigned volatile char slave_adresse, daten;


int main(void)
{
sei();
DDRB = 0xFF;
PORTB &= ~(1<<PB0);
TWAR = 0x02;
TWBR = 0xC;
TWCR = (1<<TWEA)|(1<<TWEN)|(1<<TWIE);
TWSR &= 0b11111100;
TWCR |= (1<<TWINT);
for(;;)
{
if(daten == 0x03)
{
PORTB = (1<<PB0);
}
else
{
PORTB &= ~(1<<PB0);
}
}
}

SIGNAL (SIG_2WIRE_SERIAL)
{
if((TWSR & 0b11111000) == 0x80)
{
daten = TWDR;
}
else
{
daten = 0x00;
}
TWCR |= (1<<TWINT);
}


bitte helft mir! sagt mir jeden Fehler den ihr findet! Ich bedanke mich schon im Vorraus!
Gruß Michi

michaelb
03.01.2006, 11:24
Hi,
so dann melde ich mich mal wieder!
Hat keiner ein Fehler finden können? :( :(
Naja dann muss ich halt mal selber probieren meinen Code zu debuggen!!
Gruß Michi

michaelb
03.01.2006, 11:42
Hi,
kann des sein dass ADC und der TWI sich gegenseitig blockieren?
Gruß Michi

tobimc
03.01.2006, 11:47
Hi Michi!

Solange der TWI und der ADC nicht die selben Ports benutzen, sollten da eigentlich keine Störungen auftreten.

Frage: Welchen AVR verwendet du, undwelche Pullups?

dein Code hat doch meines Wissens schonmal funktioniert. verglecihe ihm mal zum funktionierenden.

VLG Tobi

linux_80
04.01.2006, 22:39
Hallo,
was geht denn jetzt eigentlich nicht,
wird nicht gesendet,
wird nicht empfangen,
wird nicht gemessen ?
Was mir so auffällt, beim Master wird der TWI erst aktiviert, wenn das erste Byte zu senden ansteht, evtl. sollte TWI zumindest eingeschaltet werden, damit die Pegel an den Pins stimmen !
Ausserdem wird der Status der TWI-Funktionen in main() nicht ausgewertet, und einfach weitergemacht, das kann ja auch allesmögliche verursachen !

michaelb
04.01.2006, 23:00
Hi,
juhu endlich mal Antworten!!

@tobi
>Ich verwende den Atmega32
>ADC und TWI verwenden nicht die gleichen Pins!
>Pullups hab ich deaktiviert war ja ein Quatsch beim Analogeingang ](*,) hat aber nichts gebracht!!

@linux_80
>ob gesendet wird weiß ich nicht! aber die TWI übertragung funktioniert generell schon weil wenn ich statt nem Sharp an PB0 nen Taster hängt und den auswerte und entsprechend sende klappt es prima! z.B. sobald der Taster gedrückt ist brennt(leuchtet) die LED am Slave! So klappt das aber mit dem adc irgendwie net!

>adc funktioniert auch weil wenn statt der Sendeprozedur eine Led an den µC hängt dass die leuchten soll wenn ein bestimmter adc wert vorliegt, klappt dass! Einfachkeitshalber hab ich bei dem genannten adc Test einfach vor die TWI Routinen ein // gesetzt und somit als Kommentare deklarier!

>Fazit TWI und adc klappen einzelnd prima aber irgendwie zusammen net!!

>Ja den Status werte ich gar nicht aus stimmt könnte ich eigentlich machen aber der TWI funktioniert ja eigentlich!

>Der TWI sendet doch immer! Ist doch ne Endlosschleife!? Zuerst wird der ADC eingelesen und danach wird ausgewertet und entsprechend gesendet.

>Wie kann ich eigentlich schauen ob mein µC was über den TWI schickt? Einfach LEDs nach Masse schalten?

>Ich hab da noch ne frage! Da steh ich irgendwie gerade auf der Leitung!
Die 4 Funktionen geben ihren Errorwert zurück wie kann ich feststellen ob mindestens ein Funktion den Error gesendet hat? Etwa alle Rückgabewerte addieren und dann schauen ob der Wert über null ist?

Gruß Michi

NumberFive
05.01.2006, 06:39
Hallo Ich kann zwar nix zu dein problem bei trgaen aber dir vielleicht ein Tip geben wie so was leichter finden kann.

Da ich verwönter C++ Programmierer mit debugger und so bin hat mir die Möglichkeit bei AVR immer gefehlt so habe ich mir einfach auch ein debug mit ifdef und der serialen schnittstelle gebaut.

Leider habe ich den source gerade nicht da somit kann ich dir den nicht posten.

Ich hatte auch mal das problem das ich Interrupts aktiviert habe und mein prg nicht mehr lief (fing immer wieder von vorne an).

Fehlt bei dir vielleicht irgend ein SIGNAL was kommt ?

Gruß

linux_80
05.01.2006, 09:50
jetzt hab ich noch was gesehen,
beim Slave wird in der SIGNAL-Routine das TWI ausgeschaltet,
kommt, glaub ich, nicht so gut !

tobimc
05.01.2006, 09:52
HI Michi!

Ich meinte welche Pullups du am I2C-Bus benutzt.
4,7k? 10k?

Frage: Wie ist dein Taster beschaltet???

Die Errorwerte addieren, wäre eine Möglichkeit.
Aber warum machst du nicht sowas:

if(myfunction(...) != 0){
//error-routine
}

Da kannst du dann individuell auf den Fehler eingehen, und ihn gleich beheben.

Ist es möglich, dass das Problem evtl an deinem Taster liegt, wenn der Master andauernd sendet?

Geht die LED am Slave an?

SDA und SCL liegen ja an portc. HM.

Ist am Atmega JTAG deaktiviert?

VLG Tobi

SprinterSB
05.01.2006, 12:05
ADC und TWI blockieren sich nicht, wenn du Interrupts dafür verwendest. Wenn du in einer while-SChleife bist, macht dein µC ja nix anderes.

Der Slave erscheint mit recht mager. AVR-TWI implementiert ja eine komplette State-Machine, die zu bedienen wird wohl etwas mehr aufwand.

Bei den avr-Includes gibt es auch ein Include für twi (avr/twi.h), dann hast du defines für viele Konstanten und lesbareren Code.

michaelb
05.01.2006, 15:39
Hi Leutz,
bumm mich hat's erschlagen mit den Antworten! awa so schlimm war's nicht!
@linux_80:
>Warum soll der TWI ausgeschaltet werden? Ich setz doch bloß wieder TWINT auf 1!

@an alle:
>Der TWI alleine läuft nur in Verbindung mit dem adc nicht!!!

@tobi
>Die LED am Slave geht an wenn ich das ganze mit dem Taster statt mit dem adc mach!
>JTAG isch aus weil der TWI alleine geht ja!!
>Taster ist gegen Masse geschaltet
>Pullups = 10K


if(myfunction(...) != 0){
//error-routine
}

>Wie soll ich das machen bzw. weiß ich nicht wie ich das einsetzen soll!

@SprinterSB
>TWI-Slave funktioniert ja! wen ich am Master den Taster und nicht den Sharp hab!
>Ja kann ich mal machen mit dem Header einbinden!

Ich poste nachher mal meinen einzelnen ADC Code(Master) der funktioinert ohne die TWI Übertragung! Und den Master-Slave Code mit dem Taster am Master!

Gruß Michi

linux_80
05.01.2006, 16:13
Ich setz doch bloß wieder TWINT auf 1!
hoppala, ich hab das | nicht richtig gesehen 8)
jaa, dann, der nächte bitte ...