Not logged in. · Lost password · Register

yv21ipim
Member since Jan 2013
7 posts
Subject: 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
Member since May 2011
41 posts
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
Member since Apr 2012
12 posts
Falls hier zufällig jemand draufschaut,

Müsste bei der Initialisierungsfunktion nicht:

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

stehen?
killermiller
Member since May 2011
41 posts
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.
Close Smaller – Larger + Reply to this post:
Verification code: VeriCode Please enter the word from the image into the text field below. (Type the letters only, lower case is okay.)
Smileys: :-) ;-) :-D :-p :blush: :cool: :rolleyes: :huh: :-/ <_< :-( :'( :#: :scared: 8-( :nuts: :-O :troll:
Special characters:
Go to forum
Powered by the Unclassified NewsBoard software, 20110527-dev, © 2003-8 by Yves Goergen