Forum: Mikrocontroller und Digitale Elektronik Probleme mit einfachem C-Code


von Kilian H. (qwert)


Lesenswert?

Hallo,

ich versuche gerade, in Abhängigkeit von verstrichener Zeit etwas 
auszuführen und scheitere gerade an folgendem Code (so weit wie möglich 
reduziert, sodass sich momentan kein Sinn ergibt):

Das Ergebnis: LEDs an PORTB leuchten sehr schwach
Erwartet: Die LEDs sind aus
1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include <stdlib.h>
4
#include <stdint.h>
5
#include <avr/interrupt.h>
6
7
uint16_t cnt = 0;
8
volatile int minuten = 0;
9
10
int main(void) {
11
  DDRB = 0xff;
12
  PORTB = 0xff;
13
14
15
  DDRC = 0x00;
16
  PORTC = 0xff;
17
  
18
  PORTB = 0x00;
19
  while(1) {
20
    if(PINC & (1<<PINC4))
21
      minuten = ((minuten / 15)+1)*15;
22
  }
23
24
  return 0;
25
}
26
27
ISR (TIMER0_OVF_vect) {
28
  cnt++;
29
  if(cnt == 931) {
30
    cnt = 0;
31
    //1 Minute verstrichen
32
    minuten++;
33
  }
34
}

Wenn ich die Zeile
1
minuten = ((minuten / 15)+1)*15;
auskommentiere, funktioniert es wie erwartet.

Was mache ich falsch?

von mmm (Gast)


Lesenswert?

Kilian Herbst schrieb:
> Das Ergebnis: LEDs an PORTB leuchten sehr schwach
> Erwartet: Die LEDs sind aus

Wie sind die LEDs angeschlossen?

von Kilian H. (qwert)


Lesenswert?

Ich habe das Atmel Evaluation Board Add on Board. Da sind diese über 
einen ULN2803 und einen Widerstand auf 5V angeschlossen. Sind die 
Ausgänge aktiv, wird auf GND durchgeschaltet.

von Detlef K. (adenin)


Lesenswert?

Also Du machst die erst mal die Variale "minuten" kaputt.
Ich schätze mal der Wert wird immer auf 15 gesetzt.
Allerdings ist hier keine Rückwirkung auf die Pins zu sehen.
Ist das die koplette Source?
Meldet der Compiler keinen Fehler, wenn Du die Zeile auskommentierst, 
weil dem IF was fehlt?

von Martin K. (maart)


Lesenswert?

Was soll den mit dem Code auch passieren? Ein Portpin wird ja 
nirgendwo gesetzt/gelöscht.

von Kilian H. (qwert)


Lesenswert?

Wie gesagt, der Code ist reduziert auf das nötigste, um den Fehler zu 
verursachen.

Die Variable Minuten wird immer auf die nächsten vollen 15 Minuten 
gesetzt.

von Werner A. (homebrew)


Lesenswert?

Dann erklär doch mal, was dieser Code deiner Meinung nach machen soll 
und was er wirklich macht

von Kilian H. (qwert)


Lesenswert?

Der Compiler meldet keinen Fehler.

Ich habe gerade nochmal den Code per Copy&Paste in ein neues Projekt 
geladen, auf den Controller übertragen und das selbe Ergebnis erhalten. 
Also mit auskommentierter Zeile sind die LED's aus, sonst halb an.

von Kilian H. (qwert)


Lesenswert?

Der Code sollte die LEDs durch die Zeile
PORTB = 0x00
ausschalten und dann in der Endlosschleife auf einen Tastendruck an PINC 
4 warten und entsprechend die Variable minuten hochzählen. (Das 
Timer-Zeug hätte ich natürlich auch noch weglassen können)

Und was er wirklich macht, weiß ich nicht ;).

von ich (Gast)


Lesenswert?

Abgesehen, daß du deine Variable "minuten" immer wieder nur auf 15 
setzt, hat das mit dem PORTB überhaupt nichts zu tun.

minuten:
im Timer incrementierst du sie (z.B. von 15 auf 16), dann kommt deine 
Zeile
1
minuten = ((minuten / 15)+1)*15;
und setzt sie wieder auf 15. Nach einer Minute kommt wieder der Timer 
dran, setzt sie wieder auf 16 und so weiter...

Aber das ist ja nicht die Frage. Was hat das alles mit den PORTs zu tun?
Nach der Zeile
1
PORTB = 0x00;
wird der PORTB nie wieder angefaßt.

Ich würde jetzt erstmal die gesamte Verdrahtung überprüfen.
Das Auskommentieren der Zeile hat doch keinen Einfluß auf PORTB...

von Werner A. (homebrew)


Lesenswert?

ich schrieb:
> Das Auskommentieren der Zeile hat doch keinen Einfluß auf PORTB...

Es sei denn, dass das Auskommentieren dazu führt, dass der Controller 
kontinuierlich in einen Reset geht. Dann flackert die halt sehr schnell.

Probier doch mal das aus
1
while(1) {
2
    if(PINC & (1<<PINC4)) {
3
      minuten = ((minuten / 15)+1)*15;
4
    }
5
    minuten = minuten;
6
  }
und dann dies
1
while(1) {
2
    if(PINC & (1<<PINC4)) {
3
//      minuten = ((minuten / 15)+1)*15;
4
    }
5
    minuten = minuten;
6
  }

von Detlef K. (adenin)


Lesenswert?

Ich setz mal voraus, das Du am PORTC4 einen Widerstand nach Masse hast 
und durch drücken der Taste der Pin auf high gehen soll.
Wenn da kein Massewiderstand ist, dann ist PINC4 immer high, weil Du 
durch PORTC=0xFF den internen Pullup aktiviert hast.
Und wenn PINC4 high ist, dann werden die Minuten mit jeden 
Schleifendurchgang um 15 erhöht.
Das erklärt aber nicht dein LED-Problem. grübel

von Kilian H. (qwert)


Lesenswert?

1
minuten = ((minuten / 15)+1)*15;
Wenn minuten jetzt 16 ist, dann ist doch
minuten = ((16 / 15) +1)*15 = (1+1)*15 = 30;
oder überseh ich schon wieder irgendwas?

Ich habe festgestellt, dass es scheinbar mit dem Schlüsselwort 
"volatile" zusammenhängt, denn wenn ich dieses entferne, so funktioniert 
es wie erwartet. Genauer: Wenn ich in der while-Schleife eine 
volatile-Variable verändere, geht es nicht mehr.

Nur warum nicht??

von Kilian H. (qwert)


Lesenswert?

Werner A. schrieb:
> Probier doch mal das auswhile(1) {
>     if(PINC & (1<<PINC4)) {
>       minuten = ((minuten / 15)+1)*15;
>     }
>     minuten = minuten;
>   }
> und dann dieswhile(1) {
>     if(PINC & (1<<PINC4)) {
> //      minuten = ((minuten / 15)+1)*15;
>     }
>     minuten = minuten;
>   }

Erste Variante: LEDs leuchten schwach.
Zweite Variante: LEDs sind aus.

Erste Variante mit minuten nicht als volatile deklariert: LEDs sind aus.

von Stefan E. (sternst)


Lesenswert?

Welcher Controller genau?

von DirkZ (Gast)


Lesenswert?

Wenn Du das
1
volatile
weglässt, wird die Variable vom Compiler wegoptimiert und hier durch 15 
ersetzt.
siehe FAQ: 
http://www.mikrocontroller.net/articles/FAQ#Was_hat_es_mit_volatile_auf_sich

von Kilian H. (qwert)


Lesenswert?

Stefan Ernst schrieb:
> Welcher Controller genau?

ATmega8

von Stefan E. (sternst)


Lesenswert?

Zeige doch bitte mal den Build-Output.

von Kilian H. (qwert)


Lesenswert?

Stefan Ernst schrieb:
> Zeige doch bitte mal den Build-Output.

Danke, das war der entscheidende Hinweis!! Ich hatte für einen atmega32 
compiliert ;).

Dann kann ich meinen Assembler-Text wieder über den Haufen werfen :).

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.