Not logged in. · Lost password · Register
Forum: Grundstudium 2. Semester Informatik (GDI II) SPiC RSS
Klausur Oktober 2008
Stefan #1 -- for 2 months · 31 posts
Show profile · Link to this post
Subject: Klausur Oktober 2008
Ich habe versucht die Programmieraufgabe zu lösen und diese über den Mikrokontroller laufen zu lassen.
Natürlich musste ich einige Änderungen vornehmen.
Meiner Meinung nach sollte das so laufen.
Es treten aber zwei Fehler auf:
1.Wenn der Mikrokontroller aus der Schlafphase erwacht, dann setzt er speed nur 5000, wenn ich vorher z.B.
noch eine Warteschleife laufen lass.(In den Kommentaren Versuch mit der Warteschleife)
2.Bei Knopfdruck hat man das Gefühl, dass der Mikrokontroller sofort auf Vollspeed schaltet.

Was ist also falsch am Programm?

  1. #include <avr/io.h>
  2. #include <avr/interrupt.h>
  3. #include <avr/sleep.h>
  4. #include <led.h>
  5.  
  6. static volatile unsigned int speed = 5000;
  7. void init();
  8. void wait(unsigned int);
  9.  
  10. ISR(INT0_vect){
  11.     if(speed>1000){
  12.         speed -= 1000;
  13.     }
  14. }
  15.  
  16. void main(){
  17.     /*volatile unsigned int z;*/
  18.     int i = 0;
  19.     init();
  20.     sei();
  21.  
  22.     while(1){
  23.        
  24.         for(i=0;i<8;i++){
  25.            
  26.             int pin;
  27.            
  28.             PORTD &=~ (1<<7);
  29.             PORTC &=~ (1<<0);
  30.             PORTC &=~ (1<<1);
  31.             PORTC &=~ (1<<6);
  32.             PORTC &=~ (1<<7);
  33.             PORTA &=~ (1<<7);
  34.             PORTA &=~ (1<<6);
  35.             PORTA &=~ (1<<5);
  36.  
  37.             switch(i) {
  38.             case 0:
  39.             pin = 7;
  40.             break;
  41.             case 1:
  42.             pin = 0;
  43.             break;
  44.             case 2:
  45.             pin = 1;
  46.             break;
  47.             case 3:
  48.             pin = 6;
  49.             break;
  50.             case 4:
  51.             pin = 7;
  52.             break;
  53.             case 5:
  54.             pin = 7;
  55.             break;
  56.             case 6:
  57.             pin = 6;
  58.             break;
  59.             case 7:
  60.             pin = 5;
  61.             break;
  62.             }
  63.             switch(i) {
  64.                 case 0:
  65.                 PORTD |=  (1<<pin);
  66.                 break;
  67.                 case 1:
  68.                 PORTC |=  (1<<pin);
  69.                 break;
  70.                 case 2:
  71.                 PORTC |=  (1<<pin);
  72.                 break;
  73.                 case 3:
  74.                 PORTC |=  (1<<pin);
  75.                 break;
  76.                 case 4:
  77.                 PORTC |=  (1<<pin);
  78.                 break;
  79.                 case 5:
  80.                 PORTA |=  (1<<pin);
  81.                 break;
  82.                 case 6:
  83.                 PORTA |=  (1<<pin);
  84.                 break;
  85.                 case 7:
  86.                 PORTA |=  (1<<pin);
  87.                 break;
  88.             }
  89.  
  90.             cli();
  91.             wait(speed);
  92.             sei();
  93.         }
  94.  
  95.         cli();
  96.         if(speed<10000){
  97.             speed += 1000;
  98.         } else {
  99.             sleep_enable();
  100.             sei();
  101.             sleep_cpu();
  102.             sleep_disable();
  103.             /*z = 0;
  104.             while(z<50000){
  105.                 z++;
  106.             }*/
  107.             cli();
  108.             speed = 5000;
  109.             sei();
  110.         }
  111.  
  112.     }
  113. }
  114.    
  115. void init(){
  116.     DDRD |= (1<<7);
  117.     DDRC |= (1<<0);
  118.     DDRC |= (1<<1);
  119.     DDRC |= (1<<6);
  120.     DDRC |= (1<<7);
  121.     DDRA |= (1<<7);
  122.     DDRA |= (1<<6);
  123.     DDRA |= (1<<5);
  124.  
  125.     PORTD |= (1<<7);
  126.     PORTC &=~ (1<<0);
  127.     PORTC &=~ (1<<1);
  128.     PORTC &=~ (1<<6);
  129.     PORTC &=~ (1<<7);
  130.     PORTA &=~ (1<<7);
  131.     PORTA &=~ (1<<6);
  132.     PORTA &=~ (1<<5);
  133.  
  134.     DDRD &= ~0x04;
  135.     PORTD|= 0x04;
  136.     MCUCSR |= (1<<ISC00);
  137.     MCUCSR |= (1<<ISC01);
  138.     /*MCUCSR |= (1<<(ISC00|ISC01));*/
  139.     GICR |= (1<<INT0);
  140. }
  141.  
  142. void wait (unsigned int interval){
  143.     volatile unsigned int i = 0;
  144.     while(i<interval){
  145.         i++;
  146.     }
  147. }
This post was edited on 2010-07-25, 20:34 by morty.
Edit reason: C-Highlighting
morty (Administrator) #2 -- since Sep 2003 · 730 posts · Location: Erlangen
Show profile · Link to this post
Hab mal das Highlighting aktiviert.
Klingt so als ob dein Taster nicht ordentlich entprellt ist.
BTW: Int ist böse
Stefan #3 -- for 2 months · 31 posts
Show profile · Link to this post
Kann ich da was tun???
Das würde zumindest den Vollspeed erklären.
Aber nicht, dass nach dem Schlafdmodus die Variable speed nicht 5000 gesetzt wird.
Ist der code von der Idee her korrekt?
morty (Administrator) #4 -- since Sep 2003 · 730 posts · Location: Erlangen
Show profile · Link to this post
Prellen: Eine Warteschleife einbauen - wie du es gemacht hast. Im Interrupt sollte man das tunlichst nicht tun, aber manchmal muss dann doch der Pragmatismus siegen. Man sollte sich nur über die Folgen bewusst sein. Alternativ müsste man das SPiC-Board mal schnell mit 'nem Oszi anschauen. T0 sollte ja eigentlich entprellt sein.
Die Idee ist grundsätzlich richtig. Probleme sehe ich an folgenden Stellen:
  • Du wirst momentan von jedem beliebigen Interrupt geweckt wirst. Also auch von einem Timer. Den hast du hier zwar nicht, aber du kannst davon ausgehen, dass du im Normalfall mit mehr als einem Interrupt arbeiten wirst.
  • Was passiert, wenn der Taster während des wait() gedrückt wird?
Stefan #5 -- for 2 months · 31 posts
Show profile · Link to this post
Ja stimmt ich werde von jedem Interrupt geweckt.
Aber ich habe doch sowieso nur einen Interrupt aktiviert.
In der Übungsstunde wurde auch besprochen, dass es mit einer einfachen if-Bedingung
funktioniert, wenn nur ein Interrupt aktiv ist. Sonst muss man die while nehmen.
Stefan #6 -- for 2 months · 31 posts
Show profile · Link to this post
Ich denke die Zeitäderung wird lediglich erst in der nächsten wait aktiv.
Oder tritt dann noch ein Nebenläufigkeitsproblem auf?
Aber speed wird doch also aktueller Parameter übergeben.
Der formale Parameter ist jetzt interval.
Das wird vom Interrupt nicht verändert.
morty (Administrator) #7 -- since Sep 2003 · 730 posts · Location: Erlangen
Show profile · Link to this post
Überleg dir mal wann der Interrupt behandelt wird und was passiert, wenn man zwei mal hintereinander drückt.
Panos #8 -- for 2 months · 18 posts
Show profile · Link to this post
Ich denke die Zeitäderung wird lediglich erst in der nächsten wait aktiv.
Oder tritt dann noch ein Nebenläufigkeitsproblem auf?
Aber speed wird doch also aktueller Parameter übergeben.
Der formale Parameter ist jetzt interval.
Das wird vom Interrupt nicht verändert.

Was ist aber wenn bei deinem Programm, der Taster 2 mal in der wait gedrückt wird? Da die Interrupts gesperrt sind, wird nur einer gepuffert. Da speed als  mit call-by-value an die Funktion übergeben wird (wie du schon gesagt hast), kannst du in der wait die Interrupts zulassen und es werden alle Tastendrücke registriert.

Ich hätte auch mal eine Frage zur Aufgabe. In der Aufgabenstellung steht: Nach Erreichen einer minimalen Geschwindigkeit stoppt das Programm nach Ausschalten der LED an Pin 7. Ist mit Stoppen des Programms gemeint, dass es aus der main rausspringt und aufhört?
Stefan #9 -- for 2 months · 31 posts
Show profile · Link to this post
Wäre der Fehler dann behoben, wenn ich den Wert von speed vor Aufruf der wait in einer Variable sichere.
also:
cli();
wtime = speed;
sei();
wait(wtime);
morty (Administrator) #10 -- since Sep 2003 · 730 posts · Location: Erlangen
Show profile · Link to this post
Jup!
Panos #11 -- for 2 months · 18 posts
Show profile · Link to this post
Wäre es auch richtig, wenn ich vor dem Aufruf die Interrupts sperre, die Funktion mit der globalen Variable speed aufrufe und dann in der Funktion die Interrupts wieder freigebe?
morty (Administrator) #12 -- since Sep 2003 · 730 posts · Location: Erlangen
Show profile · Link to this post
Ja, aber sehr unschön. Man sollte Funktionen immer "Neutral" betreten und sie sollten sich auch neutral verhalten.
Stefan #13 -- for 2 months · 31 posts
Show profile · Link to this post
Noch mal zum Entprellen:
Wenn man das dann mit der Warteschleife realisiert, dann bekommt man beim Knopfdruck
eine Verzögerung des Lauflichts.
Kann es sein, dass der andere Button entprellt ist?
morty (Administrator) #14 -- since Sep 2003 · 730 posts · Location: Erlangen
Show profile · Link to this post
...der mit dem parallel geschalteten Kondensator ist entprellt.
Close Smaller – Larger + Reply to this post:
Verification code: VeriCode Please note the verification code from the picture into the text field next to it.
Smileys: :-) ;-) :-D :-p :blush: :cool: :rolleyes: :huh: :-/ <_< :-( :'( :#: :scared: 8-( :nuts: :-O
Special characters:
Go to forum
Unclassified NewsBoard 1.6.4 © 2003-5 by Yves Goergen
Page created in 680.4 ms (471 ms) · 133 database queries in 81.3 ms
Current time: 2010-09-10, 04:30:42 (UTC +02:00)