Nicht angemeldet. · Kennwort vergessen · Registrieren

muffdey
Mitglied seit 04/2012
12 Beiträge
Betreff: Klausur Juli 2014
Hallo zusammen,

Hier meine Lösung zur Aufgabe Juli 2014 2a) Kurzzeitwecker.

Für das Auslesen des Tasterzustandes habe ich für gedrückt: PIND & (1<<PIND2) benutzt und für "wieder losgelassen" !(PIND & (1<<PIND2)) benutzt. Ich bin mir nicht sicher ob das so funktioniert aber habe damit weitergearbeitet.

Aufgabenstellung

Schreiben Sie ein Programm für einen AVR-Mikrocontroller, das einen Kurzzeitwecker
implementiert. Durch Drücken und Halten des Tasters wird der Wecker in die Konfigurationsphase
versetzt. In dieser Phase wird mit einem Potentiometer die gewünschte Dauer eingestellt,
die auf einer Flüssigkristallanzeige angezeigt wird. Durch Loslassen des Tasters
wird die eingestellte Zeit heruntergezählt und nach deren Ablauf ein Weckton erzeugt.
Ihr Programm soll 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. Die Anzeige zeigt 0 Minuten und 0 Sekunden.
– Das Programm wartet nach dem Starten im Schlafmodus auf einen Tastendruck.
– Während der Taster gedrückt ist, soll in der Konfigurationsphase kontinuierlich
das Potentiometer mit der Bibliotheksfunktion uint16_t poti_read(void); ausgelesen
werden. Diese liefert einen 10-Bit-Wert zurück, welcher der gewählten
Dauer in Sekunden entspricht. Der aktuelle Wert wird auf der Anzeige dargestellt,
welche sich mit der Bibliotheksfunktion void display_show(uint8_t
minutes, uint8_t seconds); ansteuern lässt.
– Durch Loslassen des Tasters wird der aktuell eingestellte Wert übernommen und
die Countdown-Phase beginnt. Die noch verbleibende Zeit wird auf der Anzeige
jede Sekunde heruntergezählt.
– Der Weckton wird durch das Einschalten eines Tongebers für 500 ms erzeugt.
Danach wartet das Programm auf eine erneute Konfiguration.
Beachten Sie, dass nach einem Abbruch der Taster zuerst wieder losgelassen werden muss,
bevor die Konfigurationsphase erneut betreten werden kann.
Implementieren Sie die Wartezeit unter Verwendung einer aktiven Wartefunktion
uint8_t 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.
Wird während des Wartens erneut der Taster betätigt, wird die Wartezeit sofort abgebrochen
und die Funktion mit dem Rückgabewert ungleich 0 verlassen. Der Rückgabewert 0 zeigt an,
dass kein Tastendruck stattgefunden hat.


Mein Code:
  1. #include <avr/io.h>
  2. #include <avr/interrupt.h>
  3. #include <avr/sleep.h>
  4. #include <stdint.h>
  5.  
  6. #define LOOPS_PER_MS 50
  7.  
  8. uint16_t poti_read(void);
  9. void display_show(uint8_t minutes, uint8_t seconds);
  10.  
  11. //Funktionsdeklarationen, globale Variablen, etc.
  12. void init(void);
  13. void wait(uint16_t ms);
  14. volatile uint8_t taster;
  15. static uint16_t minutes;
  16. static uint16_t seconds;
  17. static uint16_t pot;
  18. //Unterbrechungsbehandlungsfunktion
  19. ISR(INT0_vect){
  20.  
  21.   taster=1;
  22.  
  23. }
  24.  //Funktion main
  25.  
  26. void main(void){
  27.  //Initialisierung und lokale Variablen
  28.   init();
  29.   display_show(0,0);
  30.   taster=0;
  31.  //gedrückt=0;
  32.  //Hauptschleife
  33.  while(1){
  34.     cli();
  35.     //Schlafphase
  36.     while(!taster){
  37.       sei();
  38.       sleep_cpu();
  39.       sleep_disable();
  40.       cli();
  41.     }   
  42.       //Konfigurationsphase
  43.    
  44.     while(taster==1 && (PIND & (1<<2))==0){ // Interrupt wurde ausgelöst und Taster wird immer noch gedrückt (PIND & (1<<2))==0
  45.       pot=poti_read(void)+1
  46.       minutes=pot/60;
  47.       seconds=pot%60
  48.       display_show(minutes, seconds);
  49.     }
  50.     //Countdownphase
  51.     while(taster==1 && (PIND & (1<<2))==1){ //Interrupt wurde ausgelöst und Taster wurde losgelassen (PIND & (1<<2))==1 oder !(PIND & (1<<2))==0. Geht das auch  mit Pin Maske? also while(taster==1 && PIND ==0x02)??
  52.       for(uint8_t i=0; i<pot; i++){
  53.         minutes=(pot-i)/60;
  54.         seconds=(pot-i)%60;
  55.         display_show(minutes, seconds);
  56.         wait(1000);
  57.         }
  58.         taster=0;
  59.        
  60.       }
  61.         //Tongeber auslösen
  62.     PORTB &= ~(1 << PB5);
  63.     wait(500);
  64.     PORTB |= (1 << PB5);
  65.  }  
  66. //Ende main
  67. }
  68.  
  69. //Funktion wait
  70. static void wait(uint16_t ms){
  71.  static uint16_t i= ms*LOOPS_PER_MS;
  72.  while(i--);
  73. }
  74.  
  75. //initialisierungsfunktion
  76. void init(void){
  77.   sleep_enable();
  78.   sei();
  79.  
  80.   PORTB |= (1<<5);
  81.   DDRB |= (1<<5);
  82.  
  83.   PORTD |= (1<<2);
  84.   DDRD &= ~(1<<2);
  85.  
  86.   GICR |= (1<<INT0);
  87.  
  88.   MCUCR &= ~(1<<ISCOO);
  89.   MCUCR |=  (1<<ISCO1);
  90. }

Ich bitte um Verbesserungen =) (davon wird es wohl viele geben)

Viele Grüße

Muffdey
Dieser Beitrag wurde am 20.03.2015, 15:05 von muffdey verändert.
il66ifix
Mitglied seit 05/2011
110 Beiträge
HI

Zu Zeile 51: Eine PIN-Maske würde gehen, wenn alle Einträge in diesem Register bekannt sind (hier wäre es null). Das weist du aber nicht. Deshalb ist die Abfrage des Einzelbits so schon richtig.

Zeile 42: Du hats ein sei() nach deiner Schlafphase vergessen. Und den MCUCR/GICR im Init sollte man vor den ersten sei() setzen, damits keine Probleme gibt. Sonst reagiert das während dem Init evtl auf sonstwas.

Außerdem solltest du mal genau überlegen, welche Attribut deine Variable i in der Wartefunktion haben muss und warum.
Und in de rAngabe steht: "...aktiven Wartefunktion uint8_t wait(uint16_t ms)". Das heißt, hier ist ein Rückgabewert gefordert. Der ist in den letzten beiden Sätzen auch angegeben. Wenn du diverse Sachen (zwiscen Zeile 44 und 60) verschiebst, kommst du nahe an die Lösung.

lg
il66ifix
muffdey
Mitglied seit 04/2012
12 Beiträge
Hey, Vielen Dank für deine Antwort.

-Also generell bei Taster und einzelnen Ports lieber den exakten Pin abfragen mit PINA & (1<<2) anstatt die gesamte Maske. Bei LED's sollte dann ja die Maske passen.

- Das sei() dann einfach am Ende der void init(){} setzen und nach der while(!taster){} die interrupts wieder mit sei() freigeben.

- Die wait funktion mit return werten schau ich mir mal an.

-Ich verstehe jetzt nur nicht genau was du mit den diversen Sachen zwischen Zeile 44 und 60 meinst.

Grüße

muffdey
Lars
Mitglied seit 08/2013
11 Beiträge
Kann man in diesem Beispiel eigentlich nicht mit einer beliebigen Flanke arbeiten? Und somit wird jeweils beim drücken sowie beim loslassen ein Interrupt ausgelöst und ich verändere entsprechend meine Taster variable und springe in ne neue while (taster==x) schleife oder habe ich da Grad nen kompletten Denkfehler drin?
Dieser Beitrag wurde am 24.03.2015, 14:46 von Lars verändert.
il66ifix
Mitglied seit 05/2011
110 Beiträge
Das mit Zeile 40 bis 60 könnte man unter //irgendwas setzen. Nur leider weis ich nicht mehr was da stand, weil du es jetzt wegeditiert hast :(

Durch Drücken und Halten des Tasters wird der Wecker in die Konfigurationsphase
versetzt. .... Durch Loslassen des Tasters wird der aktuell eingestellte Wert übernommen
Das is aus der Angabe. Is die Flanke jetzt noch beliebig?
Je nachdem was man in GCICR und MCUCR an Bits setzt, lassen sich die Flanken auswählen, die den Interrupt hervorrufen. Du kannst das also so proggen, dass dein Interrupt auf Drücken auslöst. Was du dann machst is dir überlassen. Du kannst natürlich zwischen zwei while-Schleifen im Hauptprogramm wechseln (oder mehr, is ne effiktive Methode für nen Zustandsautomat, bei dem du mit Knopfdruck den Zustand auswählst).
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