case-Anweisung

#4042384
Lesenswert?

Moin,

ich arbeite gerade mit einem ATMEGA168 und möchte ein 
switch-case-Anweisung verwenden. Interessanterweise funktioniert eine 
der Anweisungen ohne Probleme, die andere, die genauso aufgebaut ist 
allerdings nicht. Hier mal der Code:

Die funktionierende Anweisung
1
void light(int x)
2
  {
3
    switch (x){
4
    
5
      case 0:
6
        PORTC |= (1<<PC5);
7
        break;
8
      case 1:
9
        PORTC &= ~(1<<PC5);
10
        break;
11
    }
12
  }

Die nicht funktionierende Anweisung
1
void led_rt(int x)
2
  {
3
    switch (x)
4
    {
5
    case 0:
6
      PORTB |= (1<<PB1);
7
      break;
8
    case 1:
9
      PORTB &= ~(1<<PB1);
10
      break;
11
    
12
    }
13
  }

Ich sehe den Unterschied (vom Aufbau her) der beiden Anweisungen nicht, 
und kann mir nicht erklären, warum es einmal funktioniert und einmal 
nicht.

Gruß
#4042982
Lesenswert?

tastendrücker schrieb:
> jöle schrieb:
>> Was heißt
>> überhaupt "... es einmal funktioniert und einmal nicht".
>
> Na -ich denke er meint: light(x) fnktioniert und led_rt(x) nicht.

Dann einfach mal den Inhalt der beiden Funktionen vertauschen.

Ich tippe auch auf entweder einen Hardware-Fehler (LED falsch 
angeschlossen), oder eine falsche Initialisierung irgendwo in einem 
Stück Code, das man uns hier wie so oft vorenthält.
#4042992
Lesenswert?

Nein die LED ist nicht verpolt, da sie außerhalb der Case-Anweisung auch 
leuchtet, wenn ich die Pins manuell setzte.

Hier mal der Code, wobei ich die Initialisierung der Ports bereits 
angegeben hatte.
1
int main(void)
2
{
3
  avr_init();
4
  lcd_init();
5
  //TSIC_INIT();
6
  light(1);
7
  
8
  lcd_clear();
9
  led_bl(1);
10

11
  
12
  
13
  
14
    while(1)
15
    {
16
    
17
    sprintf(Buffer_counter, "%d", counter);
18
    lcd_setcursor(0,1);
19
    lcd_string("Counter: ");
20

21
    
22
//          getTSicTemp(&temperature);          
23
//          temperature = ((temperature * 250L) >> 8) - 500;  
24
//          itoa(temperature, temperature_out, 10);
25
//          celsius = temperature / 10 + (float) (temperature % 10) / 10;
26
//          lcd_setcursor(3,0);
27
//          lcd_string("Temperatur");
28
//          lcd_numbers(celsius, 5, 1);
29
     _delay_ms(500);
30
//     lcd_clear();
31
     light(1);
32
     
33
     
34
     if (counter >= 100)
35
     {
36
      light(0);
37
      lcd_clear();
38
      led_bl(0);
39
      led_rt(1);
40
      
41
      counter = 0;
42
     }
43
 
44
     
45
     counter++;
46
    }
47
}

Und Hier die avr_init():
1
void avr_init(void){
2
  
3
  //Definieren der Ausgänge
4
  DDRB |= (1<<DDB0) | (1<<DDB1);
5
  DDRC |= (1<<DDC5);
6
  
7
  //Definieren der Eingänge
8
  DDRC &= ~(1<<DDC3);
9
  DDRD &= ~(1<<DDD6);
10
  
11
  //Setzen der Pull-Ups der Eingänge
12
  PORTC = (1<<PC3);
13
  PORTD = (1<<PD6);
14
  
15
  //Setzen der Ausgangszustände
16
  PORTB |= (1<<PB0) | (1<<PB1);
17
  PORTC |= (1<<PC5);
18
}
#4042999
Lesenswert?

Vergessen zu kopieren. Dies steht natürlich noch vor der main:
1
#define F_CPU 1000000UL
2

3
#define Grad 0x80
4

5
#include <avr/io.h>
6
#include <util/delay.h>
7
#include <stdio.h>
8
#include "avr.h"
9
#include "lcd.h"
10
#include "tsic.h"
11

12
uint16_t temperature = 0;
13
float celsius = 0;
14
char temperature_out[10];
15
int counter = 0;
16
char Buffer_counter[5];
#4043010
Lesenswert?

Möglicher Weise hat der Compiler Probleme mit dem _ in LED_rt. Den _ 
würde ich mir hier schenken und eher ledRot schreiben oder ähnliches.

int x würde ich so auch nicht verwenden, du weißt hier nämlich nicht wie 
groß x gewählt wird und es könnte hier auch ein 32 bit Integer benutzt 
werden. Hier genügt aber ein 8 bit Integer und der ist für den AVR auch 
leichter zu behandeln. Daher ist es nicht verkehrt immer uint8_t (hier 
wird ein 8 bit unsigned Integer benutzt) und ähnliches zu benutzen.
Gast #4043046
Lesenswert?

Also mit im Nebel rumstochern ist dir nicht geholfen und uns nur Zeit 
gestohlen. Reduziere den Code auf die fehlerhaften Funktionen und teste, 
ob es dann funktioniert. Wenn Nein, dann poste hier den reduzierten Code 
hier, aber diesen inklusive Funktions- und Variablendeklaration und 
definition. Dann besteht auch die Chance, dass dir hier schnell und gut 
geholfen werden kann.
#4043065
Lesenswert?

Hier mal der vereinfachte Code. Die blaue LED funktioniert, nur die Rote 
nicht.

avr.h
1
#ifndef AVR_H_
2
#define AVR_H_
3

4
void avr_init(void);
5
void led_rt(uint8_t);
6
void led_bl(uint8_t);
7
void light(uint8_t);
8

9

10
#endif /* AVR_H_ */

avr.c
1
  #define F_CPU 1000000UL
2
  
3
  #include <avr/io.h>                  //einbinden der Bibliothek 'io.h'
4
  #include <util/delay.h>                //einbinden der Bibliothek 'delay.h'
5
 
6
  
7
 
8
  void avr_init(void){
9
  
10
  //Definieren der Ausgänge
11
  DDRB |= (1<<DDB0) | (1<<DDB1);
12
  DDRC |= (1<<DDC5);
13
  
14
  //Definieren der Eingänge
15
  DDRC &= ~(1<<DDC3);
16
  DDRD &= ~(1<<DDD6);
17
  
18
  //Setzen der Pull-Ups der Eingänge
19
  PORTC = (1<<PC3);
20
  PORTD = (1<<PD6);
21
  
22
  //Setzen der Ausgangszustände
23
  PORTB |= (1<<PB0) | (1<<PB1);
24
  PORTC |= (1<<PC5);
25

26
  
27
  
28
  }
29
  
30
  void led_rt(uint8_t x)
31
  {
32
    switch (x)
33
    {
34
    case 0:
35
      PORTB |= (1<<PB1);
36
      break;
37
    case 1:
38
      PORTB &= ~(1<<PB1);
39
      break;
40
    
41
    }
42
  }
43
  
44
  void led_bl(uint8_t x)
45
  {
46
    switch (x)
47
    {
48
    case 0:
49
      PORTB |= (1<<PB0);
50
      break;
51
    case 1:
52
      PORTB &= ~(1<<PB0);
53
      break;
54
    
55
    }
56
  }
57
  
58
  void light(uint8_t x)
59
  {
60
    switch (x){
61
    
62
      case 0:
63
        PORTC |= (1<<PC5);
64
        break;
65
      case 1:
66
        PORTC &= ~(1<<PC5);
67
        break;
68
    }
69
  }

main.c
1
define F_CPU 1000000UL
2

3

4
#include <avr/io.h>
5
#include <util/delay.h>
6
#include "avr.h"
7

8

9

10
int counter = 0;
11

12

13
int main(void)
14
{
15
  avr_init();
16
  
17
  led_bl(1);
18
  led_rt(0);
19

20
  
21
  
22
  
23
    while(1)
24
    {
25
 
26
   counter++;
27

28
     if (counter >= 100)
29
     {
30
      
31
      lcd_clear();
32
      led_bl(0);
33
      led_rt(1);
34
      
35
      counter = 0;
36
     }
37

38
     
39
     _delay_ms(500);
40
     
41
    }
42
}
#4043090
Lesenswert?

Mal abgesehen vom LCD-Code sehe ich hier keinen Fehler. Gib dem Switch 
für die rote LED mal eine default-funktion, sowas wie
1
default:
2
PORTB |= (1<<PB0);
3
_delay_ms(500);
4
PORTB &= ~(1<<PB0);
5
_delay_ms(250);
6
PORTB |= (1<<PB0);
7
_delay_ms(250);
8
PORTB &= ~(1<<PB0);
9
_delay_ms(250);
10
PORTB |= (1<<PB0);
11
_delay_ms(250);
12
PORTB &= ~(1<<PB0);
13
_delay_ms(250);
14
PORTB |= (1<<PB0);
15
_delay_ms(250);
16
PORTB &= ~(1<<PB0);
17
_delay_ms(250);
18
PORTB |= (1<<PB0);
19
_delay_ms(500);
20
PORTB &= ~(1<<PB0);
21
break;
#4043103
Lesenswert?

Marco G. schrieb:
> So jetzt mal die Zeile rausgenommen und neu kompiliert. Hat sich nichts
> am Verhalten der LED geändert.

Dreh mal die 0 und 1 bei den LED-Funktionen in main rum, so dass die 
LEDs genau andersrum leuchten müss(t)en wie vorher. Wenn nicht, dann 
programmierst du seit Stunden immer das Programm von gestern in den 
Controller, oder deine Hardware ist nicht das, was du von ihr erwartest.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren