Hallo,
da ich nach längerer Suche (in meinem Programm sowol auch mit SuFu's)
nicht weitergekommen bin, wende ich mich nun einmal vertrauensvoll an
dieses Forum...
Ich bin momentan dabei ein kleines Testgerät zu entwickeln und arbeite
mich Schritt für Schritt dadurch. Dabei versuche ich immer einzelne
Bereiche nacheinander zu erstellen.
Nun will ich mich um mein Menü kümmern. Ich hab dazu n paar Sachen, auch
brauchbare gefunden und verzweifel nun an einem (vermulich recht
einfachem) Fehler.
Also- ich will so lange auf einen Taster drücken und dabei soll eine
Variable inkrementiert werden; solange bis ein bestimmter Wert erreicht
ist. Angezeigt werden soll das mit einer LED.
Hier das was sich mein Hirn so gedacht hat:
//----------------------------------------------------------------------
#define F_CPU 8000000
#include <avr\io.h>
#include <util\delay.h>
//----------------------------------------------------------------------
void wait_ms(int miliSec)
{
_delay_loop_2( 1*(F_CPU/(1000/4)) * miliSec); // 4 Zyklen
warteschleife
}
int main (void)
{
DDRB=0x0F; //B -> 4-7 Eingang, 0-3 Ausgang
DDRC=0xFF; //C -> Ausgang
PORTB=0xF0; //B -> 4-7 pullup
int a;
a=1;
do
{
PORTC=1;
if (!(PINB&0b00010000))
{
a=a++;
}
if (a==5)
{
PORTC=0;
}
}
while(1);
}
//======================================================================
Es passiert allerdings gar nichts.
Kann mir jmd sagen, wo mein Fehler liegt? Wäre recht praktisch =)
LG
du mußt die Taste natürlich entprellen!!!
Ob überhaupt was passiert (auch mit prellender Taste) siest du, wenn du
if (a >= 5) schreibst.
Viel Erfolg beim rantasten
>> a=a++;
Diese Schreibweise mit dem Post-Increment ist recht unüblich.
Anders geschrieben ist das:
a=a;
a++;
Bekannter sind die Schreibweisen:
a++;
oder
a=a+1;
Mit der Zeile
>> if (!(PINB&0b00010000)) a++;
wird a hochgezählt, solange der Taster gedrückt ist.
Zusammen mit dem anschliessenden
>> if (a==5)
ist das eher ein Reaktionstest.
Die Taste muss losgelassen werden, wenn a==5 ist. Nur dann wird der Code
>> PORTC=0;
dauerhaft (in jedem Durchlauf) ausgeführt. Die Chancen dafür stehen
schlecht... :-o
Denn beim nächsten Durchlauf der while()-Schleife wird
>> PORTC=1;
gesetzt, a wird 6, und
>> if (a==5)
nicht mehr ausgeführt.
So, danke erstmal für die schnellen Antworten.
Ich weiß schon, warum ich eigentlich Hardware prepheriere.. ;)
Aber ich denke mal nichts ist unmöglich, da muss ich nun einfach mal
durch- und schaden kanns auch nicht.
Mal schaun, wenn ichs weiterhin nicht schaffe, meld ich mich wieder...
ansosnten spätestens beim I2C- Bus...
LG
So, ich hab noch ein wenig rumprobiert. Aber einen Fehler habe ich
immernoch... leider...
Vielleicht kann mir ja wieder jemand helfen, ich find den einfach
nicht...
Hier meine Main-Funktion:
//----------------------------------------------------------------------
-----
// Main-Funktion
//----------------------------------------------------------------------
-----
int main (void)
{
int a; //Variable fürs in/dekrementieren
wait_ms(200);
lcd_init(); //LCD initialisieren
a=0; //Variable bei "0" beginnen lassen
do
{
if (!(PINC&0b00000010)) // wenn Taster an pin c2 gedrückt
wird, variable um "1" erhöhen
{
wait_ms(200);
if (!(PINC&0b00000010))
a++;
}
if (!(PINC&0b00001000)) //wenn Taster an pin c4 gedrückt
wird, variable um "1" verringern
{
wait_ms(200);
if (!(PINC&0b00001000))
a--;
}
}
while (a==1); //a ist 1, ausgabe "automatisch"
{
autom();
}
while (a==2); //a ist 2, ausgabe "manuell"
{
manu();
}
while (a==3); //a ist 3, ausgabe "konfiguration"
{
konfi();
}
while (a>=4); //a größer 4, ausgabe "fehler"
{
nein();
}
while (1); // Mainloop
return 0;
}
So.. so habe ich mir das gedacht. Natürlich gehört noch mehr zu dem
programm, aber ich denke dass ich den fehler in der mainfunktion habe...
Weil- nach dem Brennen des Programmes wird direkt "fehler" angezeit.
Mann kann (denke mal durch die Trägheit des LCD's) noch kurz erahnen,
dass erst noch was anderes angezeigt wird- daraus schließe ich, dass die
variable direkt hochgezählt wird.... nur- warum?
Vielen Dank schonmal für eure Mühen :)
LG
Ich gehe mal davon aus, das hochgezählt wird, ohne das du eine Taste
drückst???
Taster sind gegen GND???
PullUps an???
Die Tasten sind immer noch nicht entprellt, bei Tastendruck wirst du
immer "irgendwo" (bei a++ im "ERROR") landen.
Viel Erfolg!!
Hallo,
> if (!(PINC&0b00000010)) // wenn Taster an pin c2 gedrückt> ...> if (!(PINC&0b00001000)) //wenn Taster an pin c4 gedrückt
Du fragst PC1 und PC3 ab, nicht PC2 und PC4, wie Du im Kommentar
schreibst. Gibt es Pull-ups (ich sehe keine Initialisierung der internen
Pull-ups)? Schaltet Dein Taster nach GND oder nach Vcc?
Gruß
risu
Ja, Taster sind gegen GND und pullups auch an... und ja, es word gezählt
ohne dass ich eine Taste drücke...
DDRD=0xFF; //D -> Ausgang
DDRB=0x0F; //B -> 0-3 ausgang, 4-7 eingang
DDRC=0x00; //C -> Eingang
PORTD=0;
PORTB=0xF0; //B -> 0-3 ---, 4-7 pullup
PORTC=0xFF; //C -> 0-7 pullup
Dann sollte ich mich mal schleunigst um die entprellung kümmern!
@risu:
Und ich hab mich versehen, ich meinte pin 1 und pin 3... sry hab eben
auch nochmal nachgemessen, 1 & 3!
Ja, ich hab nicht das ganze Programm gepostet, ich werds mal als Anhang
dazustellen...
Hallo,
benutzt Du einen C++ Compiler? In der Überschrift schreibst Du
"C-Programm", dann folgen aber verschiedene Definitionen von lcd_write()
(mit jeweils unterschiedlichen Parametern), was C++ typisch ist.
Hier ist eine Deiner do-while-Schleifen:
1
do
2
{
3
if(!(PINC&0b00000010)){
4
// ....
5
}
6
if(!(PINC&0b00001000)){
7
//....
8
}
9
}
10
while(a==1);
Aus der Formatierung Deines Programm schließe ich, dass Du das gar nicht
so auffasst... Aus der Struktur Deines Programms kann ich nicht
entnehmen, was Du eigentlich versuchst.
Gruß
risu
Ich hatte eine Vorlage geladen (fürs LCD) und mich dann nicht weiter um
die Überschrift gekümmert...
Was ich da mit der do-while-Schleife machen will:
Ich will eine Variable je nach Tastendruck verändern, also entweder
erhöhen oder verringern.
Je nach Variablenwert soll dann auf dem Display dann eine Ausgabe
erscheinen.
Auf diese Art und Weise versuche ich ein Menü zu erzeugen. Und dann je
nach Variablenwert und einem "Enter-Taster" ein Programm ausführen, aber
das hab ich da noch nicht drin... erstmal will ich die Anzeige
vernünftig hinbekommen...
Hallo,
schau Dir Deine do-while-Schleife noch einmal genauan. Die Schleife wird
verlassen, sobald "a ungleich 1"! Das heißt, ohne Tastendruck werden
immer sofort nach Programmstart alle Ausgabefunktionen hintereinander
aktiviert. Schließlich bleibt die zu "nein()" gehörige Ausgabe auf dem
LCD stehen (die anderen Texte verschwinden zu schnell, um sie zu
erkennen), und dann wird immer nur noch "while (1);" abgearbeitet. Ohne
Tastendruck wird die Variable "a" also nie erhöht! Der Fehler liegt in
der fehlerhaften Struktur Deines Programms. Ich hatte mit meinem vorigen
Posting versucht, Dich dazu zu bringen, diesen Fehler selbst zu
erkennen.
Ich schlage vor, Du klemmst Dich erstens hinter ein Tutorial oder Buch
zu C und zu dessen elementaren Strukturen; sonst stolperst Du immer
wieder über solche Probleme. Die Verzögerung von 200 ms bei der
Tastenabfrage ist ein sehr unschöner Kompromiss. Als zweiten Schritt
rate ich Dir, Du suchst hier im Forum nach "entprellen" und siehst Dir
insbesondere den Code zum Beitrag
Beitrag "Tasten entprellen - Bulletproof" an. Das ist nicht die allein
seligmachende Methode (und anfangs nicht leicht verständlich), aber Du
kannst daraus lernen, Deinen eigenen Code zu schreiben.
Viel Erfolg!
Gruß
risu
while (a==2); // auch nicht erfüllt !
Ist das nicht egal was in der Bedingung steht wenn da sowieso nur eine
leere Anweisung folgt.
Oder was soll das ;
Hi skua,
> Ist das nicht egal was in der Bedingung steht> wenn da sowieso nur eine leere Anweisung folgt.
Nein: wäre die Bedingung erfüllt, bliebe das Programm in dieser (dann
Endlos-)Schleife! Das ";" ist eins der Probleme in der Programmstruktur
des OP.
Gruß
risu
Ja ich denke ich sollte mal ein bisschen mehr im Tutorial lesen.. ;)
Und die Sache mit dem Entprellen- da muss ich was dran tun, ich denke
ich werd zusehen dass ich das per Hardware mache... frisst alles soviel
Speicher... (ich habs eben geschafft mit den ganzen Schleifen den
Speicher voll zu bekommen :( )
Ich weiß, ich denke nicht unbedingt einfach.. und hab da auch einige
Probleme beim Programmieren mit! Das ist nichts neues... ;)
Aber, ich habs geschafft. Also das hinzubekommen was ich machen will...
das ist wahrscheinlich noch stark verbesserungswürdig, auch gehts
wahrscheinlich noch viel, viel einfacher. Aber dazu machts mans ja, ums
zu lernen...
Trotzdem danke für Anregungen und Tipps! =)
LG
@risu
Hast natürlich recht bin wohl noch nicht richtig wach.
(c kann ich eh nicht so toll eher pascal)
@lordhelmchen
Am besten
1. Programm komplett entsorgen
2. Alle Ausdrucke vernichten
3. C Buch lesen
4. 3 Tage angeln gehen
5. Programm neu schreiben
oder so in der art
mindestens aber 1. und 5.
hat bei mir schon Wunder gewirkt.
Hi,
freut mich, dass Du nicht sauer bist über die Tipps! Statt
Hardware-Entprellung nimm einen Timer-Interrupt, wenn Du noch einen frei
hast. Dann die Tasten periodisch (z.B. alle 10 ms) abfragen und, falls
ein Tastenwert 2-3 mal hintereinander "EIN" ist, eine Zustandsvariable
(nicht vergessen, dass die volatile sein muss) setzen, die dann vom
(sonst eher kurzen) Code in "main()" ausgewertet wird.
Solltest Du Dich für eine Hardware-Lösung entscheiden, nimm nicht nur
eine R/C-Kombination, sondern eine dieser Schaltungen (
http://www.geocities.com/thetonegod/debounce/debounce.html ) oder gleich
eine integrierte Schaltung zum Entprellen (z.B. MC14490 {
http://www.onsemi.com/pub_link/Collateral/MC14490-D.PDF }für 6
Schalter.)
Viel Erfolg!
risu
Aber eine Frage habe ich da gerade mal noch...
Wie kann ich eine Variable, welche in der Mainschleife "bearbeitet"
wird, aufm Display ausgeben?
Wenn ich die gleich Variable in dem Unterprogramm zum schreiben auf dem
Display definiere, passiert gar nichts.
Ich hab das auch mal versucht, indem ich "WERT z" im Header definiert
habe, und dann versucht habe in der mainschleife der Variablen "z" einen
Wert zu geben und dann auf dem Display "lcd_write(WERT);" die Variable
wieder auszugeben... was aber auch nicht geht...
Hast ne Idee bzw ne Ahnung wo ich nachlesen kann??
LG
Da macht er es oben so schön, in dem er die Frage mit kompletten
Quellcode spickt und dann kommt er jetzt an mit einem
> Ich hab das auch mal versucht, indem ich "WERT z" im Header definiert> habe, und dann versucht habe in der mainschleife der Variablen "z" einen> Wert zu geben und dann auf dem Display "lcd_write(WERT);" die Variable> wieder auszugeben...
TzzTzzTzz
Aber lies mal:
http://www.mikrocontroller.net/articles/FAQ#Wie_kann_ich_Zahlen_auf_LCD.2FUART_ausgeben.3F
Okok... ich dachte ich spare mir das und schreib nur was ich gemacht
hab.
Aber hast recht... anbei also der Quellcode...
Ich hab das gerade da nachgelesen, hilft mir aber nicht so wirklich
(oder ich les nict richtig... -.-). Aber ich les es nochmal...
Aber ich glaub ich kann so langsam n neues Topic aufmachen...oder kann
man ein bestehendes umbenennen??
LG
> Aber ich glaub ich kann so langsam n neues Topic aufmachen...oder kann> man ein bestehendes umbenennen??
Umbenennen kann ein normaler User wohl nicht. Die Entscheidung alter
Thread oder neuer ist nicht einfach. Ich tendiere eher dazu weniger neue
Threads aufzumachen bzw. mag es beim Lesen eher gerne zusammenhängend.
Also es geht um diesen Ausschnitt:
1
#define WERT z
2
3
voidautom()
4
{
5
intz;
6
7
lcd_goto(1,1);
8
lcd_write("Autotest ");
9
lcd_goto(2,1);
10
lcd_write(WERT);
11
}
Für den Ausschnitt trifft 100% die Antwort in dem oben verlinkten
FAQ-Abschnitt zu.
Du kannst der Funktion lcd_write(), die einen String erwartet (wie bei
lcd_write("Autotest "); auch verwendet), keine Zahl (WERT aka z)
vorwerfen. Die Zahl muss vorher in einen String umgewandelt werden!
So... die Endung macht mein "myAVR Workpad" automatisch... bislang hatte
ich keine Probleme damit...
So... das mit der Ausgabe funktioniert schonmal soweit, danke.
Mittlerweile glaube ich auch dass ich das einigesmaßen begriffen habe!
=)
Aber- ein Problem hab ich dennoch.
Ich habe ja den Wert, den ich ausgeben will, in der Mainschleife. Und
den Wert muss ich ja in die Schleife bekommen, in der die Ausgabe fürs
LCD steht. (Später sollen Heizwerte/ Adressewerte vom I²C ausgegeben
werden, dafür muss ihc dass dann ja nur noch anpassen)
Daher meine Frage- wie bekomme ich das hin dass der Wert von der einen
in die andere Schleife kommt?!? Da hängts bei mir mal wieder...
LG
Scheint mir, als ob ich das geschafft habe...
ich hab am Anfang "uint8_t WERT;" definiert... und "WERT" lasse ich
ausgeben und auch den Wert annehmen, den ich ausgeben will... =)
Hallo aller seite,
ich muss einen Programm schreiben, der beim erste tasten drück den Licht
an der Led langsam ausschält und beim zweite mal langsam auschält, ich
habe gerade mit dem AVR STK500 angefagen und benutze eine atmega8515
device, hier ist der code die ich geschrieben hebe´, die leider nicht
geht,
Warum !?!?
kann jemand mir helfen!!!
#define F_CPU 8000000
#include <avr\io.h>
#include <util\delay.h>
//Diese Funktion lässt den Controller
//"ms" Millisekunden warten.
//Die while-Schleife wird so oft durchlaufen,
//wie der Funktion übergeben wurde.
//Bei jedem Duchlauf wir noch 1ms gewartet.
void sleep_ms(uint16_t ms)
{
while(ms)
{
ms--;
_delay_ms(1);
}
}
int main (void)
{
// Hardware einstellen
DDRB=0x0F; //B -> 4-7 Eingang, 0-3 Ausgang
DDRD=0xFF; //C -> Ausgang
PORTB=0xF0; //B -> 4-7 pullup
PORTD = 1; // low-active LED AUS
// Hauptarbeitsschleife
do
{
// Eingabe
if (!( PINB & 0b00010000 )) // low-active TASTER an PB4 abfragen
{
PORTD = 0; // low-active LED AN
pwm_started();
}
else
{
PORTD = 1; // low-active LED AUS
}
} while(1);
}
void pwm_started()
{
//uint8_t LEDstat;
OCR0AL = PULSE_WIDTH; //Load Pulse width
OCR0AH = 0;
PORTB = 0xff; // enable pull-ups for inputs, set outputs
high, Pin LED auf 1 setzen
DDRB |= (1<<5); //PortB.5 as o/p
TCCR0A = (1<<WGM00)|(1<<COM0A1); // PWM, phase correct, 8 bit.
TCCR1B = (1<<CS01) |(1<<CS00); // set clock/prescaler 1/64 ->
enable counter
for(PWMcounter=0; PWMcounter<PULSE_WIDTH; PWMcounter++)
LEDstat ++;
PORTB = LEDstat;
}
Warum hängst du deine Frage an einen anderen Beitrag an?
Du solltest doch eher einen neuen Thread anfangen.
Lies doch bitte auch mal Formatierung im Forum
> OCR0AL = PULSE_WIDTH; //Load Pulse width> OCR0AH = 0;
Die Schreibreihenfolge ist falsch! Es muss zuerst das High-Byte
geschrieben werden. Abgesehen davon bietet AVR-GCC-C die Möglichkeit,
diese Doppelregister als ganzes zu verarbeiten, so dass der
Programmierer sich nicht um die Reihenfolge kümmern muss.