Not logged in. · Lost password · Register

Baum
Member since Jul 2013
8 posts
Subject: Klausur April 2009
Hallo,

kann jemand diese Aufgabe korrigieren (oder zumindest ein paar Teile davon). Hab leider keine Möglichkeit das Programm zu testen, von daher wäre ein feedback sehr hilfreich.

  1. /*Funktionsdeklarationen, globale Variablen etc.*/
  2. void init(void);
  3. void showSnake(int, unsigned char);
  4. void active_wait(volatile unsigned int);
  5. volatile unsigned int len =1;
  6. volatile uint8_t taster;
  7. volatile int pos;
  8.  
  9.  
  10. /*Unterbrechungsbehandlungsfunktion*/
  11. ISR(INT0_vect){
  12.  
  13.     taster++;
  14. }
  15.  
  16.  
  17. /*Funktion main*/
  18. void main(void){
  19.     /*Initialisierung*/
  20.     init();
  21.     sleep_enable();
  22.    
  23.    
  24.     /*Hauptschleife*/
  25.     for(;;){
  26.         /*ein Snake Umlauf*/
  27.         showSnake(pos, len);
  28.         active_wait(5000);
  29.         pos = (pos+1)%6;
  30.         /*Vorbereitung des nächsten Umlaufs bzw. Schlafen*/
  31.         if(pos==0){
  32.             len++;
  33.         }
  34.         cli();
  35.         if(len-taster>0){
  36.             len-=taster;
  37.         } else {
  38.             len = 1;
  39.         }
  40.         taster =0;
  41.         while(len == 6){
  42.             sei();
  43.             sleep_cpu();
  44.             cli();
  45.             pos = 0;
  46.             len = 1;
  47.             if(taster != 0){
  48.                 taster = 0;
  49.                 break;
  50.             }
  51.         }
  52.         sei();
  53.        
  54.     }
  55. }
  56. /*Ende der Funktion main*/
  57.  
  58. /*Funktion init*/
  59. void init (void){
  60.     DDRB |= (1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5);
  61.     PORTB |= (1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5);
  62.     DDRD &= ~(1<<2);
  63.     PORTD |= (1<<2);
  64.     GICR |= (1<<INT0);
  65.     MCUCR |= (1<<ISC01);
  66.     MCUCR &= ~(1<<ISC00);
  67. }
  68. /*Ende der Funktion init*/
  69.  
  70. /*Funktion active_wait()*/
  71. void active_wait(volatile unigned int len){
  72.  
  73.     for(volatile uint16_t i =0; i<len; i++){}
  74.  
  75. }
  76. /*Ende der Funktion active_wait()*/
  77.  
  78. /*Funktion showSnake()*/
  79. void showSnake(int pos, unsigned char len){
  80.     PORTB |= (1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5);
  81.     for(uint8_t i = 0; i<len; i++){
  82.         PORTB &= ~(1<<((pos+6-i)%6));
  83.     }
  84.  
  85. }
  86. /*Ende der Funktion showSnake()*/
This post was edited on 2013-07-20, 15:18 by Baum.
ingonör
Member since May 2013
67 posts
Ich schreibe die Aufgabe später selber mal und gebe dann meine Senf dazu!
ingonör
Member since May 2013
67 posts
In reply to post #1
Quote by Baum on 2013-07-19, 21:26:
  1. volatile unsigned int len =1;
  2. (...)
  3. volatile int pos;
Warum volatile und auch noch global deklariert? Ist in meinen Augen nicht nötig. Zudem sollte len vom Typ unsigned char sein, falls es sich dabei um die Schlangenlänge handelt, die an showSnake übermittelt wird.

Quote by Baum on 2013-07-19, 21:26:
  1.         while(len == 6){
  2.             sei();
  3.             sleep_cpu();
  4.             cli();
  5.         }
Das ist nicht das "Standardvorgehen", um den Prozessor schlafen zu legen. Problem: Was, wenn der Prozessor durch einen Interrupt geweckt wird, der aber nicht von deinem Taster kommt? Dann läuft das Programm wieder auf Hochtouren, ohne, dass es der Anwender wollte. Sie dazu meinen Code unten, Zeilen 37-43.


Quote by Baum on 2013-07-19, 21:26:
  1. /*Funktion showSnake()*/
  2. void showSnake(int pos, unsigned char len){
  3.     PORTB |= (1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5);
  4.     for(uint8_t i = 0; i<len; i++){
  5.         PORTB &= ~(1<<((pos+6-i)%6));
  6.     }
  7. }

Ich weiß nicht, ob folgende Anmerkung von mir stimmt: Aber du vergleichst in deiner for-Schleife eine uint8_t Variable mit einer unsigned char Variablen, was ohne Typecast nicht möglich sein dürfte.
Ich würde i ebenfalls als unsigned char deklarieren.


Ansonsten sieht es doch ganz gut aus!

PS. Wir haben beide schön das Präprozessor-Makro NUMLED übersehen und nicht verwendet.  :troll:

Ich poste hier mal noch meinen Code, denn ich habe eine Frage zu den Zeilen 33 bis 57. Dort deaktiviere ich die Interrupts vor der if-Abfrage und aktiviere sie hinterher wieder. Ich mache das, damit es keine Probleme bei der else if-Abfrage in Zeile 46 gibt. In Zeile 47 aktiviere ich die Interrupts wieder und in Zeile 57 wieder. Ist das ein Problem?

  1. #include <avr/io.h>
  2. #include <avr/interrupt.h>
  3. #include <avr/sleep.h>
  4. #define NUMLED 6
  5.  
  6. /* Funktiondeklarationen, globale Variablen, etc. */
  7. void init(void);
  8. void active_wait(volatile unsigned int);
  9.  
  10. volatile uint8_t taster = 0;
  11. /* Unterbrechungsbehandlungsfunktion */
  12. ISR (INT0_vect) {
  13.     taster++;
  14. }
  15.  
  16. /* Funktion main */
  17. void main(void) {
  18.  
  19. /* Initialisierung */
  20.     init();
  21.     unsigned char len = 1;
  22.     int pos = 0;
  23. /* Hauptschleife */
  24.     while(1) {
  25. /* ein Snake-Umlauf */
  26.         while(pos < 6) {
  27.             showSnake(pos++, len);
  28.             wait(5000);
  29.         }      
  30.        
  31. /* Vorbereitung des naechsten Umlaufs bzw. Schlafen */
  32.         pos = 0;
  33.         cli();
  34.         if(len == 5 && taster == 0) {
  35.             sei();
  36.             showSnake(0, 6);
  37.             cli();
  38.             while(!taster) {
  39.                 sei();
  40.                 sleep_cpu();
  41.                 cli();
  42.             }
  43.             sei();
  44.             taster = 0;
  45.             len = 1;
  46.         } else if(taster) {
  47.             sei();
  48.             if (taster < len) {
  49.                 len -= taster;
  50.             } else {
  51.                 len = 1;
  52.             }
  53.             taster = 0;
  54.         } else {
  55.             len++
  56.         }
  57.         sei();
  58.        
  59. /* Ende der Funktion main */
  60.     }
  61. }
  62.  
  63. /* Funktion init */
  64. void init(void) {   
  65.     sleep_enable();
  66.     sei();
  67.    
  68.     DDRB |= 0x3f;
  69.     PORTB |= 0x3f;
  70.    
  71.     DDRD &= ~(1 << PD2);
  72.     PORTD |= (1 << PD2);
  73.    
  74.     MCUCR |= (1 << ISC01);
  75.     MCUCR &= ~(1 << ISC00);
  76.    
  77.     GICR |= (1 << INT0);
  78. }
  79. /* Ende der Funktion init */
  80.  
  81. /* Funktion active_wait() */
  82. void active_wait(volatile unsigned int len) {
  83.     while(len--)
  84.         ;
  85. }
  86. /* Ende der Funktion active_wait() */
  87.  
  88. /* Funktion showSnake() */
  89. void showSnake(int pos, unsigned char len) {
  90.     PORTB |= 0x3f;
  91.     for(unsigned char i = 0; i < len; i++) {
  92.         PORTB &= ~(1 << ((pos + 6 - i) % 6));
  93.     }
  94. }
  95. /* Ende der Funktion showSnake() */
morty
SPiC-Meister
(Moderator)
Member since May 2011
331 posts
Quote by ingonör:
Ich weiß nicht, ob folgende Anmerkung von mir stimmt: Aber du vergleichst in deiner for-Schleife eine uint8_t Variable mit einer unsigned char Variablen, was ohne Typecast nicht möglich sein dürfte.
Ich würde i ebenfalls als unsigned char deklarieren.
Die werden implizit beide in int gewandelt. In sofern geht das ok. Irgendwo müsst in den Headern ein
  1. typedef uint8_t unsigned char
stehen.

Quote by ingonör:
Ich poste hier mal noch meinen Code, denn ich habe eine Frage zu den Zeilen 33 bis 57. Dort deaktiviere ich die Interrupts vor der if-Abfrage und aktiviere sie hinterher wieder. Ich mache das, damit es keine Probleme bei der else if-Abfrage in Zeile 46 gibt. In Zeile 47 aktiviere ich die Interrupts wieder und in Zeile 57 wieder. Ist das ein Problem?
Jaein. Du hättest die einfacher getan in zweiten Schritt auf len zu testen oder einfach anders zu Schachteln (if(len < 5) len++ else if(taster) {} else {}

Für die showsnake fehlt die Deklaration. Dafür ist die Implementierung umso schöner!

Alternativ hättest du auch len im Interrupt zählen können.

27: ++ richtig eingesetzt! Ich versuch das inzwischen zu vermeiden, weil sich da häufig Fehler einschleichen.

Ansonsten sehe ich gerade nichts....
ingonör
Member since May 2013
67 posts
Danke!  :cool:
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