Nicht angemeldet. · Kennwort vergessen · Registrieren

ac94imas
Mitglied seit 02/2014
4 Beiträge
Betreff: Klausur Juli 2013 (remote_control)
Hallo zusammen,

ich habe mich mal an die o.g. Programmieraufgabe herangewagt, und wollte mal fragen, ob da jemand mal drüberschauen könnte, ob das so passt, oder ob ich manches falsch / zu kompliziert gemacht habe. Ich hoffe, meine Kommentare helfen noch etwas weiter.
Und eine Frage bzgl. break() hab ich noch rot markiert.
Danke schonmal :)


#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <stdint.h>
#define LOOPS_PER_MS 50
#define NBLINK 5
static uint16_t muster[8] = {420,680,210,160,370,110,920,750};

/* Funktionsdeklarationen, globale Variablen, etc. */

void main (void);
void init (void);
void send (uint8_t button);
static int8_t tastendruck = 0;
static uint8_t maske = 0;


/* Unterbrechungsbehandlungsfunktion */

ISR(INT0_vect){
    maske = ~(0xff & PORTA);
        //maske hat an den Stellen 1 dessen Tasten gedrueckt wurden
    for(uint8_t i=0; i<8; i++){
         if(maske == (1<<i)){
            tastendruck = 1;
            // Fall dass nur ein Button gedrueckt wurde
        }
        tastendruck = -1;
    }
}

/* Funktion main */

void main (void){
   
    /* Initialisierung und lokale Variablen */

    init();

    /* Hauptschleife */
    while(1){

        /* auf Tastendruck warten */
        while(tastendruck == 0){
             //Energiesparmodus
            sleep_enable();
            sei();
            sleep_cpu();
            sleep_disable();
            cli();
        }

        /* Betaetigung von Tasten auswerten */
       
        if(tastendruck==1){
            for(uint8_t i=0; i<8; i++){
                if(maske == (1<<i)){
                     // Knopf i wurde dann gedrueckt
                    send(i);
                     break;
                    // Frage: ist hier break noetig? -> da tastendruck=1 ist, wurde ja nur ein Button gedrueckt und somit sollte die Schleife zuende laufen, ohne noch was auszuführen
                }
            }
         }
        // Fall dass mehrere Buttons gedrueckt wurden
        PORTB &= ~(1<<4);
         wait(1000);// rote Fehler-LED blinkt
        PORTB |= (1<<4);
     }
    /* Ende main */
}
    /* Funktion send
    zu Taste gehoerendes Muster mit Infrarot-LED senden */

    void send(uint8_t button){
         for(uint8_t i = 0; i < NBLINK; i++){
             PORTC &=~(1<<0); //Infrarot ein
             wait(muster[button]);
            PORTC |= (1<<0); //Infrarot aus
             wait(500);
        }
    }

    /* Initialisierungsfunktion */

    void init(void){
       
        DDRB |= (1<<4);
        PORTB |= (1<<4);
        DDRC |= (1<<0);
        PORTC |= (1<<0);
        DDRA = 0;
        PORTA = 0xff;
        DDRD &= ~(1<<2);
        PORTD |= (1<<2);
       
        GICR |= (1<<INT0);
       
        MCUCR &= ~(1<<ISC00);
        MCUCR |= (1<<ISC01);    //fallende Flanke
    }

    /* Wartefunktion */

    void wait(uint16_t ms){
        for(volatile uint16_t i = 0; i<(LOOPS_PER_MS*ms); i++){

        }
    }
ac94imas
Mitglied seit 02/2014
4 Beiträge
Achso und hier wäre noch die Aufgabenstellung :)

Aufgabe 2a: remote_control (30 Punkte)
Sie dürfen diese Seite zur besseren Übersicht bei der Programmierung heraustrennen!
Programmieren Sie eine Steuerung für eine Fernbedienung mit einem AVR-Mikrocontroller.
Die Fernbedienung hat 8 Tasten, eine Infrarot-LED und eine rote LED zur Anzeige von Fehlern.
Wird eine der Tasten gedrückt, wird durch Ein- und Ausschalten der Infrarot-LED in
einem bestimmten Muster ein Signal gesendet. Wird mehr als eine Taste gleichzeitig
gedrückt, leuchtet die rote LED zur Anzeige einer fehlerhaften Eingabe.
Im Detail soll Ihr Programm wie folgt funktionieren:
– Initialisieren Sie die Hardware in der Funktion void init(void);. Es sollen keine
Annahmen über den initialen Zustand der Hardware-Register getroffen werden. Das
Programm startet mit ausgeschalteten LEDs.
– Während desWartens auf eine Eingabe soll der Mikrocontroller in den Schlafmodus
wechseln.
– Wird eine der Tasten gedrückt, wird dadurch ein Interrupt ausgelöst. Welche Taste
jeweils gedrückt wurde, kann in der Unterbrechungsbehandlung im entsprechenden
Hardware-Register abgefragt werden. Wurde mehr als eine Taste gedrückt, soll die
rote Fehler-LED für eine Sekunde leuchten.
– Implementieren Sie das Senden in der Funktion void send(uint8_t button);. Hier
wird zuerst die Infrarot-LED für eine variable Dauer abhängig von der gedrückten
Taste eingeschaltet, danach wird die Infrarot-LED für 500ms ausgeschaltet.
Dieser Vorgang wird so oft wiederholt, wie es durch die Präprozessorkonstante
NBLINK vorgegeben ist. Die Einschaltdauer der Infrarot-LED wird pro Taste in einem
vorgegebenen Array muster festgelegt. Die Werte sind in Millisekunden angegeben.
– Implementieren Sie die Pausen unter Verwendung einer aktiven Wartefunktion
void wait(uint16_t ms);, die ms Millisekunden wartet. Ihnen steht eine Präprozessorkonstante
LOOPS_PER_MS zur Verfügung, die angibt, wieviele Schleifendurchläufe
einer Millisekunde entsprechen.
Information über die Hardware
Infrarot-LED:PORTC, Pin 0, eingeschaltet bei low-Pegel
- Pin als Ausgang konfigurieren: entsprechendes Bit in DDRC-Register auf 1
Fehler-LED:PORTB, Pin 4, eingeschaltet bei low-Pegel
- Pin als Ausgang konfigurieren: entsprechendes Bit in DDRB-Register auf 1
Tasten: PORTA, alle Pins
- Pin als Eingang konfigurieren: entsprechendes Bit in DDRA-Register auf 0
- die Leitungen verbinden den Pin jeweils mit Masse, es muss der interne Pullup-
Widerstand verwendet werden (entsprechendes Bit in PORTA-Register auf 1 setzen).
- Zustand kann durch Lesen des PINA-Registers abgefragt werden.
- Durch eine entsprechende Gatterschaltung wird durch einen Tastendruck auch die
Interrupt-Leitung mit Masse verbunden, so dass jede Taste den Interrupt auslösen kann.
Interrupt-Leitung:PORTD, Interrupt-Leitung an Pin 2
- externe Interruptquelle INT0, ISR-Vektor-Makros: INT0_vect
- die Leitung verbindet den Pin mit Masse, es muss der interne Pullup-Widerstand
verwendet werden (entsprechendes Bit in PORTD-Register auf 1 setzen).
- Aktivierung der Interruptquelle erfolgt durch Setzen des INT0-Bits im Register GICR.
Konfiguration der externen Interruptquelle 0 (Bits in Register MCUCR)

Interrupt 0         Beschreibung
ISC01 ISC00
0 0 Interrupt bei low Pegel
0 1 Interrupt bei beliebiger Flanke
1 0 Interrupt bei fallender Flanke
1 1 Interrupt bei steigender Flanke

Ergänzen Sie das folgende Codegerüst so, dass ein vollständig übersetzbares Programm
entsteht.
il66ifix
Mitglied seit 05/2011
110 Beiträge
HI

Wa sich aufd den ersten Blick so sehe: Der Ablauf bei der Schlaffunktion is in der Schleife richtig. Aber um dei Schleife rum fehlt das sei() und cli(). Da aknn dein µC schlfen gehn und nie wieder aufwachen wenns blöd kommt. tastendruck wird auch nie wieder auf null gesetzt (sondern nur +-1), das heißt, du schläfst einmal und dann nie wieder.
Überleg außerdem, ob die Variablen maske und tastendruck einen speziellen Modifier brauchen (Aufruf und Bearbeitung in der ISR).

Und dann fehlt die wait(..) bei den Deklarationen. main braucht man normalerweise nicht deklarieren, weil die immer da is (wie solls auch ohne gehn?).

Mehr seh ich grad net.
Schließen Kleiner – Größer + Auf diesen Beitrag antworten:
Prüfcode: VeriCode Gib bitte das Wort aus dem Bild ins folgende Textfeld ein. (Nur die Buchstaben eingeben, Kleinschreibung ist in Ordnung.)
Smileys: :-) ;-) :-D :-p :blush: :cool: :rolleyes: :huh: :-/ <_< :-( :'( :#: :scared: 8-( :nuts: :-O :troll:
Weitere Zeichen:
Gehe zu Forum
Powered by the Unclassified NewsBoard software, 20110527-dev, © 2003-8 by Yves Goergen