Hallo nochmal!
Wieder habe ich ein Problem mit dem Abfragen von Tastern. und zwar soll
einfach beim Druck auf einen Taster am STk500 die darüberligende LED
leuchten. Nur irgendwie habe ich es auch noch nicht ganz mit den
Pullup-Widerständen verstanden....
Was ist falsch?
#include <avr/io.h>
int main(void)
{
DDRA=0xFF; //Ausgang = PortA
PORTB=0x00; //Pullup-Widerstände ausschalten
DDRB=0x00; //PortB als Eingang
for(;;)
{
if (PORTB=0x01) //wenn erster Taster1 gedrückt ist, dann...
{
PORTA=0x01; //leuchte LED1
}
}
.
.
.
.
}
Danke!
Hallo,
PORTB=0x00; //Pullup-Widerstände ausschalten
DDRB=0x00; //PortB als Eingang
und sollte man die PullUps nicht eher EINschalten, damit es überhaupt
einen Hig-Pegel am Pin geben kann, wenn nichts gedrückt ist?
PS: die PullUps liegen zwischen Eingangspin und +Ub, wenn sie
eingeschaltet sind und sorgen so dafür, daß es überhaupt definierte
Verhältnisse in dieser Beschaltung gibt. Ohne hängt der Pin einfach nur
in der Luft, wenn die Taste nicht gedrückt ist...
Gruß aus Berlin
Michael
ok vielen Dank!
ich habe meinen fehler selbst gefunden...es war die If-Abfrage mit ==
und =. Programmiere nebenher noch Visual Basic und da gibts kein "=="
sondern NUR "=", drum war ich bissl verwirrt ;)
nun noch eine Frage:
Ich habe selbst ein Board aufgebaut und bei dem muss ich nicht wie beim
STK500 beispielsweise den Taster1 mit "0x7F" sondern einfach mit "0x01"
abfragen. Woran liegt das? Gibt es so eine Art "invertierung" in C,
damit ich anstelle von 0x7F für das STK500 auch 0x01 schreiben kann?
danke!
EinSteigÄr wrote:
> ok vielen Dank!>> ich habe meinen fehler selbst gefunden...es war die If-Abfrage mit ==> und =. Programmiere nebenher noch Visual Basic und da gibts kein "=="> sondern NUR "=", drum war ich bissl verwirrt ;)
Das war aber nicht dein einziges Problem :-)
>> nun noch eine Frage:>> Ich habe selbst ein Board aufgebaut und bei dem muss ich nicht wie beim> STK500 beispielsweise den Taster1 mit "0x7F" sondern einfach mit "0x01"> abfragen. Woran liegt das?
Das liegt daran, dass du deine Taster anders angeschlossen
hast, als sie im STK500 angeschlossen sind.
Im STK500 sind sie so angeschlossen:
PIN ---o----------+
|
/
/
|
|
GND ----------+
Du hast deine so angeschlossen
Vcc -------------+
|
/
/
|
|
PIN ---o----------+
|
+-+
| |
+-+
|
GND -----------+
Wenn also in der STK Variante der Taster geschlossen wird, so
stellt er eine Verbindung zu Masse her. Das hat den Vorteil, dass
dann die AVR internen Pullup Widerstände zugeschaltet werden
können und keine externen benötigt werden wie bei deiner Lösung.
(Du hast doch Pulldown Widerstände eingebaut, oder?)
> Gibt es so eine Art "invertierung" in C,> damit ich anstelle von 0x7F für das STK500 auch 0x01 schreiben kann?
Sicher gibt es das: Die Tilde ~
~0x01 == 0x7F
~0x7F == 0x01
Die Tilde dreht alle Bits um. Sollte sich aber auch in deinem
C Buch finden.
ok vielen Dank!
Habe es jetzt gecheckt...
Nun noch eine Frage lieber Karl heinz, und zwar bin ich nun fast mit
meinem Projekt fertig. (Außer dass ich noch die Schaltung löten muss ->
kann ja nicht das STK500 abgeben ;) und noch paar Verbesserungen am
Programm vornehmen muss)...
Hier mal der Quellcode. Ich hoffe du weißt noch um was es ging. Es ist
das Projekt mit den Lichtschranken, die nacheinander Durchfahren werden.
Sobald eine Lichtschranke durchfahren wird, wird der momentane
TimerRegister in eine variable (reg1...8) gespeichert und der bis dahin
stattgefundene Überlauf dieses Timer-Registers (ubergabe1...8). Der 8.
Taster ist zum Senden der Variablen (ubergabe1...8 und reg1...8) über
den UART gedacht.
Nun mein Problem: Wenn ich im Terminal die werte ansehe (also nachdem
ich den schalter8: 0x7F gedrückt habe), kommen da schon mal nicht alle
werte an, obwohl ich nacheinander die 8 Taster drücke. Somit müssten ja
14 Werte (8 "reg"-variablen und 8 "ubergabe"-variablen plus jeweils ein
x dazwischen) erscheinen. Es kommen aber immer nur 5 (plus Trenn"x").
Die x haben nur die Aufgabe, dass das von mir geschrieben VisualBasic
Programm weiß, wann es die werte in die nächste Textbox/Variable
schreiben soll. Nächstes Problem ist, dass MINUS-Zahlen kommen??!!
Hier der Code:
if(TIFR&(1<<TOV0))//wenn generell Überlauf, erhöhe Variable "ubergabe" um eins
62
{
63
ubergabe++;
64
TIFR=1<<TOV0;
65
}
66
67
if(PINB==0xFE)//wenn Taste1 gedrückt wird, dann schreibe in Var "reg1" den Zählerstand (TCNT0)
68
{//und den momentanen Wert von Var "uberlauf" in "uberlauf1"
69
reg1=TCNT0;
70
ubergabe1=ubergabe;
71
}
72
if(PINB==0xFD)
73
{
74
reg2=TCNT0;
75
ubergabe2=ubergabe;
76
}
77
if(PINB==0xFB)
78
{
79
reg3=TCNT0;
80
ubergabe3=ubergabe;
81
82
}
83
if(PINB==0xF7)
84
{
85
reg4=TCNT0;
86
ubergabe4=ubergabe;
87
}
88
if(PINB==0xEF)
89
{
90
reg5=TCNT0;
91
ubergabe5=ubergabe;
92
}
93
if(PINB==0xDF)
94
{
95
reg6=TCNT0;
96
ubergabe6=ubergabe;
97
}
98
if(PINB==0xBF)
99
{
100
reg7=TCNT0;
101
ubergabe7=ubergabe;
102
}
103
if(PINB==0x7F)
104
{
105
reg8=TCNT0;//sobald der letzte Taster(taster8) gedrückt wird, dann wird der Timer gestoppt und über kontrol=1 das senden der Daten über den UART verursacht
EinSteigÄr wrote:
> Nun mein Problem: Wenn ich im Terminal die werte ansehe (also nachdem> ich den schalter8: 0x7F gedrückt habe), kommen da schon mal nicht alle> werte an, obwohl ich nacheinander die 8 Taster drücke. Somit müssten ja> 14 Werte (8 "reg"-variablen und 8 "ubergabe"-variablen plus jeweils ein> x dazwischen) erscheinen. Es kommen aber immer nur 5 (plus Trenn"x").
Wie hast du das kontrolliert?
Häng doch mal ein Terminalprogramm (Hyperterminal) an die
Leitung und schau nach was da ankommt.
So wie es aussieht, gibt es 2 Fehlermöglichkeiten:
Entweder schickt der Sender (also der AVR) nicht das was er soll
oder der Empfänger wertet das empfangene nicht korrekt aus.
Da das empfangende Programm ebenfalls von dir ist, kann der Fehler
in beiden stecken. Und um rauszukriegen in welchem, ersetzt man
halt mal eine Seite durch ein Programm, von dem man weiss das
es funktioniert. In deinem Fall ist das einfachste, da mal
ein Termialprogramm ala Hyperterminal dranzuhängen.
> Die x haben nur die Aufgabe, dass das von mir geschrieben VisualBasic> Programm weiß, wann es die werte in die nächste Textbox/Variable> schreiben soll. Nächstes Problem ist, dass MINUS-Zahlen kommen??!!
Auch das ist klar.
Bei dir ist alles ein int. Und ein int kann nun mal auch negativ
werden. Insbesondere wird eine Addition von 1 zur größtmöglichen
positiven Zahl einen 'Überlauf' zur kleinstmöglichen Zahl bewirken.
Genau aus dem Grund gibt es den Datentyp 'unsigned int'. Dann
musst du dir aber raussuchen welches Formatierzeichen der sprintf
für unsigned int haben will.
>> Hier der Code:
Du solltest dir wirklich ein C Buch zulegen.
Ist dir das ewige Code-Duplizieren nicht auf den Wecker
gefallen? Sowas macht man doch mit Arrays.
also ich habe es vorhin ja mit einem TerminalProgramm (Hyperterminal von
Microsoft) aber da kommen eben nicht alle werte an und außerdem manchmal
"minus"-zahlen.
das ist eben der fehler. Genauso kommt es aber auch in meinem
VB-Programm an, also kanns schon mal nicht am visualbasic-programm von
mir liegen, da ja hyperterminal das gleiche anzeigt.
schmeiss doch mal die sendx() Funktion raus. Die braucht keiner.
Und dann veränderst du dein Hauptprogramm so:
UCSRB |= (1<<TXEN); //Senden aktivieren
UCSRC |= (1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1); //
UBRRH = 00; //Baudrate einstellen 9600 bei 8 MHz
UBRRL = 51;
uart_putc( 'a' );
wandle(reg1);
uart_putc( 'b' );
wandle(ubergabe1);
uart_putc( 'c' );
wandle(reg2);
uart_putc( 'd' );
wandle(ubergabe2);
uart_putc( 'e' );
wandle(reg3);
uart_putc( 'f' );
wandle(ubergabe3);
uart_putc( 'g' );
wandle(reg4);
uart_putc( 'h' );
wandle(ubergabe4);
uart_putc( 'i' );
wandle(reg5);
uart_putc( 'j' );
wandle(ubergabe5);
uart_putc( 'k' );
wandle(reg6);
uart_putc( 'l' );
wandle(ubergabe6);
uart_putc( 'm' );
wandle(reg7);
uart_putc( 'n' );
wandle(ubergabe7);
uart_putc( 'o' );
wandle(reg8);
uart_putc( 'p' );
wandle(ubergabe8);
TCCR0=0;
kontrol=0;
}
und siehst mal nach, welche Werte denn kommen und welche
nicht.
> und außerdem manchmal> "minus"-zahlen.
Ja. Sagte ich doch schon warum das so ist.
PS: Und zieh die UART Initialisierung vor die Schleife.
Es reicht völlig, wenn der UART einmal bei Programmstart
initialisiert wird. Es gibt keinen Grund das jedesmal zu machen.
habe mal deine veränderung am code so reingeschrieben und geflasht.
folgendes kommt am Terminal nun an:
a0b0c0d0e0f0g0h0i0j0k0l0m0n0o142p-10330a0b0
nachdem ich die taste 0x7F gedrückt habe.
danke
Na ja. Sind doch alle da! Von 'a' bis 'p'!
Die negative kriegst du weg, indem du jetzt endlich mal
die Umstellung von 'int' zu 'unsigned int' machst.
Und dann musst du dich mal damit beschäftigen, warum ein
Teil der Werte 0 ist.
ok, also ich werde heute mal die "int" variablentypen mit "unsigned int"
ersetzen. Dann müsste das Problem mit dem vorzeichen vor den Zahlen
behoben sein :-)
danke!
Also. habe heute mal aus den "int" Datentypen "unsigned int" gemacht,
aber anscheinend erfolglos. Wenn ich mein Programm nun so laufen lasse,
wie Karl-Heinz mir vorgeschlagen hat, bringt er wieder die zeichen von
a-p im Terminal, jedoch immer noch die "-" -> vorzeichen.
Hier der Terminal-Ausdruck, nachdem alle Taster nacheinander gedrückt
wurden:
a213b30121c128d-12895e63f11358g12h30918i49j-11897k166l19707m233n-18894o1
42p3595a213b30121c128d-12895e63f11358g12h30918i49j-11
897k166l19707m233n-18894o158p3595
Hier nochmal der gesamte Code:
[ c ]
int main (void)
{
unsigned int ubergabe=0,ubergabe1=0,ubergabe2=0,ubergabe3=0,
ubergabe4=0,ubergabe5=0,ubergabe6=0,ubergabe7=0,ubergabe8=0;
unsigned int reg1=0,reg2=0,reg3=0,reg4=0,reg5=0,reg6=0,reg7=0,reg8=0,
kontrol=0;
DDRD =0xFF;
DDRB =0x00;
TCCR0 |= (1<<CS00); //Prescaler für Timer
UCSRB |= (1<<TXEN); //Senden aktivieren
UCSRC |= (1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1);
UBRRH = 00; //Baudrate einstellen 9600 bei 8 MHz
UBRRL = 51;
for(;;)
{
if (TIFR &(1<<TOV0)) //wenn generell Überlauf, erhöhe Variable
"uberlauf" um eins
{
ubergabe++;
TIFR = 1<<TOV0;
}
if (PINB==0xFE) //wenn Taste1 gedrückt wird, dann schreibe in Var
"reg1" den Zählerstand (TCNT0)
{ //und den momentanen Wert von Var "uberlauf" in
"uberlauf1"
reg1=TCNT0;
ubergabe1=ubergabe;
}
if (PINB==0xFD)
{
reg2=TCNT0;
ubergabe2=ubergabe;
}
if (PINB==0xFB)
{
reg3=TCNT0;
ubergabe3=ubergabe;
//bei Druck auf Taste3, Timer beenden (TCCR0=0)
}
//Speichert bis hierher bei verschiedenen Tastendrücken die
momentanen Überläufe (ubergabe1-3)
//sowie die momentanen Registerwerte (reg1-3)
if (PINB==0xF7)
{
reg4=TCNT0;
ubergabe4=ubergabe;
}
if (PINB==0xEF)
{
reg5=TCNT0;
ubergabe5=ubergabe;
}
if (PINB==0xDF)
{
reg6=TCNT0;
ubergabe6=ubergabe;
}
if (PINB==0xBF)
{
reg7=TCNT0;
ubergabe7=ubergabe;
}
if (PINB==0x7F)
{
reg8=TCNT0;
ubergabe8=ubergabe;
TCCR0=0;
kontrol=1;
}
if (kontrol==1)
{
/*
sendx();
wandle(reg1);
sendx();
wandle(ubergabe1);
sendx();
wandle(reg2);
sendx();
wandle(ubergabe2);
sendx();
wandle(reg3);
sendx();
wandle(ubergabe3);
sendx();
wandle(reg4);
sendx();
wandle(ubergabe4);
sendx();
wandle(reg5);
sendx();
wandle(ubergabe5);
sendx();
wandle(reg6);
sendx();
wandle(ubergabe6);
sendx();
wandle(reg7);
sendx();
wandle(ubergabe7);
sendx();
wandle(reg8);
sendx();
wandle(ubergabe8);
TCCR0=0;
kontrol=0;*/
uart_putc( 'a' );
wandle(reg1);
uart_putc( 'b' );
wandle(ubergabe1);
uart_putc( 'c' );
wandle(reg2);
uart_putc( 'd' );
wandle(ubergabe2);
uart_putc( 'e' );
wandle(reg3);
uart_putc( 'f' );
wandle(ubergabe3);
uart_putc( 'g' );
wandle(reg4);
uart_putc( 'h' );
wandle(ubergabe4);
uart_putc( 'i' );
wandle(reg5);
uart_putc( 'j' );
wandle(ubergabe5);
uart_putc( 'k' );
wandle(reg6);
uart_putc( 'l' );
wandle(ubergabe6);
uart_putc( 'm' );
wandle(reg7);
uart_putc( 'n' );
wandle(ubergabe7);
uart_putc( 'o' );
wandle(reg8);
uart_putc( 'p' );
wandle(ubergabe8);
kontrol=0;
}
}
}
[ /c ]
Außerdem: Wenn man nicht sofort den Taster 0x7F "zum Senden" loslässt,
kommt der String - logischerweise - sooft, bis man den Schalter
loslässt. Wie kann ich nur Einmal den String senden??
Vielen dank!
> Hier nochmal der gesamte Code:
Das ist nicht der geamte Code. Wo ist die Funktion wandle?
Nochmal: Deine Funktion wandle() kriegt jetzt einen
unsigned int! Das heist du musst das Formatierzeichen
im sprintf austauschen! %d ist für int, %u ist für
unsigned int.
> Wie kann ich nur Einmal den String senden??
Indem du eine Variable benutzt, in der du dir merkst,
dass die ganze Litanei schon gesendet wurde.
Ist die Variable auf 0 und kommt der Zustand 0x7F
dann sendest du die Daten und setzt die Variable auf 1
Wenn du das nächste mal 0x7F antriffst und diese Variable
ist auf 1, dann weist du, dass die Daten schon gesendet
wurden und brauchst nichts tun.
Jetzt musst du dir nur noch ein schönes Plätzchen suchen,
wo die Variable wieder auf 0 gesetzt wird.
Nachtrag:
Mit deiner kontrol Variablen hast du schon den Grundstock dafür.
Daraus kannst du diese Steuerung aufbauen.
Danke für die Code-Lösung, werde diese wohl auch so anwenden, ist mit
arrays wirklich viel einfacher. Trotzdem zeige ich nochmal meinen Code.
Die Vorzeichen habe ich nun wegbekommen. Jetzt geht es um ein
Verständnis-Problem:
Ich schicke ja nacheinander immer "reg", dann x und dann "ubergabe". Wie
kann es sein, dass die Zahlen im terminal so aussehen?
23x3998x239x1999x.....
| |
reg, uberlauf
Wie kann es mit meinem Code vorkommen, dass die Überläufe nicht
aufsteigend größer werden, da die "uberlauf"-variable ja eigentlich
hochzählen sollte und immer der momentane Wert in die "uberlauf1-8"
reingeschrieben werden sollen, die dann am terminal ausgegeben werden?
Es müsste doch ein aufsteigendes "uberlauf"-muster im terminal geben?
Macht es aber nicht
danke
EinSteigÄr wrote:
>> Ich schicke ja nacheinander immer "reg", dann x und dann "ubergabe". Wie> kann es sein, dass die Zahlen im terminal so aussehen?>> 23x3998x239x1999x.....> | |> reg, uberlauf> Wie kann es mit meinem Code vorkommen, dass die Überläufe nicht> aufsteigend größer werden, da die "uberlauf"-variable ja eigentlich> hochzählen sollte und immer der momentane Wert in die "uberlauf1-8"> reingeschrieben werden sollen, die dann am terminal ausgegeben werden?> Es müsste doch ein aufsteigendes "uberlauf"-muster im terminal geben?> Macht es aber nicht
Wie schnell taktest du deinen µC und wie schnell drückst du
die Tasten?
Ich geh mal von 4 Mhz aus.
d.h. der Timer zählt mit 4 Mhz, da der Prescaler 1 ist.
Bis zum Überlauf muss er bis 256 zählen. Das passiert
in 1 Sekunde 4000000 / 256 = 15625 mal
Ein unsigned int kann bis 65535 zählen. Da deine
ueberlauf Variable 15625 mal in der Sekunde erhöht wird,
ist dieser Zahlenbereich in knapp 4 Sekunden einmal durch,
dann beginnt ueberlauf wieder bei 0
Oder anders ausgedrückt, wenn du nicht innerhalb von 4
Sekunden (bei 4 Mhz Takt), alle Tasten der Reihe nach
drückst, siehst du einen Sprung. Wenn dein µC mit 16 Mhz
läuft, hast du entsprechend wendiger Zeit. Dann bist du in
knapp 1 Sekunde einmal rum.
Und dann hast du natuerlich noch das Problem, dass du
die ganzen Zaehler nie auf 0 zurücksetzt. Da du zwischen den
Zahlen aber immer nur x ausgibst, weist du in deiner Zahlenreihe
nie, wo denn ein neuer Messzyklus beginnt.
ich muss doch die zähler auch nicht auf null zurücksetzen, wenn ich in
meinem VB-Programm die Differenz (zeit-uberlaufe1,2 =
uberlauf2-uberlauf1)
oder?
EinSteigÄr wrote:
> ich muss doch die zähler auch nicht auf null zurücksetzen, wenn ich in> meinem VB-Programm die Differenz (zeit-uberlaufe1,2 => uberlauf2-uberlauf1)>> oder?
Setz einfach mal ein paar Zahlenwerte ein und du wirst sehen
was dann raus kommt.
also es funktioniert :) habe mal gaaanz schnell die taster nacheinander
gedrückt und habe gesehen, dass es aufsteigend funktioniert. Werde dann
entweder - wie karlheinz geschrieben hat - immer die werte auf 0
zurücksetzen oder einfach größere Datentypen für die Variablen
verwenden.
Danke!