Forum: Mikrocontroller und Digitale Elektronik erstes C-Programm läuft nicht am AVR


von Michael R. (michir)


Angehängte Dateien:

Lesenswert?

Hallo @ Forum,

seit nicht all zu langer Zeit habe Ich mich dazu ermutigt mit dem 
Programmieren zu beginnen :)

Habe das Pollin Board mit nem ATMega 16 und benutze den USB_Programer 
zum flashen.

Nun mal zu meiner Angelegenheit...

Habe ein Programm geschrieben was auch funktioniert hat. Das Programm 
hat nur die beiden LED´s auf dem Pollin Board in folgender Weise Blinken 
lassen:

0. beide LED´s aus
1. LED 1 an
2. LED2 an und LD 1 aus
3. beide LED´s an

das ganze wird über einen Taster eingeschaltet und das blinken der LED´s 
läuft so lange bis ich das Pogramm über nen 2ten Taster stoppe. Das 
Programm hatte nur keine Tastenentprellung.

Also habe ich das benannte Programm nur mit einer Tastenentprellung 
versehen. Und das modifizierte Programm läuft eben nich...

Mal noch zur erläuterung des Problemprogramms:

max_count bezeichnet die Zählervariable die für das Array counter[] 
notwendig ist.

Das Programm wird zyklisch über die ISR ausgeführt und scannt alle 
Tasten (in meinem Falle gerade nur 2)

Prellt die Taste nicht wird der Zähler bis auf 5 erhöht, und schaltet in 
diesem falle eine stelle des Arrays outputs[] auf eins was signalisiert 
das die Taste ohne Prellen gedrückt wurde. Prellt die Taste wird das der 
counter zurückgesetzt.

Die Funktion blinken ist wie der name schon sagt für das Blinken der 
LED´s verantwortlich.

Falls es noch fragen geben sollte kann ich das gerne noch erläutern :)

Nun liegt an euch :) denn ich weiß nicht mehr was ich noch versuchen 
soll....

Ich bedanke mich für jeden Tipp der weiterhelfen könnte.

mfg und schön Abend noch.
Michael

von Karl H. (kbuchegg)


Lesenswert?

Wirf mal alles raus, was nicht unmittelbar mit den Tasten zu tun
hat. Dadurch bekommst du die LED frei, damit dir das Programm
'Nachrichten zuspielen' kann.

Als erstes solltest du mal prüfen, ob die ISR auch aufgerufen
wird. Wie kannst du das prüfen? Ganz einfach: Innerhalb der
ISR lässt du dir eine LED einschalten. Also zb. so
1
# include <avr/io.h>
2
# include <stdint.h>
3
# include <avr/interrupt.h>
4
5
ISR (TIMER0_OVF_vect)
6
{
7
  PORTD |= ( 1 << PD5 );
8
}
9
10
void main (void)
11
{
12
  DDRD  &= ~((1<<PD2) | (1<<PD3) | (1<<PD4));
13
  PORTD &= ~((1<<PD2) | (1<<PD3) | (1<<PD4));
14
  
15
  DDRD   |=  (1<<PD5) | (1<<PD6) | (1<<PD7);
16
  PORTD  &= ~((1<<PD5) | (1<<PD6) | (1<<PD7));
17
  
18
  TCCR0 |= (1<<CS00)|(1<<CS02);
19
  TIMSK = (1<<TOIE0);
20
21
  sei();
22
23
  while (1)
24
  {
25
  }
26
}

Bleibt die LED aus, dann wird die ISR nie aufgerufen und du hast
einen Ansatzpunkt an dem du Suchen kannst. Kommt die LED aber,
dann gehts weiter.

In deiner Originalen Routine schaltet die ISR die globale Variable
switch_check um. Erkennt das auch die Hauptschleife in main()?
Wieder: Nicht raten. Testen!
1
# include <avr/io.h>
2
# include <stdint.h>
3
# include <avr/interrupt.h>
4
5
# define max_count 5
6
7
void blinken (void);
8
void Taster (void);
9
10
volatile uint8_t flag;
11
volatile int8_t switch_check;
12
volatile int8_t a;
13
volatile int16_t counter[2];
14
volatile int16_t outputs[2];
15
16
17
ISR (TIMER0_OVF_vect)
18
{
19
  flag++;
20
  
21
  if (switch_check == 0)
22
  {
23
    switch_check = 1;
24
  }
25
}
26
27
void main (void)
28
{
29
  DDRD  &= ~((1<<PD2) | (1<<PD3) | (1<<PD4));
30
  PORTD &= ~((1<<PD2) | (1<<PD3) | (1<<PD4));
31
  
32
  DDRD   |=  (1<<PD5) | (1<<PD6) | (1<<PD7);
33
  PORTD  &= ~((1<<PD5) | (1<<PD6) | (1<<PD7));
34
  
35
  TCCR0 |= (1<<CS00)|(1<<CS02);
36
  TIMSK = (1<<TOIE0);
37
38
  sei();
39
  a = 0;
40
41
42
  while (1)
43
  {
44
    if (switch_check == 1)
45
    {
46
      PORTD |= ( 1 << PD5 );
47
    }
48
  }
49
}

Wenn die LED hier kommt, dann könnte das nächste Problem in der
Funktion Tasten liegen. Anstelle das kompliziert auszuwerten, lass
dir doch einfach mal die beiden output an den LED ausgeben
1
# include <avr/io.h>
2
# include <stdint.h>
3
# include <avr/interrupt.h>
4
5
# define max_count 5
6
7
void blinken (void);
8
void Taster (void);
9
10
volatile uint8_t flag;
11
volatile int8_t switch_check;
12
volatile int8_t a;
13
volatile int16_t counter[2];
14
volatile int16_t outputs[2];
15
16
17
ISR (TIMER0_OVF_vect)
18
{
19
  flag++;
20
  
21
  if (switch_check == 0)
22
  {
23
    switch_check = 1;
24
  }
25
}
26
27
void main (void)
28
{
29
  DDRD  &= ~((1<<PD2) | (1<<PD3) | (1<<PD4));
30
  PORTD &= ~((1<<PD2) | (1<<PD3) | (1<<PD4));
31
  
32
  DDRD   |=  (1<<PD5) | (1<<PD6) | (1<<PD7);
33
  PORTD  &= ~((1<<PD5) | (1<<PD6) | (1<<PD7));
34
  
35
  TCCR0 |= (1<<CS00)|(1<<CS02);
36
  TIMSK = (1<<TOIE0);
37
38
  sei();
39
  a = 0;
40
41
42
  while (1)
43
  {
44
    if (switch_check == 1)
45
    {
46
      Taster ();
47
      switch_check = 0;
48
    }
49
50
    if( outputs[0] == 1 )
51
      PORTD |= ( 1 << PD5 );
52
    else
53
      PORTD &= ~( 1 << PD5 );
54
    
55
    if( outputs[1] == 1 )
56
      PORTD |= ( 1 << PD6 );
57
    else
58
      PORTD &= ~( 1 << PD6 );
59
  }
60
}
61
62
void Taster (void)
63
{
64
  if (PIND & (1<<PD2))
65
  {
66
    if (counter[0] < max_count + 1)
67
    {
68
      counter[0]++;
69
    }
70
    
71
    if (counter[0] == max_count)
72
    {
73
      outputs[0] = 1;
74
    }
75
  }
76
  else 
77
  {
78
    counter[0] = 0;
79
  }
80
81
  if (PIND & (1<<PD3))
82
  {
83
    if (counter[1] < max_count + 1)
84
    {
85
      counter[1]++;
86
    }
87
    
88
    if (counter[1] == max_count)
89
    {
90
      outputs[1] = 1;
91
    }
92
  }
93
  else 
94
  {
95
    counter[1] = 0;
96
  }
97
  
98
  if (PIND & (1<<PD4))
99
  {
100
    if (counter[2] < max_count + 1)
101
    {
102
      counter[2]++;
103
    }
104
    
105
    if (counter[2] == max_count)
106
    {
107
      outputs[2] = 1;
108
    }
109
  }
110
  else 
111
  {
112
    counter[2] = 0;
113
  }
114
115
}

Was machen jetzt die LEDs. Spiegeln sie den Zustand der Tasten wieder?
Wenn nein, dann wird wohl die Tasten() Funktion der Schuldige sein.
Auch dort könnte man jetzt mal mit den LEDs nachsehen, was da passiert.
(ZB. indem man sich einen der beiden counter auf den 3 LED ausgeben
lässt. 3 LED sind 3 Bit und damit kann man bis 8 zählen. Deine counter
laufen aber nur bis 5, also reichen 3 Bits aus um alle Zählerstände
zu sehen).

Es ist wichtig, dass du selbst dir Techniken beibringst, wie du
dein Programm so attributieren kannst, daß dir das Programm mitteilt
was es gerade macht. Die wenigsten Programme laufen auf Anhieb
und auch wenn Nachdenken eine gute Methode ist um Fehlern auf die
Spur zu kommen, so hat es sich in der Praxis doch bewährt, wenn dir
das Programm selbst dabei hilft, Fehler zu finden.

von Michael R. (michir)


Lesenswert?

Hallo Karl Heinz,

da bin ich ja gerade an den richtigen geraten :)

Bin immer wieder positiv von deinen Beiträgen überrascht. Du 
erklärst/erläuterst den Erstellern des Threads immer auf eine gute Art 
und Weise das Problem und auch die Lösung. So auch in meinem Fall.

Aber ich wollte gerade den Thread bearbeiten... da hast du aber schon 
geschrieben. Denn ich hatte das Programm schonmal etwas umgeschrieben.

Habe schon wie du geschrieben hast eine LED in der ISR toggeln lassen. 
Das klappt soweit.

Habe dann die funktion blinken auskommentiert und da eine LED toggeln 
lassen. Das klappt auch.

if ((outputs[0] == 1) && (flag == 50))
    {
      //blinken();

      PORTD ^= ( 1 << PD5 );

      flag = 0;
    }

Aber sobald ich die Funktion wieder rein nehme is wieder alles im 
eimer...

Das entprellen der Tasten klappt eigentlich auch, denn wenn ich die 
funktion blinken rausnehme und nur die LED toggeln lasse kann ich die 
ohne Probleme an und auch wieder ausschalten.

werde aber gerne deine tipps befolgen und mal deine Programm teile mit 
einfügen.

bedanke mich schonmal für die schnelle Hilfe.

mfg
Michael

von G. L. (sprintersb)


Lesenswert?

was mir so beim Überfliegen auffällt
1
if (outputs[0] == 1 && flag >= 50)

geht auch nicht? Falls Du eine IRQ verpasst siehst du evtl sowas wie 
..48..49..51..

Und Kommentare würden es erleichtern daß Dir Leute helfen, die kein 
solchen Board haben.

D.2, D.3, D.4 sind Taster und D.5, D.6, D.7 sind LEDs? Sind die Taster 
low- oder high-active mit PullUp bzw. PullDown? Interne PullUps 
scheint's ja net zu brauchen...

von Karl H. (kbuchegg)


Lesenswert?

Georg-johann L. wrote:
> was mir so beim Überfliegen auffällt
>
>
1
> if (outputs[0] == 1 && flag >= 50)
2
>
>
> geht auch nicht? Falls Du eine IRQ verpasst siehst du evtl sowas wie
> ..48..49..51..

Auf sowas ähnliches hätte ich auch getippt.
Beim drüberlesen des Codes ist mir nichts aufgefallen, was nach
Fehler schreien würde.

von Michael R. (michir)


Lesenswert?

Hallo,

Sry das ich noch nix kommentiert habe in dem Programm

PD2 bis PD4 sind die 3 Taster auf dem Board. Ich verwende gerade nur 2 
für das Programm

PD5 und PD6 sind 2 LED´s und PD7 is ein Summer.

Die Taster sind übrigens über Pull-Down an den Controller angeschlossen.


if ((outputs[0] == 1) && (flag == 50))

kann schon sein das der zähler mal die 50 weglässt... durch was auch 
immer...

aber ich glaub nich das das immer passiert.

den ich hntte ja schonmal was getestet indem ich den aufruf der 
"blinken-funktion" unterbunden habe und stattdessen eine LED toggeln 
lasse. Und das hat 1a funktioniert. Die LED ist in einem 
gleichbleibenden Takt an und ausgegangen. Kann also denk ich mal nicht 
am Zähler in der ISR liegen.

Hatte das so gelöst:

if ((outputs[0] == 1) && (flag == 50))
    {
      //blinken();

      PORTD ^= ( 1 << PD5 );

      flag = 0;
    }


Aber wenn ich zu hause bin werde ich mir mal noch die Vorschläge von 
Karl Heinz zu gemüte führen.

Werde berichten wenn ich was rausgefunden habe.

mfg
Michael

von Karl H. (kbuchegg)


Lesenswert?

Noch eine Frage:
Mit welcher Taktfrequenz betreibst du deinen Mega16?

Damit man mal ein bischen rechnen kann :-)

von Michael R. (michir)


Lesenswert?

Uja hätt ich ja mal mit reinschreiben können:)

Der Mega16 wird mit 16MHz betrieben...

Wäre schön wenn du das mal durchrechnen könntest :) denn mit sowas kenn 
ich mich noch nich so aus... Also was wie lange dauert ect.

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.