Nicht angemeldet. · Kennwort vergessen · Registrieren

yv21ipim
Mitglied seit 01/2013
7 Beiträge
Betreff: Klausur Juli 2012
Lösungsvorschlag - wäre nett wenn jemand mal drüberschaun kann ;)

Aufgabenstellung:
Schreiben Sie eine Steuerung für einen AVR-Mikrocontroller in einem Safe, der mit einem
8-stelligen Binärschlüssel gesichert ist. Der Code wird während der Eingabe durch LEDs
visualisiert.
Die Eingabe des Schlüssels erfolgt mit Hilfe von zwei Tastern, die entsprechend mit "0"
(Taster 0) und "1" (Taster 1) beschriftet sind. Jede der 8 Stellen des Schlüssels wird durch
den Benutzer nacheinander durch Drücken eines der beiden Taster eingegeben. Die 8 LEDs
visualisieren den eingegebenen Schlüssel, so dass die LEDs nach der Eingabe jeder Stelle
den bisher eingegebenen Binärcode anzeigen.
Nach der achten eingegebenen Stelle wird der Schlüssel mit einer gegebenen statischen Konstante SECRET verglichen. War die Eingabe erfolgreich, öffnet sich das Schloss für eine
Gesamtdauer von 5 Sekunden während alle LEDs mit einer Periodendauer von einer
Sekunde (1000 ms) blinken, dann schließt das Schloss wieder. Nach dieser Sequenz oder im
Fall eines falschen Schlüssels startet die Eingabe des Schlüssels wieder von vorne.
Im Detail soll Ihr Programm wie folgt funktionieren:
– Initialisieren Sie die Hardware in der Funktion void init(void).
– Das Programm startet mit allen LEDs ausgeschaltet, das Schloss ist geschlossen und
die Eingabe des Benutzers wird erwartet. Während des Wartens auf eine Eingabe soll
der Mikrocontroller jeweils in den Schlafmodus gehen.
– Implementieren Sie das Blinken der LEDs während der Öffnung des Safes unter Verwendung einer aktiven Wartefunktion void wait(uint16_t ms), die ms Millisekunden wartet. Ihnen steht eine PräprozessorkonstanteLOOPS_PER_MS zur Verfügung, die
angibt, wieviele Schleifendurchläufe gewartet werden muss, um eine Millisekunde
verstreichen zu lassen.
Information über die Hardware
LEDs: PORTA, Pins 0-7, Start bei LED 1 an Pin 0, eingeschaltet bei low-Pegel
- Pin als Ausgang konfigurieren: entsprechendes Bit in DDRA-Register auf 1
Schloss: PORTB, Pin 5, offen bei high-Pegel, geschlossen bei low-Pegel
- Pin als Ausgang konfigurieren: entsprechendes Bit in DDRB-Reg. auf 1
Taster: PORTD, "Null"-Taster (Taster 0) = Pin 2, "Eins"-Taster (Taster 1) = Pin 3
- Pin als Eingang konfigurieren: entsprechendes Bit in DDRD-Register auf 0
- externe Interruptquellen INT0 und INT1, ISR-Vektor-Makros:INT0_vect und INT1_vect
- Aktivierung der Interruptquellen erfolgt durch Setzen desINT0- bzw.INT1-Bits
im Register GICR.
- die Taster verbinden den Pin mit Masse, es müssen die internen Pullup-Widerstände
verwendet werden (entsprechende Bits in PORTD-Register auf 1 setzen).
- Konfiguration der externen Interruptquellen 0 und 1 (Bits in Register MCUCR)



/* Funtionsdeklaration, globale Variablen, etc. */
static void init(void);
static void wait(uint16_t ms);
volatile uint8_t event = 0;
volatile uint8_t taster = 0;

/* Unterbrechungsbehandlungsfunktionen */
ISR(INT0_vect) {
    event = 1;
    taster = 0;
}
ISR(INT1_vect) {
    event = 1;
    taster = 1;
}

/* Funktion main */
void main(void){
    /*Initialisierung und lokale Variablen */
    init();
    uint8_t position = 0;
    /* Hauptschleife */
    while(1) {
        /* Code-Eingabe */
        while(pos < 8) {
            cli();
            while(event == 0){
                sleep_enable();
                sei();
                sleep_cpu();
                sleep_disable();
                cli();
            }
            sei();
            portA |= (taster<<pos);
            pos++;
            event = 0;
        }
        /* Schloss oeffnen, naechster Durchlauf */
        if(!(SECRET ^ PORTA)) {
        uint8_t i = 0;
        PORTA = 0xff;
        PORTB |= (1<<5);
        while(i < 5){
            PORTA = ~(0xff);
            wait(500);
            PORTA = 0xff;
            wait(500);
            i++;
        }
        PORTB &= ~(1<<5);   
        }
        event = 0;
    }
}

/* Initialisierungsfunktion */
static void init(void) {
    DDRA |= 0xff;
    PORTA |= 0xff;
   
    DDRB |= (1<<5);
    PORTB &= ~(1<<5);
   
    DDRD &= ~((1<<2)|(1<<3));
    PORTD |= (1<<2)|(1<<3);
    MCUCR |= (1<<ISC01)|(1<<ISC11);
    MCUCR &= ~((1<<ISC11)|(1<<ISC01));
    GICR |= (1<<INT0)|(1<<INT1);
   
    sei();
}
/* Wartefunktion */
static void wait(uint16_t ms) {
    volatile uint16_t i = 0;
    while(i < ms*LOOPS_PER_MS) {
        i++;
    }
}
killermiller
Mitglied seit 05/2011
41 Beiträge
passt....
statt "if(!(SECRET ^ PORTA))" hätts auch n "if(PORTA==SECRET)" getan, aber geht ja so auch...
Rest müsste vom ersten Durchsehen her okay sein.
muffdey
Mitglied seit 04/2012
12 Beiträge
Falls hier zufällig jemand draufschaut,

Müsste bei der Initialisierungsfunktion nicht:

   MCUCR |= (1<<ISC01)|(1<<ISC11);
    MCUCR &= ~((1<<ISC00)|(1<<ISC10));

stehen?
killermiller
Mitglied seit 05/2011
41 Beiträge
Ja, stimmt, MCUCR muss so initialisiert werden, dass beide Interruptquellen bei fallender Flanke auslösen.
Konkrete Werte stehen im Datenblatt oder in der Angabe zur Klausur, aber die zweite Variante (muffdey's) ist wohl eher richtig,
zumal die erste (im langen Lösungsvorschlag) die selben Bits (ISC01 und ISC11 im MCUCR-Register) zuerst auf 1 und dann wieder auf 0 setzt.
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