- Akku Tests und Balkonkraftwerk Speicher         
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 14

Thema: Atmega8 spinnt

  1. #1
    Erfahrener Benutzer Roboter Experte Avatar von BurningWave
    Registriert seit
    22.12.2007
    Ort
    nahe Stuttgart
    Alter
    30
    Beiträge
    656

    Atmega8 spinnt

    Anzeige

    Praxistest und DIY Projekte
    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:

    Code:
    #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);
    		}
    	}
    }
    wait.h
    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);
    }
    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???

  2. #2
    Erfahrener Benutzer Robotik Visionär Avatar von Hubert.G
    Registriert seit
    14.10.2006
    Ort
    Pasching OÖ
    Beiträge
    6.220
    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.
    Grüsse Hubert
    ____________

    Meine Projekte findet ihr auf schorsch.at

  3. #3
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    14.01.2008
    Beiträge
    164
    ....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.

  4. #4
    Erfahrener Benutzer Robotik Visionär Avatar von Hubert.G
    Registriert seit
    14.10.2006
    Ort
    Pasching OÖ
    Beiträge
    6.220
    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.
    Grüsse Hubert
    ____________

    Meine Projekte findet ihr auf schorsch.at

  5. #5
    Erfahrener Benutzer Robotik Visionär Avatar von Hubert.G
    Registriert seit
    14.10.2006
    Ort
    Pasching OÖ
    Beiträge
    6.220
    @_R2D2 Hast du ext. PullUp an den Tasten, die internen sind ja nicht aktiv.
    Grüsse Hubert
    ____________

    Meine Projekte findet ihr auf schorsch.at

  6. #6
    Erfahrener Benutzer Roboter Experte Avatar von BurningWave
    Registriert seit
    22.12.2007
    Ort
    nahe Stuttgart
    Alter
    30
    Beiträge
    656
    Ich habe jetzt eine LED an PC0 angeschlossen und

    Code:
    PORTC^=(1<<PC0);
    wait_ms(1000);
    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?

    Ich habe die Delay-Funktionen aus dem Lehrheft LCD Programmierung von myAVR abgeschrieben, deswegen müssten sie doch eigentlich auch funktionieren?!

  7. #7
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    06.05.2005
    Ort
    Berlin
    Beiträge
    212
    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:
    Code:
    uint8_t n;  //das kommt vor dem  while (1) {
    for (n=0; n<10; n++)
    	_delay_ms(50); //Unterstrich bei _delay nicht vergessen.
    Wenn Du's eifach haben willst, setze nur wait_ms(50) und
    laß das 10x durch 'ne Schleife laufen.
    p.s.
    die Fuses sind doch hoffentlich richtig gesetzt?

  8. #8
    Erfahrener Benutzer Roboter Experte Avatar von BurningWave
    Registriert seit
    22.12.2007
    Ort
    nahe Stuttgart
    Alter
    30
    Beiträge
    656
    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?!

  9. #9
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    06.05.2005
    Ort
    Berlin
    Beiträge
    212
    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.

  10. #10
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    14.01.2008
    Beiträge
    164
    .....Ich hab auch noch nie mit sbi() und cbi() gearbeitet. ......

    ist eine schreiberleichterung und übesichtlich.

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Solar Speicher und Akkus Tests