ATMega8 als Zähler

Gast #1451458
Lesenswert?

Hallo zusammen,

ich habe mal wieder ein Problem mit meinem C-Programm. :-/

Für meine Schaltung verwende ich einen ATMega 8, programmiere mit dem 
AVR-Studio und programmiere in C.

Die Schaltung soll die Zustände einer anderen Mikrocontroller-Schaltung 
(ATtiny13) überwachen und je nach Zustand reagieren.

Sollte ein Fehler auftreten, so soll er den "Zaehler" um 1 erhöhen, es 
auf dem Display ausgeben, die Mikrocontroller-Schaltung (ATtiny13) 
zurücksetzen und das Ganze von vorne beginnen.

Das Problem:
Er zählt bis 1 hoch, aber dann passiert nichts mehr! Das Programm ist im 
Anhang. Kann mir jemand helfen?
Ich bin für alle Antworten und Hilfestellungen dankbar!!!

Viele Grüße

Simon
Angehängte Dateien:
#1451473
Lesenswert?

Wieviele Pins willst du am Port B eigentlich überwachen? Und woran 
erkennt man, dass 'ein Fehler aufgetreten' ist?

Formatier das doch bitte mal ein wenig vernünftig. Ich denke nicht, dass 
da jetzt irgendwer Lust darauf hat, diese Monster-Bedingung mit all 
seinen vielen Klammern im if bzw. while zu analysieren um rauszufinden 
unter welchen Umständen der jeweilige Pfad genommen wird und wann nicht. 
Alles in allem kommt mir das reichlich kompliziert vor für die 
eigentlich primitiv anmutende AUfgabenstellung aus dem Anfangsposting.


PS: Was macht eigentlich der goto da am Anfang und am Ende der Funktion. 
Dir ist schon klar, dass die Funktion schleife_normal sowieso wieder und 
wieder ausgeführt werden würde und es daher nicht so schlau ist, da in 
der Funktion windige Schleifenkonstrukte mit goto aufzubauen?
Gast #1451515
Lesenswert?

Als Zustandüberwachung habe ich 4 LEDs gewählt...2 LEDs geben den 
Grundzustand wieder (beide leuchten)...wenn beide Leuchten, soll das 
Programm aktiviert werden. Die anderen beiden LEDs blinken dann 
abwechselnd.
Solange sie blinken, soll er nichts tun (while-Schleife im 
main-Programm)..weicht der Zustand vom Blinkzustand ab (Durch äußere 
elektromagnetische Felder, dann soll das Programm den Zähler um 1 
erhöhen, auf dem Display ausgeben und die Schaltung in den Grundzustand 
setzen (LEDs, wie oben leuchten beide). Dach wieder das Blinkprogramm 
aktivieren usw.

Die goto's lass ich außen vor...es geht nur darum, dass nicht hochgezält 
wird.

Bevor ich die Sache mit dem itoa eingefügt habe, ging alles wie 
geschmiert.
#1451521
Lesenswert?

Simon R. schrieb:
> Als Zustandüberwachung habe ich 4 LEDs gewählt...2 LEDs geben den
> Grundzustand wieder (beide leuchten)...wenn beide Leuchten, soll das
> Programm aktiviert werden.

Welche sind das?

> Die anderen beiden LEDs blinken dann
> abwechselnd.
> Solange sie blinken,

Mit welcher Frequenz blinken sie? (ungefähr. Damit man abschätzen kann, 
in welchen Zeiträumen sich ein Pinzustand ändern muss um als Fehler 
erkannt zu werden)

Welche sind das?

> soll er nichts tun (while-Schleife im
> main-Programm)

Äh nein. Das ist nicht deine Programmlogik.


> Die goto's lass ich außen vor...es geht nur darum, dass nicht hochgezält
> wird.

Ich denke mal dass genau diese gotos dich soweit verwirrt haben, dass 
deine Programmlogik einfach nicht stimmt. Ohne die goto könnte man das 
Programm halb so kurz formulieren, die Struktur würde besser rauskommen 
und die Chance Fehler zu machen siinkt ebenfalls


Im übrigen halte ich die ganze Idee mit einem zweiten Prozessor, der 
einen ersten Prozessor überwachen soll, für ziemlich kontraproduktiv. 
Getreu dem Motto: Wer überwacht eigentlich den Überwacher? Was, wenn 
dieser Prozessor ebenfalls ausfällt?
#1451531
Lesenswert?

Nur so als Beispiel.
Man könnte das zb so formulieren
1
.....
2

3
   zaehler = 0;
4

5
   while( 1 ) {    // Hauptschliefe in main()
6

7
     // warte auf die beiden LED an PB3 und PB4.
8
     // wenn sie angehen, ist der Prozessor hoch
9

10
     while( ! ( PINB & ( 1 << PB3 ) &&
11
                PINB & ( 1 << PB4 ) )
12
       ;
13

14
     // ok, LED sind an, der andere Prozessor ist hoch.
15
     // in regelmässigen Zeitabständen muss sich jetzt der Zustand
16
     // an PB1 und PB2 ändern
17
     old = PINB & ( 1 << PB1 || 1 << PB2 );
18
     now = old;
19
     while( old != now ) {
20
       old = now;
21
       _delay_ms( setzte einen Zahlenwert ein, von dem sichergestellt
22
                  ist, dass sich die Blink-LED in dieser Zeit ändern
23
                  müssten );
24
       now = PINB & ( 1 << PB1 || 1 << PB2 );
25
     }
26

27
     // es hat in der Wartezeit keine Änderung des Pinzustands gegeben
28
     // -> Schluss: Prozessor ist abgeschmiert
29

30
     zaehler++;
31

32
     // resetten und am LCD ausgeben
33
     lcd_puti( zaehler );
34
     ....
35

36
   }
37
}
#1451552
Lesenswert?

> allerdings hatte ich es auch einfach mit zaehler-48 versucht

Wozu -48?

Steck zaehler in itoa hinein und du bekommst einen String, der ASCII 
mässig der Zahl in zaehler entspricht. Fertig.

Am besten machst du dir für diese Operation, einen int ausgeben, eine 
Funktion
1
void lcd_puti( int zahl )
2
{
3
  char buffer[10];
4

5
  itoa( zahl, buffer, 10 );
6
  lcd_puts( buffer );
7
}

und benutzt die ganz einfach, wann immer du einen int auszugeben hast.
1
   ....
2

3
                _delay_ms(30);                
4
                 zaehler++;
5
                _delay_ms(3000);
6
                
7
                lcd_home();
8
                lcd_string("Ausfaelle:");
9
                lcd_puti( zaehler );
10
                          
11
                set_cursor(0,2);
12
                lcd_string("BFR:");
13
                lcd_puti( ausfaelle );
14
                lcd_string("/");
15
                lcd_puti( pulse );
16
   ....
Gast #1451555
Lesenswert?

Was die Zustände angeht...es muss durch umgekehrte Logik erfolgen.

Auch die LEDs dürfen nur abwechselnd aktiviert werden (XOR).

Ich weiß, dass das kompliziert aussieht...aber ich hatte vorher eine 
Logiktabelle über alle Zustände (insgesamt 2^4=16) aufgestellt und alle 
einzeln in die Bedingung eingebracht, die NICHT auftreten dürfen.
#1451562
Lesenswert?

Simon R. schrieb:
> Die -48 habe ich eingebunden, weil sonst, wenn er um eins erhöht, eine
> 49 auf dem LC-Display (EA DIP 204-4 von Assembly Electronic) ausgibt.

Ja.
Wenn du zaehler als ASCII Code an das Display schickst.
Aber du hast ja itoa. Das weiß schon, wie man einen int zu einem String 
wandelt, so dass der String die Textrepräsentierung der Zahl darstellt.
#1451591
Lesenswert?

Ich will mich jetzt ehrlich gesagt nicht durch den ganzen Code (noch 
dazu mit schleifen und goto Kombination quälen), aber ein paar Dinge 
sind mir beim kurzen überfliegen aufgefallen:

1. Dein Zähler wird JEDESMAL am Anfang von schleife_normal() auf 0x30 
zurück gesetzt gesetzt. Ist das wirklich Absicht??
Wenn ich das Programm richtig durchschaut habe wird im Fehlerfall der 
zähler um 1 erhöht, aufs LCD geschrieben und schleife_normal() beendet. 
Die main loop startet schleife_normal() wieder und setzt den zähler 
zurück. (Warum eigentlich ausgerechnet auf 0x30?)

2. ausfaelle wird NUR am Anfang von schleife_normal() zugewiesen. Im 
Fehlerfall erhöhst du zwar zähler, zeigst aber ausfaelle an???
Und das sowohl für Ausfaelle als auch BFR.

by(e)
Stephan
Gast #1451605
Lesenswert?

Ausfaelle ist ja quasi durch zaehler definiert...
...aber das habe ich mittlerweile geändert...denn selbstsamerweise hat 
er mir statt einer 1 immer 49 ausgegeben (also 1+48)..
aber durch die richtige Initilisierung hat sich das geändert. :-)

Was deine Vermutung (zaehler immer zurückgesetzt) angeht, kannst du 
recht haben...

Man hat immer das Problem, dass man vor lauter Bäumen den Wald nicht 
mehr sieht...vor allem dann, wenn man schon zig mal dieses Programm 
umgeschrieben hat...

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