Forum: Mikrocontroller und Digitale Elektronik Selbsthaltung durch Variable


von Bit (Gast)


Lesenswert?

Hallo alle zusammen,
so ich stehe gerade dermaßen auf der Leitung und blicks gerade nicht 
mehr.
ich mochte eine selbst Haltung in c programmieren. Meine Idee ich 
benutze eine Variable um einen Zustand zu speichern.
Das Ergebnis sieht nun so aus:
1
#include <avr/io.h>
2
Int Einschaltet=0;
3
Int main (void){
4
DDRC &= ~(1<<PC0),~(1<<PC1),~(1<<PC2); // Eingang
5
PORTC = 0x00; // Ohne pulldownwid…
6
While(1){
7
  if (PINC & (1<<PC0)==1){ //  Bedingung = true führe die Schleife aus 
8
 Eingeschaltet=1;} // Variable Eingeschaltet wird der Wert 1 gegeben
9
10
 if (Eingeschaltet==1){ // Bedingung = true führe die Schleife aus
11
 s++;} // Zählt eine Variable nach oben (+1 pro Durchgang der schleife)
12
13
  }
14
}

Mein Problem ist nun folgendes, das nichts passiert wenn ich den Taster 
drücke, egal ob lange <1s oder nur kurz >1s.

Allerdings funktioniert folgendes:
1
#include <avr/io.h>
2
Int main (void){
3
DDRC &= ~(1<<PC0),~(1<<PC1),~(1<<PC2); // Eingang
4
PORTC = 0x00; // Ohne pulldownwiderstände
5
While(1){
6
  if (PINC & (1<<PC0)==1){ //  Bedingung = true führe die Schleife aus 
7
 s++;} // Zählt eine Variable nach oben (+1 pro Durchgang der schleife)
8
  }
9
}

Über jegliche Art tipp wäre ich sehr dankbar.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Bit schrieb:
> Int Einschaltet=0;

C unterscheidet zwischen Groß- und Kleinschreibung.

Wie ist dein Typ „Int“ definiert?

> DDRC &= ~(1<<PC0),~(1<<PC1),~(1<<PC2); // Eingang

Du solltest dir die Funktion des Komma-Operators durchdenken.

Davon abgesehen: die Portpins eines AVRs (um den es offenbar geht)
stehen nach einem Reset auf Eingang.

> PORTC = 0x00; // Ohne pulldownwid…

… außerdem hat ein AVR keine Pulldowns sondern bestenfalls Pullups,
aber auch die sind nach Reset abgeschaltet.

>  Eingeschaltet=1

Oben hieß die Variable noch anders …

Bevor wir hier noch weiter deine Tippfehler suchen müssen: bitte
poste doch den Code, den du auch wirklich benutzt hast, in
compilierfähiger Form.

: Bearbeitet durch Moderator
von Rainer U. (r-u)


Lesenswert?

Was soll denn "passieren"? Oder hab ich übersehen wo Du eine Aktion / 
Ausgabe programmiert hast?

von eijach (Gast)


Lesenswert?

Im Beispiel 1 wird die variable s nach dem Drücken des Tasters für immer 
hochgezählt. Man weiß den Datentyp von "s" ja nicht, aber der wird 
irgendwann überlaufen und wieder bei 0 beginnen.

Bei dem 2. Bsp. wird "s" nur so lange hochgezählt wie der Taster 
gedrückt ist.

von Bit (Gast)


Lesenswert?

Im Folgenden findet ihr meine "Organal" Programm es ist noch nicht ganz 
fertig bzw. wird noch erweitert.
Ja da haben sich wirklich ein paar fiese Rechtschreibfehler bei der 
Übertragung eingeschlichen … (Achtung es können sich in den Kommentaren 
immer noch Rechtschreibfehler befinden)
vor allem geht es mir um den teil des Programmes welcher nach
//*****************************taster*********************************** 
*
folgt, da dieser es in dieser Form nicht richtig funktioniert

1
#define F_CPU 1000000UL
2
3
#include <avr/io.h>
4
#include <avr/interrupt.h>
5
6
// definire Bitmuster
7
#define Zahl0 0b01000000
8
#define Zahl1 0b01110011
9
#define Zahl2 0b00100100
10
#define Zahl3 0b00100001
11
#define Zahl4 0b00010011
12
#define Zahl5 0b00001001
13
#define Zahl6 0b00001000
14
#define Zahl7 0b01100011
15
#define Zahl8 0b00000000
16
#define Zahl9 0b00000001
17
18
//     Variablen um Sekunden zu zählen
19
int s;
20
//     Variable um Minuten zu Zählen
21
int m;
22
//     Variablen um Stunden zu Zählen
23
int h;
24
// Variable für das Multiplexen
25
long int Multiplexen;
26
//  Variable
27
int Eingeschaltet = 0;
28
// Array für die Bittmuster welche angezeigt werden sollen.
29
char Anzeige[10] = {Zahl0,Zahl1,Zahl2,Zahl3,Zahl4,Zahl5,Zahl6,Zahl7,Zahl8,Zahl9};
30
31
//  Array für meine Transistoren welche meine Anzeigen An und Aus schalten
32
char Transistoren[6] = {PB0,PB1,PB2,PB3,PB4,PB5};
33
34
int nummer =0; // variable
35
36
int main(void)
37
{
38
  // / segment anzeige
39
  DDRD = 0xff; // DDRD wird zum Ausgang
40
  PORTD = 0x00; // puldownwiderstände ausgeschaltet
41
  // Transistoren
42
  DDRB = 0xff; //DDRB wird zum ausgang
43
  PORTB = 0xff; // pulldownwiderstände eingeschaltet
44
  // Taster
45
  DDRC &= ~(1<<PC0),~(1<<PC1),~(1<<PC2),~(1<<PC3),~(1<<PC4),~(1<<PC5); // wird zum eingang
46
  PORTC = 0x00; // pulldownwiderstände werden ausgeschaltet
47
  
48
  // Festlegung des Taktes auf 1 Hz
49
  TCCR1B |= (1<<WGM12);
50
  TIMSK |= (1<<OCIE1A);
51
  sei(); // erlaube globale interrupts
52
  OCR1A = 15624; //Preceller von 15624 sorgt für 1  HZ
53
  TCCR1B |= (1<<CS10) | (1<<CS11); // Teiler
54
  
55
  
56
  while(1)
57
  {
58
59
//*****************************Zähler**************************************
60
      if (s>59) 
61
      {
62
        m++; 
63
        s=0; 
64
      }
65
      if (m>59) 
66
      {
67
        h++;  
68
        m=0; 
69
      }
70
      if (h>23) 
71
      {
72
        h=0; 
73
      }
74
//*****************************Anzeigenzuweisung**************************
75
      Transistoren [0] = Anzeige[s%10]; 
76
      Transistoren [1] = Anzeige[s/10]; 
77
      Transistoren [2] = Anzeige[m%10]; 
78
      Transistoren [3] = Anzeige[m/10]; 
79
      Transistoren [4] = Anzeige[h%10]; 
80
      Transistoren [5] = Anzeige[h/10]; 
81
//*****************************Multiplexen*******************************
82
      Multiplexen=0; // Setzt die Variable Multiplexen auf 0 zurück
83
      PORTB = 0xff; // PORTB wird eingeschaltet
84
      PORTD = Transistoren[nummer]; 
85
      PORTB &= ~(1<<nummer);
86
      nummer++; //Zählt die Variable Index +1
87
      if (nummer>=6) // wenn die Variable index größer gleich 6 ist wird die schleife ausgeführt
88
      {
89
        nummer=0; // Der Variablen wird der Wert 0 gegeben
90
      }
91
  }
92
//*****************************taster************************************  
93
  // Einschalten ***
94
  if (PINC & (1<<PC0)==1){ // Pinabfrage von PC0 trift diese zu führe schleife aus
95
  Eingeschaltet=1;}  // gibt der Variable "Eingeschaltet" den wert 1
96
  // hier fehlen noch befehle !!!
97
}   
98
99
ISR(TIMER1_COMPA_vect) // Interruptservicerutine
100
{
101
//*****************************Sekundenzähler****************************  
102
  //*** Einschalten ***
103
  if (Eingeschaltet==1){ // solange die Variable "Eingeschaltet" den wert 1 hatt wird die schleife ausgeführt
104
  s++;} // variable"s" wird um 1 nach oben gezehlt
105
}

von Achim S. (Gast)


Lesenswert?

Bit schrieb:
> Im Folgenden findet ihr meine "Organal" Programm

prima

Bit schrieb:
> if (PINC & (1<<PC0)==1){ // Pinabfrage von PC0 trift diese zu führe
...

dieser Code kommt nach der Schleife while(1). Da diese Schleife niemals 
beendet wird, wird dieser Code nie ausgeführt, Eingeschaltet bleibt also 
ewig auf 0.

von Peter II (Gast)


Lesenswert?

was soll das PB0 usw. darin?
1
char Transistoren[6] = {PB0,PB1,PB2,PB3,PB4,PB5};
2
Transistoren [0] = Anzeige[s%10];

von Einer K. (Gast)


Lesenswert?

Noch mal den Kommaoperator überprüfen.

// falsch
DDRC &= ~(1<<PC0),~(1<<PC1),~(1<<PC2),~(1<<PC3),~(1<<PC4),~(1<<PC5);

//besser
DDRC &= ~(1<<PC0)&~(1<<PC1)&~(1<<PC2)&~(1<<PC3)&~(1<<PC4)&~(1<<PC5);

oder ganz weg lassen, der Grund wurde schon genannt.


So:
volatile int Eingeschaltet = 0;

if (PINC & (1<<PC0)==1) // ??
if (PINC & (1<<PC0)) // ausreichend

von Dietrich L. (dietrichl)


Lesenswert?

Bit schrieb:

> int Eingeschaltet = 0;

Da diese Variable auch in der ISR benutzt wird, braucht Du
1
volatile int Eingeschaltet = 0;

von eijach (Gast)


Lesenswert?

Du musst ggf. die Variablen die im IRQ verwendet werden als "volatile" 
deklarieren.

Sprich "s" und "eingeschaltet" als "volatile int s;"


usw.

von Dorftrottel (Gast)


Lesenswert?

Bit schrieb:
> PORTD = 0x00; // puldownwiderstände ausgeschaltet

AVR haben AFAIK Pullup -Widerstände.

von Bit (Gast)


Lesenswert?

Achim S. schrieb:

> Bit schrieb:
>> if (PINC & (1<<PC0)==1){ // Pinabfrage von PC0 trift diese zu führe
> ...
>
> dieser Code kommt nach der Schleife while(1). Da diese Schleife niemals
> beendet wird, wird dieser Code nie ausgeführt, Eingeschaltet bleibt also
> ewig auf 0.

Doch diese schleife wird immer wieder ausgeführt da die bedingung gräßer 
0 ist.

Peter II schrieb:
> was soll das PB0 usw. darin?
PB0 usw. sind die bezeichnung meiner pins am yC

> char Transistoren[6] = {PB0,PB1,PB2,PB3,PB4,PB5};
Ein Array mit der bezeichnunt Transistoren

> Transistoren [0] = Anzeige[s%10];
ein Arrey sucht an 0ter stelle etwas und zeigt dieses an
anzeige array sucht die variable die bei der modulation der variable s 
durch 10 herrauskomt und zeigt diese an

Arduino F. schrieb:
> Noch mal den Kommaoperator überprüfen.
>
> // falsch
> DDRC &= ~(1<<PC0),~(1<<PC1),~(1<<PC2),~(1<<PC3),~(1<<PC4),~(1<<PC5);
>
> //besser
> DDRC &= ~(1<<PC0)&~(1<<PC1)&~(1<<PC2)&~(1<<PC3)&~(1<<PC4)&~(1<<PC5);
>
> oder ganz weg lassen, der Grund wurde schon genannt.
>
> So:
> volatile int Eingeschaltet = 0;
>
> if (PINC & (1<<PC0)==1) // ??
> if (PINC & (1<<PC0)) // ausreichend

tatsechnich wen das funktioniert ist es übersichtlicher

eijach schrieb:
> Du musst ggf. die Variablen die im IRQ verwendet werden als
> "volatile"
> deklarieren.
>
> Sprich "s" und "eingeschaltet" als "volatile int s;"
>
> usw.

also gut das werde ich gleich ausprobieren

Dorftrottel schrieb:
> Bit schrieb:
>> PORTD = 0x00; // puldownwiderstände ausgeschaltet
>
> AVR haben AFAIK Pullup -Widerstände.

ok da hatt sich ein bezeichnungsfehler eingeschlichen

Also ich werde das Programm nun umschreibenn und das neue ergebis posten

von Peter II (Gast)


Lesenswert?

Bit schrieb:
>> char Transistoren[6] = {PB0,PB1,PB2,PB3,PB4,PB5};
> Ein Array mit der bezeichnunt Transistoren

nein, ganz bestimmt nicht. In dem Array steht einfach die Zahlen 0 bis 5

> Transistoren [0] = Anzeige[s%10];
damit werden die Zahlen eh überschrieben.

von Peter D. (peda)


Lesenswert?

Bit schrieb:
> //     Variablen um Stunden zu Zählen
> int h;
> // Variable für das Multiplexen
> long int Multiplexen;

Man muß den RAM nicht mit Gewalt zum Überlaufen bringen.
Mußt Du wirklich -32768..+32767 Stunden zählen?
Und wozu verwendest Du "Multiplexen", daß es von 
-2147483648..+2147483647 zählen muß?

von Rainer U. (r-u)


Lesenswert?

Bit schrieb:
> Mein Problem ist nun folgendes, das nichts passiert wenn ich den Taster
> drücke, egal ob lange <1s oder nur kurz >1s.

Mir scheint, Dir fehlt ein wenig Übung im debuggen. Allgemeine 
Techniken:

- LED da umschalten, wo das Programm regelmäßig vorbeikommt (ggf etwas 
bremsen, damit man das blinken noch sehen kann)
- einen Status auf zweiter LED anzeigen
- den Code immer weiter verkürzen (so lange Teile auskommentieren, bis 
es sich / die LEDs sich wie erwartet verhalten)
- danach einzelne Codeabschnitte wieder dazunehmen.

Irgendwann kommt dann immer der Moment, wo man sieht, wie man sich 
selbst ausgetrickst hat.

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

Man kann solche einfachen Programme aber auch im Simulator laufen lassen 
und sich alles angucken.
Am meisten rächt es sich aber, wenn man vorher keinen Programmablaufplan 
erstellt hat, sondern nur planlos in die Tastatur hackt.

von Bit (Gast)


Lesenswert?

Hallo zusammen also ich habe die Fehler nun gefunden
1
  while(1)
2
  {
3
4
//*****************************Zähler**************************************
5
      if (s>59) 
6
      {
7
        m++; 
8
        s=0; 
9
      }
10
      if (m>59) 
11
      {
12
        h++;  
13
        m=0; 
14
      }
15
      if (h>23) 
16
      {
17
        h=0; 
18
      }
19
//*****************************Anzeigenzuweisung**************************
20
      Transistoren [0] = Anzeige[s%10]; 
21
      Transistoren [1] = Anzeige[s/10]; 
22
      Transistoren [2] = Anzeige[m%10]; 
23
      Transistoren [3] = Anzeige[m/10]; 
24
      Transistoren [4] = Anzeige[h%10]; 
25
      Transistoren [5] = Anzeige[h/10]; 
26
//*****************************Multiplexen*******************************
27
      Multiplexen=0; // Setzt die Variable Multiplexen auf 0 zurück
28
      PORTB = 0xff; // PORTB wird eingeschaltet
29
      PORTD = Transistoren[nummer]; 
30
      PORTB &= ~(1<<nummer);
31
      nummer++; //Zählt die Variable Index +1
32
      if (nummer>=6) // wenn die Variable index größer gleich 6 ist wird die schleife ausgeführt
33
      {
34
        nummer=0; // Der Variablen wird der Wert 0 gegeben
35
      }
36
>>>  } 
37
//*****************************taster************************************  
38
  // Einschalten ***
39
  if (PINC & (1<<PC0)==1){ // Pinabfrage von PC0 trift diese zu führe schleife aus
40
  Eingeschaltet=1;}  // gibt der Variable "Eingeschaltet" den wert 1
41
  // hier fehlen noch befehle !!!
42
}   
43
44
ISR(TIMER1_COMPA_vect) // Interruptservicerutine
45
{
46
//*****************************Sekundenzähler****************************  
47
  //*** Einschalten ***
48
  if (Eingeschaltet==1){ // solange die Variable "Eingeschaltet" den wert 1 hatt wird die schleife ausgeführt
49
  s++;} // variable"s" wird um 1 nach oben gezehlt
50
}

An dieser Stelle (durch >>> markiert) habe ich meine while(1) Schleife 
geschlossen ich kam also niemals bis zur tasterabfragung.
Fehler Behoben ...

Desweiten habe ich bei der Initialisierung der Variablen nun allen 
Variablen den wert 0 gegeben (ich brauche dort eine 0).
könnt ein fehler gewesen sein ...

Beim Ausmessen der Ausgabe meiner PINC ist mir aufgefallen das PC0 und 
PC1 den selben wert (3) herrausgeben. Daraufhin  habe ich mir mein 
selbergebautes Entwicklungsboard nocheinmal angeschaut und festgestellt 
das ich zwischen PC0 und PC1 eine Lötbrücke hatte.
Lötbrücke entfernt und nun funktioniert wider alles so wie es soll.

Folgende funktionen sind nun möglich:

PC0 -> Startet die Stoppuhr
PC1 -> Stoppt das Programm
PC2 -> setzt das Programm aus 00.00.00 zurück

wenn ich die Stoppuhr gestartet habe (fängt an mit zählen ab 00.00.00 
aufwärtz) und ich mit PC1 Stoppe (z.B. bei 00.12.22) und nun erneut PC0 
drücke leuft die Stoppuhr weiter als hätte ich diese niemals angehalten
Wenn nun die Stoppuhr Läuft und ich PC2 drücke setzt sich die Stoppuhr 
aus 00.00.00 zurück und bleibt dort bis ich diese wider einschalte. (ist 
so gewollt ... momentan)


Peter D. schrieb:
> Man kann solche einfachen Programme aber auch im Simulator laufen
> lassen
> und sich alles angucken.
in der Tat das were eine gute idee gewesen habe das Problem aber auch 
ohne lösen konnen. Trozdem schau ich mich noch nach einem um.

> Am meisten rächt es sich aber, wenn man vorher keinen Programmablaufplan
> erstellt hat, sondern nur planlos in die Tastatur hackt.
nun ich habe sehr wohl einen Programmablaufplan erstellt

Zuletzt möchte ich mich noch bei Allen bedanken die mir bei der Lösung 
meines Problemes geholfen haben

von Achim S. (Gast)


Lesenswert?

Bit schrieb:
> Hallo zusammen also ich habe die Fehler nun gefunden
....
Bit schrieb:
> An dieser Stelle (durch >>> markiert) habe ich meine while(1) Schleife
> geschlossen ich kam also niemals bis zur tasterabfragung.
> Fehler Behoben ...

Ja. Und wenn du jetzt folgenden Abschnitt nochmal liest

Achim S. schrieb:
>> if (PINC & (1<<PC0)==1){ // Pinabfrage von PC0 trift diese zu führe
> ...
>
> dieser Code kommt nach der Schleife while(1). Da diese Schleife niemals
> beendet wird, wird dieser Code nie ausgeführt, Eingeschaltet bleibt also
> ewig auf 0.

merkst du, dass genau darauf hingewiesen wurdest :-)

von Bit (Gast)


Lesenswert?

Achim S. schrieb:
> Bit schrieb:
>> Hallo zusammen also ich habe die Fehler nun gefunden
> ....
> Bit schrieb:
>> An dieser Stelle (durch >>> markiert) habe ich meine while(1) Schleife
>> geschlossen ich kam also niemals bis zur tasterabfragung.
>> Fehler Behoben ...
>
> Ja. Und wenn du jetzt folgenden Abschnitt nochmal liest
>
> Achim S. schrieb:
>>> if (PINC & (1<<PC0)==1){ // Pinabfrage von PC0 trift diese zu führe
>> ...
>>
>> dieser Code kommt nach der Schleife while(1). Da diese Schleife niemals
>> beendet wird, wird dieser Code nie ausgeführt, Eingeschaltet bleibt also
>> ewig auf 0.
>
> merkst du, dass genau darauf hingewiesen wurdest :-)

Ja durch diesen Post bin ich überhaupt darauf gestoßen ^^ ohne würde ich 
warscheinlich immernoch suchen ...
ich wollte in meinem letzten Beitrag nur auf die gravierendsten Fehler 
in meinem programm hinweisen.

von Bit (Gast)


Lesenswert?

Und der Hardware...

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.