Forum: Mikrocontroller und Digitale Elektronik Fragen zu AVR C


von Antoni (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

ich bin grade an meinem avr Digitale Uhr Projekt
und habe einige Fragen zu avr C.
Im Anhang der komplette Code fuer meine Uhr zur Zeit.
Es ist eine Uhr mit 2mhz Quarz und 6 7-Segment LEDs mit gemeinsamer
Anode zur Anzeige. Die Segmente der 7Seganzeige sind jeweils parallel
verbunden und mit 7 Transistoren nach GND verbunden. Jedes
Segment hat quasi seinen eigenen Transistor und die werden durch
die einzelnen uC Pins gesteuert.
Die Anzeigetechnik ist Multiplexing, der uC ist ein Attiny2313.

Ich hab 2 konkrete Fragen zum avr-C, folgende Situation:
1) Ich wollte Taster per Interrupt einsetzen. Dazu
hab ich die  GIMSK |= (1<<PCIE); PCMSK |= (1<<PCINT7) | (1<< PCINT6);
gesetzt, ebenfalls wurde sei() ausgefuehrt.
Sobald diese Register gesetzt waren, war aber ploetzlich
jedes Mal beim Betaetigen der Taster eine Resetwirkung des Controllers
festzustellen. Die Uhranzeige hat sich immer wieder reseted.
Dann hab ich die Loesung ohne Interrupts wie im Anhang verwendet
mit der direkten PIN abfrage.

2) Ich wollte die 7Segmentanzeige an und ausmachen wollen per Taster.
Also hab ich in meiner Pinabfrage folgenden Code ausprobiert,
hier mal als Ausschnitt ausm Kopf zusammengereimt:
1
int an = 1;
2
int trust = 0;
3
while(1){
4
  if(!(PIN & (1<<6)){
5
    trust++;
6
    if(trust >= 100){
7
    if(an == 1) an = 0;
8
    else if(an == 0) an = 1;
9
    trust = 0;
10
    } 
11
    // wenn der else if teil wegfaellt, dann funktionierts,
12
    // allerdings geht das Display dann nur aus
13
    // alternativ probierte ich erst an ^= 1;
14
15
  }
16
17
  if(an == 1) {
18
//Code fuer Displayanzeige
19
  }
20
}

Sobald ich das "an und aus Spiel" auf 2 Taster verteilt habe,
hats auch funktioniert. Nur mit einem Taster gings nicht.
Ich habs anders geloest in der jetzigen Version, aber es scheint
mir ziemlich beknackt zu sein und ich verstehe nicht, warum
es nicht funktioniert. Ich vermute es liegt an der Compileroptimierung.
Ohne Optimierung gehts aber nicht, Code zu gross um es auf den
uC zu laden.

3[die unkonkrete Frage]) Der Code im Anhang funktioniert auf jeden Fall 
schonmal grob.
Die Uhr laeuft und ich kann auch die Uhrzeit einstellen.
Womit ich allerdings Probleme hab ist, dass die Uhr abstuerzt,
wenn ich die Taster intensiv benutze. Wenn ich zu intensiv
die Uhrzeit einstelle, dann passiert es, dass ploetzlich
das 7Segmentdisplay nur noch eine 1 anzeigt und nur noch ein
Reset weiterhilft. Ebenso verstellt sich manchmal die Zeit,
wenn ich das Display an und ausschalte, obwohl der Taster
nichts mit der Zeiteinstellung zu tun haben sollte.
Das ist Verhalten, was ich nicht verstehe... ich fuerchte,
dass da elektronikmaessig Stoerungen sind, die ich nicht begreife.
Man muss dazu sagen, dass 82mA Strom fliessen wenns Display an
ist und 1,3mA wenns aus ist. Das sind immer ziemliche Spruenge
mit dem an und aus machen. Kann es damit zusammmenhaengen?


lg Antoni

von Stefan F. (Gast)


Lesenswert?

Was du alles genau probiert hast, lässt sich anhand deiner Beschreibung 
nur grob erahnen. Du hättest alle Codes anhängen sollen. Dann wäre 
allerdings fraglich, wer das alles lesen wird.

Ein paar generelle Sachen:

Wen das Auslösen eine Interruptes zu einem offensichtlichen Reset führt, 
hast du vermutlich vergessen, eine Interrupt-Routine für den Interrupt 
zu schrieben. Oder deine Interrupt Routine wurde falsch (für einen 
anderen Interrupt) deklariert.

> Ich vermute es liegt an der Compileroptimierung.

Das ist sehr selten die Fehlerursache. Mir ist das in meinem ganzen 
Leben nur ein einziges mal passiert. Mit -O1 funktionierte das Programm, 
aber mit -Os funktionierte es nicht. Aber ich hatte das Problem nur mit 
einer ganz bestimmten Version des Compilers. Eine Version davor und eine 
danach klappte es mit allen Optimierungs-Varianten.

Und selbst bei diesem einen Fall kann die wahre Fehlerursache immer noch 
ein unbemerkter Programmierfehler meinerseits sein. Es kommt relativ 
häufig vor, dass man vergessene Variablen-Initialisierung und 
Array-Überläufe gar nicht oder erst nach sehr langer Zeit bemerkt.

Was mir sofort auffällt ist, dass die variable cnt sowohl im Interrupt 
als auch außerhalb verwendet wird, aber kein Mechanismus zur 
Synchronisation vorhanden ist. Die Variable ich größer als 1 Byte, daher 
musst du dafür sorgen, dass sie nur abwechselnd vom Interrupt oder von 
anderem Code angesprochen wird. Außerdem muss sie "volatile" sein. Nach 
dem Wort kannst du ja mal googeln, das wurde hier öfters detailliert 
erklärt.

Ich würde auch mal überlegen, ob die Variable cnt wirklich 64bit groß 
sein muss. Für diese kleinen 8bit Kontroller sind 64bit Operationen 
ziemlich Aufwändig. Du bekommst ein Problem, wenn die Interrupt-Routine 
länger dauert, als die Zeit zwischen zwei Interrupts.

Die Berechnung der Uhrzeit kannst du außerhalb der Interruptroutine 
machen. Es würde durchaus genügen, wenn die Interruptroutine lediglich 
die Anzahl der Interrupts einfach nur hochzählt. Die Umrechung in 
Stunden/Minuten/Sekunden machst du dann in der Hauptschleife, bevor die 
Zahlen angezeigt werden.

Dein Code ist scheußlich eingerückt. Stell deinen Texteditor mal so ein, 
dass er mit Leerzeichen einrückt (statt Tabulator) und ersetze danach 
alle Tabulator Zeichen durch 4 oder 8 Leerzeichen. So vermeidest du 
Darstellungsprobleme in anderen Programmen.

Auf jeden Fall würde dabei bleiben, die Tasten ohne Interrupts 
abzufragen. Das ist weniger Fehleranfällig.

von Stefan F. (Gast)


Lesenswert?

Hast du die Tasten mit Kondensatoren entprellt? Würde ich mal machen, 
damit ein Tastendruck nicht mehrfach gezählt wird. Man kann auch per 
Software entprellen, das ist aber nicht so einfach.
1
   Taster   100 Ohm
2
    ___
3
|---- -----[===]---+----- AVR Eingang mit Pull-Up
4
                   |
5
|----||------------+
6
    100nF

Oder:
1
     Taster   100 Ohm
2
      ___
3
+ o---- -----[===]---+----- AVR Eingang ohne Pull-up
4
  |                  |
5
  +----||------------+-----[===]---|
6
    100nF                  22k Ohm

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.