Nicht angemeldet. · Kennwort vergessen · Registrieren

Musil
Mitglied seit 07/2013
10 Beiträge
Betreff: Klausur März 2012 Aufgabe 2a
Hi,
könnte da mal jemand drüber schauen, ob das so passt?
Ich bin mir beim Ausrechnen der Warteintervalle nicht so ganz sicher, ob man das so machen darf (automatisches Runden...) genauso wie beim Setzen der Register in der Initialisierung
wär super :)

  1. /*Funktionsdeklarationen, globale Variablen etc.*/
  2. volatile int8_t helligkeit;
  3. volatile int8_t led =1;
  4. static void init(void);
  5. static void wait(uint16_t us);
  6.  
  7. /*Funktion main*/
  8. void main(void){
  9.  
  10.     /*Initialisierung und lokale Variablen*/
  11.     sleep_enable();
  12.     uint16_t leuchtzeit;
  13.     uint16_t auszeit;
  14.     init();
  15.  
  16.     /*Hauptschleife*/
  17.     for(;;){
  18.    
  19.         /*Schlafen*/
  20.         cli();
  21.         while(helligkeit == 0)
  22.             sei();
  23.             sleep_cpu();
  24.             cli();
  25.         }
  26.         sei();
  27.         /*LED ansteuern*/
  28.  
  29.         leuchtzeit = (LOOPS_PER_US*512/10*helligkeit);
  30.         auszeit = LOOPS_PER_US*512-leuchtzeit;
  31.  
  32.         PORTA = ~(1<<(led-1));
  33.         wait(leuchtzeit);
  34.         PORTA = 0xff;
  35.         wait(auszeit);
  36.     }
  37. }      
  38. /*Ende der Funktion main*/
  39.  
  40. /*Initialisierungsfunktion*/
  41. static void init(void){
  42.     DDRA = 0xff;
  43.     PORTA = 0xff;
  44.     DDRD &= ~((1<<2)|(1<<0));
  45.     PORTD |= (1<<2)|(1<<3);
  46.     MCUCR |= (1<<ISC01)|(1<<ISC11);
  47.     MCUCR &= ~((1<<ISC00)|(1<<ISC10));
  48.     GICR |= (1<<INT0)|(1<<INT1);
  49.         sei();
  50. }
  51.  
  52. /*Wartefunktion*/
  53. static void wait(uint16_t us){
  54.    
  55.     for(volatile uint16_t i = 0; i<us; i++){}
  56.    
  57. }
  58.  
  59. /*Unberbrechungsbehandlung*/
  60. ISR(INT0_vect){
  61.    
  62.     if(helligeit == 0){
  63.         if(led<8){
  64.             led++;
  65.         }
  66.     }
  67.     helligkeit = (helligkeit+1)%11;
  68.  
  69. }
  70.  
  71. ISR(INT1_vect){
  72.  
  73.     if(helligkeit==1){
  74.         if(led>1){
  75.             led--;
  76.         }
  77.     }
  78.     helligkeit = (helligkeit-1)%11;
  79.        
  80. }
Dieser Beitrag wurde 2 mal verändert, zuletzt am 20.07.2013, 17:27 von Musil.
ingonör
Mitglied seit 05/2013
67 Beiträge
Ich schreibe die Aufgabe später selber mal und gebe dann meine Senf dazu!
ingonör
Mitglied seit 05/2013
67 Beiträge
Antwort auf Beitrag #1
Zitat von Musil am 19.07.2013, 19:35:
  1.         leuchtzeit = (LOOPS_PER_US*512/10*helligkeit);
  2.         auszeit = LOOPS_PER_US*512-leuchtzeit;
Es kann sein, dass deine 'auszeit' nicht stimmt. Ich berechne die ein wenig anders. Zuerst berechne ich quasi '512 - leuchtzeit' und multipliziere das mit LOOPS_PER_US.

Zitat von Musil am 19.07.2013, 19:35:
  1. /*Initialisierungsfunktion*/
  2. static void init(void){
  3.     DDRA = 0xff;
  4.     PORTA = 0xff;
  5.     DDRD &= ~((1<<2)|(1<<0));
  6.     PORTD |= (1<<2)|(1<<3);
  7.     MCUCR |= (1<<ISC01)|(1<<ISC11);
  8.     MCUCR &= ~((1<<ISC00)|(1<<ISC10));
  9.     GICR |= (1<<INT0)|(1<<INT1);
  10.         sei();
  11. }
Sieht eigentlich ganz gut aus. Ist wie bei mir.

Zitat von Musil am 19.07.2013, 19:35:
  1. /*Unberbrechungsbehandlung*/
  2. ISR(INT0_vect){
  3.    
  4.     if(helligeit == 0){
  5.         if(led<8){
  6.             led++;
  7.         }
  8.     }
  9.     helligkeit = (helligkeit+1)%11;
  10.  
  11. }
  12.  
  13. ISR(INT1_vect){
  14.  
  15.     if(helligkeit==1){
  16.         if(led>1){
  17.             led--;
  18.         }
  19.     }
  20.     helligkeit = (helligkeit-1)%11;
  21.        
  22. }

Ja, ehm. Hier habe ich ein paar Problemchen mit der Aufgabenstellung. Also wenn ich das richtig verstanden habe, gibt es 8 LEDs. Wir beginnen mit der 1. auf Stufe 1. Ist auf Stufe 0 geschaltet worden (also aus), wird die 2. LED aktiviert, sobald man wieder den Taster0 drückt. Ist man bei der 8. angelagt, springt man wieder auf die 1. LED. Bitte korrigiert mich, falls ich das falsch verstehe.
Wendet man den Aufgabentext aber so auf deine ISR an, dann stimmt das noch nicht so ganz. Ich vermisse auch den Sprung von der 8. wieder zurück auf die 1. LED.

Edit: Eine Frage: Bei dir sind init() und wait() als static deklariert. Ist das denn notwendig? Wenn ja, warum?

Anbei mal mein Code. Ist bis auf die ISR fast identisch:

  1. #include <avr/io.h>
  2. #include <avr/interrupt.h>
  3. #include <avr/sleep.h>
  4. #include <stdint.h>
  5. #define LOOPS_PER_US 42
  6.  
  7. /* Funktionsdeklarationen, globale Variablen, etc. */
  8. void wait(uint16_t);
  9. void init(void);
  10. volatile uint8_t stufe = 0;
  11. volatile uint8_t position = 0;
  12.  
  13. /* Funktion main */
  14. void main(void) {
  15.  
  16. /* Initialisierung und lokale Variablen */
  17.     init()
  18.    
  19. /* Hauptschleife */
  20.     while(1) {
  21.    
  22. /* Schlafen */
  23.         cli();
  24.         while(!stufe) {
  25.             sei();
  26.             sleep_cpu();
  27.             cli();
  28.         }
  29.         sei();
  30.        
  31. /* LED ansteuern */ 
  32.     while(stufe) {
  33.         PORTA = 0xff;
  34.         wait(512 * 1 - stufe / 10);
  35.         PORTA |= (1 << position);
  36.         wait(512 * stufe / 10);
  37.     }
  38.    
  39. /* Ende Funktion main */
  40.     }
  41. }
  42.  
  43. /* Initialisierungsfunktion */
  44. void init(void) {
  45.     sleep_enable();
  46.     sei();
  47.    
  48.     DDRA = 0xff;
  49.     PORTA = 0xff;
  50.    
  51.     DDRD &= ~((1 << PD2) | (1 << PD3));
  52.     PORTD |= ((1 << PD2) | (1 << PD3));
  53.    
  54.     MCUCR |= ((1<< ISC01) | (1 << ISC11));
  55.     MCUCR &= ~((1 << ISC00) | (1 << ISC10));
  56.    
  57.     GICR |= ((1 << INT0) | (1 << INT1));
  58. }
  59.  
  60. /* Wartefunktion */
  61. void wait(uint16_t us) {
  62.     volatile uint16_t i = us * LOOPS_PER_US;
  63.     while(i--)
  64.         ;
  65.  
  66. }
  67.  
  68. /* Unterbrechungsbehandlung */
  69. ISR (INT0_vect) {   
  70.     if (stufe == 0) {   
  71.         stufe = 1;
  72.         position = (position + 1) % 8;
  73.     } else if (stufe < 10) {
  74.         stufe = stufe++;
  75.     }
  76. }
  77.  
  78. ISR (INT1_vect) {
  79.     if (stufe > 0) {
  80.             stufe--;
  81.     }
  82. }
Dieser Beitrag wurde am 20.07.2013, 22:03 von ingonör verändert.
morty
SPiC-Meister
(Moderator)
Mitglied seit 05/2011
331 Beiträge
static: Nein ist nicht zwingend notwendig. Sollte aber bei allen Funktionen hingeschrieben werden, die nicht von einem anderen Modul benötigt werden (vermeidet ggf Probleme mit doppelt benannten Funktionen/Variablen und erlaubt dem Compiler mehr zu optimieren). Aber vor die globalen variablen sollte man auch ein static schreiben. Da sie in einem Interrupt verwendet werden umso mehr!

musli: So wie du die wait implementiert hast entspricht es nicht der Aufgabenstellung. -> Am besten immer erst die Funktionen implementieren, dann passiert das nicht.

ingnör: Schau die mal die Berechnung in Zeile 34 an - da ist noch ein Fehler drin.
ingonör
Mitglied seit 05/2013
67 Beiträge
Antwort auf Beitrag #3
Aus
  1.         wait(512 * 1 - stufe / 10);
wird
  1.         wait(512 * (1 - stufe / 10));


morty, du hast Adleraugen. ;)
morty
SPiC-Meister
(Moderator)
Mitglied seit 05/2011
331 Beiträge
Zitat von ingonör:
morty, du hast Adleraugen. ;)
Jahrelange Übung. Ist aber immer noch falsch. ;)
King-Chris
Mitglied seit 10/2012
31 Beiträge
Antwort auf Beitrag #3
Zitat von ingonör am 20.07.2013, 21:12:
/* Unterbrechungsbehandlung */
ISR (INT0_vect) {   
    if (stufe == 0) {   
        stufe = 1;
        position = (position + 1) % 8;
    } else if (stufe < 10) {
        stufe = stufe++;
    }
}

ISR (INT1_vect) {
    if (stufe > 0) {
            stufe--;
    }
}

Aber bei position = (position + 1) % 8;  wird doch immer 1 als Ergebnis rauskommen, da man am Ende durch 8 teilt. Den Schritt verstehe ich nicht.

Du wilst ja damit von der 8. LED wieder zur 1. springen, aber geht das wirklich einfach ohne if/else-Schleife ?
Dieser Beitrag wurde 2 mal verändert, zuletzt am 25.07.2013, 17:12 von King-Chris.
ingonör
Mitglied seit 05/2013
67 Beiträge
Antwort auf Beitrag #5
Zitat von ingonör am 23.07.2013, 11:57:
Aus
  1.         wait(512 * 1 - stufe / 10);
wird
  1.         wait(512 * (1 - stufe / 10));


Verdammte Axt! Und wie wäre es damit?

  1. wait((512 * (10 - stufe)) / 10)

Edit: Sorry, habe deinen Beitrag erst jetzt gelesen. Warum sollte bei der Modulo-Rechnung immer 1 rauskommen? Die spuckt in dem Fall Zahlen zwischen 0 und 7 aus.
Edit2: Ach jetzt check ich, was du meinst. Ja, so wie es gerade da steht ist das ziemlicher Quatsch! Ich schaue mir das später nochmal in Ruhe an. Ist jetzt auch schon ein paar Tage her!
ingonör
Mitglied seit 05/2013
67 Beiträge
Antwort auf Beitrag #7
Zitat von King-Chris:
Aber bei position = (position + 1) % 8;  wird doch immer 1 als Ergebnis rauskommen, da man am Ende durch 8 teilt. Den Schritt verstehe ich nicht.

So, das war natürlich Blödsinn. Ohne Abfrage kommt man nicht weit. Ich denke, so sollte es funktionieren:
  1. position = (++position == 8) ? 1 : position;
King-Chris
Mitglied seit 10/2012
31 Beiträge
So kompliziert :D ? Könntest dus nochmals kurz erklären, was da jetzt genau gemacht wird. Ich hätte für die Aufgabe leider auch einfach keine bessere Idee.
yv21ipim
Mitglied seit 01/2013
7 Beiträge
Betreff: weiter Lösungsvorschlag
/* Funktionsdeklarationen, globale Variablen, etc. */
static void init(void);
static void wait(uint16_t us);
static volatile uint8_t stufe = 0;
static volatile uint8_t position = 0;
/* Funktion main */
void main(void){
    /* Initialisierung und lokale Variablen */
    init();
    /* Hauptschleife */
    while(1){
        /* Schlafen */
        cli();
        while(!stufe){
            sei();
            sleep_enable();
            sleep_cpu();
            sleep_disable();
            cli();
        }
        /* LED ansteuern */
        while(stufe){
            sei();
            PORTA |= (1 << position);
            wait(stufe/10*512);
            PORTA = 0xff;
            wait(512*(1-stufe/10));
            cli();
        }
        sei();
    }
}
/* Ende Funktion main */
/* Initialisierungsfunktion */
static void init(void){
    DDRA |= 0xff;
    PORTA |= 0xff;
    DDRD &= ~((1 << PD2)|(1 << PD3));
    PORTD |= (1 << PD2)|(1 << PD3);
    MCUCR |= (1 << ISC01)|(1 << ISC11);
    MCUCR &= ~((1 << ISC00)|(1 << ISC10));
    GICR |= (1 << INT0)|(1 << INT1);
    sei();
}
/* Wartefunktion */
static void wait(uint16_t){
    volatile uint16_t i = 0;
    while(i < us * LOOPS_PER_US){
        i++;
    }
}
/* Unterbrechungsbehandlung */
ISR(INT0_vect){
    if((stufe <= 0)|(stufe >= 10)) {
        stufe = 1;
        position = (position++)%8;
    } else {
        stufe++;
    }
   
]
ISR(INT1_vect){
    if(stufe > 0) {
        stufe--;
    }
}
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