Guten Abend,
Bin noch recht neu in AVR und bin gerade dabei den PCF 8574P über das
TWI und einem ATmega 32 zu programmieren. Die Ansteuerung über das TWI
ist mir bereits gelungen, jedoch funktioniert das ganze mit
Unterprogrammen nicht.
Folgendes Problem:
Schreibe ich den Code so funktioniert alles perfekt:
1
2
#include<avr/io.h>
3
#include<util/delay.h>
4
#include<util/twi.h>
5
6
intmain(void)
7
{
8
9
while(1)
10
{
11
TWBR=0x01;
12
TWSR=(0<<TWPS1)|(0<<TWPS0);
13
TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
14
while(!(TWCR&(1<<TWINT)));
15
TWDR=0x40;
16
TWCR=(1<<TWINT)|(1<<TWEN);
17
while(!(TWCR&(1<<TWINT)));
18
TWDR=0x00;
19
TWCR=(1<<TWINT)|(1<<TWEN);
20
while(!(TWCR&(1<<TWINT)));
21
TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
22
}
23
return0;
24
}
jetzt wollte ich das ganze in mehrere Unterprogramme packen:
1
#include<avr/io.h>
2
#include<util/delay.h>
3
#include<util/twi.h>
4
5
voidTWI_begin(void)
6
{
7
TWBR=0x01;
8
TWSR=(0<<TWPS1)|(0<<TWPS0);
9
}
10
11
voidTWI_send_start(void)
12
{
13
TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
14
while(!(TWCR&(1<<TWINT)));
15
}
16
17
voidTWI_send_address(unsignedcharadd)
18
{
19
TWDR=add;
20
TWCR=(1<<TWINT)|(1<<TWEN);
21
while(!(TWCR&(1<<TWINT)));
22
}
23
24
voidTWI_send_data(unsignedchardat)
25
{
26
TWDR=dat;
27
TWCR=(1<<TWINT)|(1<<TWEN);
28
while(!(TWCR&(1<<TWINT)));
29
}
30
31
voidTWI_send_stop(void)
32
{
33
TWCR=(1<<TWINT)|(1<<TWSTO)|(1<<TWEN);
34
}
35
36
37
intmain(void)
38
{
39
while(1)
40
{
41
TWI_begin();
42
TWI_send_start();
43
TWI_send_address(0x40);
44
TWI_send_data(0x00);
45
TWI_send_stop();
46
}
47
return0;
48
}
Allerdings funktioniert dieses nicht und ich komme nicht auf den Fehler
:(
Ich bitte um eure Hilfe
Analytisch ist es nicht besonders wertvoll nur festzustellen, das es
nicht funktioniert. Wesentlich wertvoller wäre es zu beschreiben, was
nicht funktioniert, an welcher_ Stelle im Code und _woran Du das genau
bemerkst.
Soweit ich es feststellen konnte funktioniert das Programm bis zum
Unterprogramm "TWI_send_data(0x00);" anscheinend bleibit er dort bei der
Abfrage while(!(TWCR & (1<<TWINT))); hängen.
>anscheinend...
Bitte noch präziser. Welches Ereigniss bzw. das Ausbleiben welchen
Ereignisses konkret vermittelt Dir den Anschein, das es dort hängen
bleibt ?
Woran merkst Du das? Glaskugel, Pendel, Geomantie, Wahrsagerei? :-)
Braucht Dir nicht leid tun.
>Da das Programm an dieser Stelle nicht mehr weiterläuft und in dieser>Schleife bleibt.
Aha. Und wie, auf welche Weise, mit welchen Mitteln stellst Du das fest?
Kartenlegen, Orakel, Innereien-Schau?
Mit der Noobmethode, dass ich einfach ein LED einmal vor der Schleife
und einmal nach der Schleife am Port D eingeschaltet habe und dabei
bemerkt habe, dass der Befehl vor der Schleife ausgeführt wird, danach
allerdings nicht mehr und auch im folgenden Programmteil wird nichts
mehr ausgeführt.
>Mit der Noobmethode, dass ich einfach ein LED einmal vor der Schleife>und einmal nach der Schleife am Port D eingeschaltet habe
Warum zeigst du dann nicht den Code mit den LEDs?
>...dass ich einfach ein LED einmal vor der Schleife>...und einmal nach der Schleife am Port D eingeschaltet habe
Gut. Das hätte schon mal ins erste Posting gehört, dann braucht man
nicht erst nachzufragen.
Wir können nicht ohne Zauberei einzusetzen, einschätzen ob eine
Behauptung auf konkreten Informationen beruht oder nur auf Annahmen.
Was hast Du an Werkzeugen? JTAG-Debugger? (z.B. JTAG-ICE MKII)
Spess hat ja schon das TWSR-Register erwähnt. Kannst Du feststellen, was
darin steht? Etwa über den Debugger oder Ausgabe auf einen Port?
Hast Du die Beschreibung schon gelesen?
Es hängt auch davon ab, wie die Person einzuschätzen ist. Wenn Spess uns
schreibt, das er in der while-Schleife hängen bleibt, dann glauben wir
ihm das unbesehen (bis es ernste Anzeichen gibt, das es nicht so ist).
Aber uns selbst und Unbekannten, glauben wir es erst wenn wir sicher
sind und materielle Beweise dafür vorliegen.
Nimm das Nachbohren also nicht so schwer. Ist nichts persönliches. Rein
geschäftlich. :-)
Ok hätte mir klar sein sollen :)
Programmiert wird über den Prog-s von Atmel auf dem Atmel
Evaluationboard.
Ich werden es versuchen jedoch dachte ich das es sich um einen
Anfängerfehler handelt, da das Programm ohne Unterprogramme einwandfrei
funktioniert hat und danach, wo ich es doch nur aufgeiteil habe nicht
mehr.
Hi
>Wenn Spess uns schreibt, das er in der while-Schleife hängen bleibt, dann>glauben wir ihm das unbesehen ....
Da ich notorischer Assemblerprogrammierer bin, wäre das eher ein
Anzeichen geistiger Umnachtung.
MfG Spess
>... dachte ich das es sich um einen Anfängerfehler handelt ...
Nein, tut es wohl nicht. Sei beruhigt. Falls ich nichts übersehen habe,
sollte der Code eigentlich genauso funktionieren. Du hast ja lediglich
die Zeilen aus der While-Schleife in Funktionen gepackt.
Dieser "Prog S" ist mitnichten von Atmel sondern von DIAMEX. (Immer
schön genau hingucken, gelle :-) )
Damit kannst Du leider nicht debuggen.
Es bleibt also nur, das TWSR-Register irgendwie auszugeben. Serielle
Schnittstelle, Port, Display oder sonstwie.
Was hast Du an Messmitteln? Multimeter? Oszilloskop? Aber zur Not gehts
auch mit ner LED.
>Da ich notorischer Assemblerprogrammierer bin...
OK. Ich korrigiere mich: Wenn Spess sagt, das er in einer LD, CPI,
BRNE-Schleife hängenbleibt, glauben wir ihm das unbesehen. Grins.
So habe jetzt das TWSR zu meinem Erstaunen erfolgreich ausgelesen und zu
meiner Überraschung konnte ich keine Fehler entdecken.
Hab das Register mit 5 LED's ausgelesen.
Ich poste hier noch schnell den Code mit Ergebnissen:
1
#include<avr/io.h>
2
#include<util/delay.h>
3
#include<util/twi.h>
4
5
voidTWI_begin(void)
6
{
7
TWBR=0x01;
8
TWSR=(0<<TWPS1)|(0<<TWPS0);
9
}
10
11
voidTWI_send_start(void)
12
{
13
intx=4;
14
TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
15
while(!(TWCR&(1<<TWINT)));
16
for(inti=7;i>=3;i--)
17
{
18
PORTD|=((TWSR>>i)&0x01)<<x;//Ergebnis: 0b0000 1xxx --> 0x08 --> A START condition has been transmitted
19
x--;
20
}
21
_delay_ms(1000);
22
PORTD=0x00;
23
_delay_ms(1000);
24
}
25
26
voidTWI_send_address(unsignedcharadd)
27
{
28
intx=4;
29
TWDR=add;
30
TWCR=(1<<TWINT)|(1<<TWEN);
31
while(!(TWCR&(1<<TWINT)));
32
for(inti=7;i>=3;i--)
33
{
34
PORTD|=((TWSR>>i)&0x01)<<x;//Ergebnis: 0b0010 0xxx --> 0x20 --> SLA+W has been transmitted NOT ACK has been received
35
x--;
36
}
37
_delay_ms(1000);
38
PORTD=0x00;
39
_delay_ms(1000);
40
}
41
42
voidTWI_send_data(unsignedchardat)
43
{
44
intx=4;
45
TWDR=dat;
46
TWCR=(1<<TWINT)|(1<<TWEN);
47
while(!(TWCR&(1<<TWINT)));
48
for(inti=7;i>=3;i--)
49
{
50
PORTD|=((TWSR>>i)&0x01)<<x;//Ergebnis: 0b0011 0xxx --> 0x30 --> Data byte has been transmitted NOT ACK has been received
51
x--;
52
}
53
_delay_ms(1000);
54
PORTD=0x00;
55
_delay_ms(1000);
56
}
57
58
voidTWI_send_stop(void)
59
{
60
TWCR=(1<<TWINT)|(1<<TWSTO)|(1<<TWEN);
61
}
62
63
64
intmain(void)
65
{
66
DDRD=0xFF;
67
while(1)
68
{
69
TWI_begin();
70
TWI_send_start();
71
TWI_send_address(0x40);
72
TWI_send_data(0x00);
73
TWI_send_stop();
74
}
75
return0;
76
}
Ich konnte auch kein hängen an der Schleife entdecken.
Das Programm läuft ohne Probleme durch nur Funktioniert es nicht :(
Defekt am Portexpander ist auszuschließen, das es mit dem anderen
Programm ohne Probleme funktioniert.
Nun ja. Du hast gerade mehrere Sachen auf einmal geändert, was Die
Ursache dafür sein kann, das sich das Verhalten geändert hat.
Nimm zunächst mal die delays raus. Auch den Port brauchst Du nicht auf
Null zu setzen. (Denke ich).
Auch diese Schleife ist unnötig kompliziert.
1
voidTWI_send_data(unsignedchardat)
2
{
3
// int x = 4;
4
TWDR=dat;
5
TWCR=(1<<TWINT)|(1<<TWEN);
6
while(!(TWCR&(1<<TWINT)));
7
// for(int i=7; i>=3; i--)
8
//{
9
PORTDTWSR&0xF8;
10
// x--;
11
//}
12
//_delay_ms(1000);
13
//PORTD = 0x00;
14
//_delay_ms(1000);
15
}
Ändere das auch in den anderen Funktionen.
Vielleicht ist das mit den Ausgaben allein nicht hinreichend. Schau Dir
mal die Codebeispiele im Datenblatt an. Dort wird bei den entsprechenden
Bedingungen zu Fehlern verzweigt. Vielleicht ist es besser dort
entsprechende Portbits zu setzen und in einen Endlos-Schleife zu gehen.
Fehlendes ACK ist natürlich ungünstig.