Ich traue diesem delay nicht. Mach eine LED in die Schleife mit PORTC^=(1<<PC0); wait_ms(1000). Die sollte dann im Sekundentakt blinken. Wenn du länger auf den Tasten bleibst zählt es weiter.
Hallo,
ich möchte mit einem Atmega8 2 Tasten abfragen und dann wenn die eine gedrückt wird eine Variable um 1 erhöhen, bzw. wenn die andere Taste gedrückt wird die Variable um 1 erniedrigen. Wenn die Variable dann den Wert 3 hat soll eine LED angehen. Dazu verwende ich folgenden C Code:
wait.hCode:#include <avr/io.h> #include "wait.h" int count = 0; void main() { DDRC = 0x07; while(1) { if(PINC & (1 << PC5)) { if(count < 15) { count++; wait_ms(500); } } if(PINC & (1 << PC4)) { if(count != 0) { count--; wait_ms(500); } } if(count == 3) { sbi(PORTC, 1); } else { cbi(PORTC, 1); } } }
Dieses Programm funktioniert auch wenn ich es am Computer simuliere (ich benutze das AVR Studio 4), aber wenn ich es dann auf den Mega8 lade und starte blitzt die LED unkontrolierbar auf und die Tasten bewirken gar nichts mehr (als Experimentierboard benutze ich das myAVR Board). Woran liegt das???Code:#define F_CPU 3686400ul #include <util/delay.h> void wait_ms(int miliSec) { _delay_loop_2(1*(F_CPU/(1000/4))*miliSec); } void wait_us(int mikroSec) { _delay_loop_2(1*(F_CPU/(1000000/4))*mikroSec); }
Ich traue diesem delay nicht. Mach eine LED in die Schleife mit PORTC^=(1<<PC0); wait_ms(1000). Die sollte dann im Sekundentakt blinken. Wenn du länger auf den Tasten bleibst zählt es weiter.
....Ich traue diesem delay nicht. ....
schau dir delay in der hilfe an von winavr-c und du verstehst sie dann.
wenn man mit diesen delay nicht richtig umgehen kann, sollte man die finger von lassen.
Ich traue diesem delay im Code von _R2D2 nicht, hätte ich besser schreiben sollen. Das die max. Verzögerung mit steigender Taktfrequenz kleiner wird, kann man oft genug lesen.
@_R2D2 Hast du ext. PullUp an den Tasten, die internen sind ja nicht aktiv.
Ich habe jetzt eine LED an PC0 angeschlossen und
in die Schleife eingebaut. Jetzt blinkt die LED, die an PC0 angeschlossen ist ca. 5 mal in der Sekunde. Wie kann ich die Delay-Funktionen jetzt so verändern, dass die LED auch wirklich nur ein mal in der Sekunde blinkt?Code:PORTC^=(1<<PC0); wait_ms(1000);
Ich habe die Delay-Funktionen aus dem Lehrheft LCD Programmierung von myAVR abgeschrieben, deswegen müssten sie doch eigentlich auch funktionieren?!
Hi,
500mS, bzw 1000mS sind definitiv zu viel,
Du rufst die Funktion _delay_loop_2() aus der delay_basic.h auf.
Dazu steht als Kommentar oben drüber:
"...,at a CPU speed of 1 MHz, delays of up to about 262.1
milliseconds can be achieved."
Bei 3,6864 MHz sind das entsprechend weniger, also:
262.1 / 3,6864 = 71 mS !
Mehr geht nicht mit diesen Funktionen.
Ich hab mal genauso dagesessen und mich gewundert mit der _delay_ms()
aus delay.h.
Was die da so richtig machen mit dem rumgecaste mit Mikrosekunden und 'ner extra "wait.h"
durchblicke ich auch nicht.
Ich würde die wait.h weglassen, dafür die util/delay.h includen.
Dann mußt Du die F_CPU 3686400ul im makefile angeben und schreibst statt wait_ms(500)
folgendes:
Wenn Du's eifach haben willst, setze nur wait_ms(50) undCode:uint8_t n; //das kommt vor dem while (1) { for (n=0; n<10; n++) _delay_ms(50); //Unterstrich bei _delay nicht vergessen.
laß das 10x durch 'ne Schleife laufen.
p.s.
die Fuses sind doch hoffentlich richtig gesetzt?
Ich habe wait_ms durch _delay_ms ersetzt so wie tholan geraten het. Das funktioniert jetzt echt gut.
Aber die LED, die an PC1 angeschlossen ist leuchtet weiterhin unkontolliert auf. Liegt das vielleicht daran, dass die Tasten PINC5, bzw. PINC4 mit dem Minuspol der Stromversorgung verbinden? Müsste das nicht der Pluspol sein?!
Ich bin eigentlich auch eher Einsteiger in C.
Ports werden allerdings allgemein "invertiert" abgefragt.
Dazu legt man, wie es hier auch gemacht wird zunächst die Ports im Datenrichtungsregister
auf 0, sprich Eingang. Damit werden die Eingänge hochohmig!
D.h. die reagieren evtl schon, wenn Du dich dem Eingangspin nur mit der Hand näherst.
Die kleinen Kapazitäten am Eingang sorgen dann dafür, daß der Eingang nach einer undefinierten
Zeit vielleicht wieder ausgeht.
Aus diesem Grund aktiviert man die Pullups und schaltet nach Null, also invertiert.
In Deinem Code sind die Pullups nicht aktiviert. Das macht man auch mit "PORTC ="
Also oben noch einfügen:
PORTC |= (1<< PC4) |(1<<PC5); //Aktivieren der Pullups
Dann mußt du natürlich die Pinabfrage auch invertieren:
Statt: if(PINC & (1 << PC5)) steht dann da: if (! (PINC & (1 << PC5)))
Dasgleiche in der anderen Bedingung. Dann werden Selbstverständlich noch die
Pins über den Taster nach Minus verbunden.
Ich hab auch noch nie mit sbi() und cbi() gearbeitet.
Normalerweise bemühe ich hier die üblichen Bitschiebereien.
Und wenn dann alles funktioniert, solltest Du Dir schnell abgewöhnen mit aktivem Warten zu arbeiten.
Blinken macht man eigentlich mit "Timer Overflow Interrupt"- ISRs.
Ich würde Dir das AVR- Tutorial von mikrocontroller.net empfehlen.
Das hat mir auch sehr geholfen.
.....Ich hab auch noch nie mit sbi() und cbi() gearbeitet. ......
ist eine schreiberleichterung und übesichtlich.
Lesezeichen