Forum: Mikrocontroller und Digitale Elektronik schieberegister pwm


von Stk 500 anfänger (Gast)


Lesenswert?

hallo leute,
bin gerade dabei 3 leds über ein schieberegister (74HC595) anzusteuern. 
dazu hab ich jetzt mal folgendes programm geschrieben:
1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include <avr/interrupt.h>
4
5
6
//PB0 auf SER, PB1 auf SCK, PB2 auf RCK, PB3 auf SCL, PB4 auf G
7
8
9
ISR(TIMER0_OVF_vect)
10
{
11
12
13
14
PORTB |= (1<<PB4);
15
16
17
}
18
19
20
ISR(TIMER0_COMP_vect)
21
{
22
23
24
PORTB &=~ (1<<PB4);
25
26
27
}
28
29
30
31
inline uint8_t debounce(volatile uint8_t *port, uint8_t pin)
32
{
33
    if ( ! (*port & (1 << pin)) )
34
    {
35
        /* Pin wurde auf Masse gezogen, 100ms warten   */
36
        _delay_ms(50);  // max. 262.1 ms / F_CPU in MHz
37
        _delay_ms(50); 
38
        if ( *port & (1 << pin) )
39
        {
40
            /* Anwender Zeit zum Loslassen des Tasters geben */
41
            _delay_ms(50);
42
            _delay_ms(50); 
43
            return 1;
44
        }
45
    }
46
    return 0;
47
}
48
49
50
51
52
53
task_SCK(void)        // Bereitstellen von posiver Flanke an SCK- Eingang
54
{
55
56
57
  PORTB &=~(1<<PB1);  //SCK auf low
58
59
  PORTB |= (1<<PB1);  //SCK auf high
60
61
62
}
63
64
task_RCK(void)
65
{
66
67
PORTB &=~ (1<<PB2);    //RCK auf low
68
69
PORTB |= (1<<PB2);    //RCK auf high
70
71
}
72
73
74
75
int main(void)
76
{
77
78
DDRB = 0xFF;   //Gesamtes Portregister als Ausgang
79
DDRD = 0b11110000; // PD0 bis PD3 als Eingang
80
PORTB = 0b00000000;    //Alle Pins von PortB auf 0
81
PORTB |= (1<<PB3);    //SCL auf high => Reset von Schieberegister aus
82
83
84
85
TCCR0 |= (1<<COM01) | (1<<COM00);    // normal mode,  inverting mode
86
TCCR0 |= (1<<CS02);                //Prescaler auf 256
87
88
TIMSK |= (1<<TOIE0) | (1<<OCIE0);    // Interrupt bei Overflow und Compare Match
89
90
91
OCR0= 220;              //Auslösen von Compare Interrupt bei Vergleichswert 128
92
93
94
95
96
sei();                //globale Interrupts ein
97
98
99
100
while(1)
101
  {
102
103
if (debounce(&PIND, PD0))             /* Falls Taster an PIN PD0 gedrueckt..    */
104
   {
105
106
    PORTB |= (1<<PB3);    //Reset Schieberegister aus
107
    
108
109
    PORTB |= (1<<PB0);    //SER high
110
    task_SCK();
111
112
  _delay_ms(3);
113
114
  PORTB &=~ (1<<PB0);      //SER low
115
    task_SCK();
116
117
  _delay_ms(3);
118
119
  PORTB |= (1<<PB0);      //SER high (101 (QA bis QC))
120
    task_SCK();
121
  
122
  
123
task_RCK();
124
  
125
  }      
126
127
    
128
if (debounce(&PIND, PD1))              //Taster 1 gedrückt(entprellt)
129
  {  
130
    
131
132
  PORTB &=~(1<<PB3);    // Schieberegister RESET
133
134
  
135
136
  task_RCK();
137
138
139
  }
140
141
142
143
144
  }
145
  return 0;
146
147
148
149
150
}

das mit der PWM funktioniert auch schon ganz wunderbar. allerdings lässt 
sich das Schieberegister beim drücken von Taster 1 nicht löschen.

dass das löschen nicht funktioniert liegt allerdings nicht am 
schieberegister, sondern daran, dass PB3 beim drücken von Taster 1 nicht 
low wird.
ich bin mir ziemlich sicher, dass dieses fehlverhalten in zusammenhang 
mit meinem timer stehen muss. das löschen funktioniert nämlich, wenn ich 
in meinem programm auf das ganze PWM- Prozedere verzichte.

wer kann mir sagen warum das so ist, bzw. was ich machen kann, damit 
mein PB3 beim drücken von Taster 1 low wird wenn ich PWM verwende?

ich hoffe meine beschreibung war verständlich


mfg

von Spezi (Gast)


Lesenswert?

Welcher Controller?  Ein Schaltplan wäre hilfreich.

von Karl H. (kbuchegg)


Lesenswert?

Da hast keine internen Pullup Widerstände an den Tastern aktiviert.
Benutzt du externe?

von Stk 500 anfänger (Gast)


Lesenswert?

controller ist ein atmega16 mit eingestellten 8MHZ taktfrequenz. 
angeschlossen hab ich das schieberegister folgendermaßen:

-LED an QA
-LED an QB
-LED an QC
-PB0 auf SER
-PB1 auf SCK
-PB2 auf RCK
-PB3 auf SCL
-PB4 auf G


mfg

von Stk 500 anfänger (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Da hast keine internen Pullup Widerstände an den Tastern aktiviert.
> Benutzt du externe?

ich benutze direkt die taster am stk500.  diese sind an einen pullup 
widerstand von 10K angeschlossen.

mfg

von Spezi (Gast)


Lesenswert?

Hier ist das Problem:

> TCCR0 |= (1<<COM01) | (1<<COM00)

Damit schaltest du den Pin OC0 (= PB3) auf PWM-Ausgang.
Da du diesen Hardware-PWM-Pin nicht verwendest, sondern PB4 in den ISRs 
einstellst, können die 2 Bits auf 0 bleiben. Dann klappt es auch mit dem 
Reset-Pin.
Oder du tauscht die Pins PB3 und PB4 in der Funktion. Dann ist PB3 der 
PWM-Ausgang, und bei richtiger Konfiguration des Timers sind die beiden 
ISRs nicht mehr notwendig (da alles in Hardware abläuft).

Achte auf den Plan des Schieberegisters: sein Reset-Pin wirkt nur auf 
das Schieberegister selbst, nicht auf die Ausgangsregister. Um die 
zurückzusetzen, ist nach dem Reset noch ein RCK-Impuls nötig.

von Stk 500 anfänger (Gast)


Lesenswert?

Spezi schrieb:
> Hier ist das Problem:
>
>> TCCR0 |= (1<<COM01) | (1<<COM00)
>
> Damit schaltest du den Pin OC0 (= PB3) auf PWM-Ausgang.
> Da du diesen Hardware-PWM-Pin nicht verwendest, sondern PB4 in den ISRs
> einstellst, können die 2 Bits auf 0 bleiben. Dann klappt es auch mit dem
> Reset-Pin.

Respekt. jetzt funktioniert es. ich dachte ich muss die zwei bits 
setzen, weil im AVR- tutorial steht, dass man invertierendes PWM 
benutzen soll.

mfg

von Spezi (Gast)


Lesenswert?

Hallo,

> ich dachte ich muss die zwei bits setzen, weil im AVR- tutorial steht

Da hilft das Konsultieren des Controller-Datenblattes; es ist immer von 
Vorteil, nicht nur fertigen Code zu kopieren, sondern auch dessen 
Funktion zu verstehen ...   :-)

von Stk 500 anfänger (Gast)


Lesenswert?

Spezi schrieb:
> Da hilft das Konsultieren des Controller-Datenblattes; es ist immer von
> Vorteil, nicht nur fertigen Code zu kopieren, sondern auch dessen
> Funktion zu verstehen ...   :-)

das habe ich schon gemacht. fertigen code kopieren ohne ihn zu verstehen 
ist auch gar nicht mein ziel. nur bestimmte dinge, wie das jetzt hier, 
muss man halt fast schon einmal ausprobiert haben um sie zu verstehen.

mfg

von Stk 500 anfänger (Gast)


Lesenswert?

so, jetzt hab ich mein schieberegister- programm zu einem programm mit 
lauflicht erweitert:
1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include <avr/interrupt.h>
4
5
6
//PB0 auf SER, PB1 auf SCK, PB2 auf RCK, PB3 auf SCL, PB4 auf G
7
8
uint16_t Lauflicht;
9
10
ISR(TIMER0_OVF_vect)
11
{
12
13
14
15
PORTB |= (1<<PB4);
16
17
18
}
19
20
21
ISR(TIMER0_COMP_vect)
22
{
23
24
25
PORTB &=~ (1<<PB4);
26
27
28
}
29
30
31
32
inline uint8_t debounce(volatile uint8_t *port, uint8_t pin)
33
{
34
    if ( ! (*port & (1 << pin)) )
35
    {
36
        /* Pin wurde auf Masse gezogen, 100ms warten   */
37
        _delay_ms(50);  // max. 262.1 ms / F_CPU in MHz
38
        _delay_ms(50); 
39
        if ( *port & (1 << pin) )
40
        {
41
            /* Anwender Zeit zum Loslassen des Tasters geben */
42
            _delay_ms(50);
43
            _delay_ms(50); 
44
            return 1;
45
        }
46
    }
47
    return 0;
48
}
49
50
51
void long_delay(uint16_t ms)
52
{
53
54
for(;ms >0; ms--)
55
  {
56
57
  _delay_ms(1);
58
59
60
  }
61
62
63
}
64
65
66
task_SCK(void)        // Bereitstellen von posiver Flanke an SCK- Eingang
67
{
68
69
70
  PORTB &=~(1<<PB1);  //SCK auf low
71
72
  PORTB |= (1<<PB1);  //SCK auf high
73
74
75
}
76
77
task_RCK(void)
78
{
79
80
PORTB &=~ (1<<PB2);    //RCK auf low
81
82
PORTB |= (1<<PB2);    //RCK auf high
83
84
}
85
86
87
88
89
90
91
92
int main(void)
93
{
94
95
DDRB = 0xFF;   //Gesamtes Portregister als Ausgang
96
DDRD = 0b11110000; // PD0 bis PD3 als Eingang
97
PORTB = 0b00000000;    //Alle Pins von PortB auf 0
98
PORTB |= (1<<PB3);    //SCL auf high => Reset von Schieberegister aus
99
100
101
102
103
TCCR0 |= (1<<CS02);                //Prescaler auf 256
104
105
TIMSK |= (1<<TOIE0) | (1<<OCIE0);    // Interrupt bei Overflow und Compare Match
106
107
108
OCR0= 220;              //Auslösen von Compare Interrupt bei Vergleichswert 128
109
110
111
112
113
sei();                //globale Interrupts ein
114
115
116
117
while(1)
118
{
119
120
if (debounce(&PIND, PD0))             /* Falls Taster an PIN PD0 gedrueckt..    */
121
   {
122
  Lauflicht = 1;
123
  }  
124
125
126
if (debounce(&PIND, PD1))             //lauflicht abbrechen mit taster1
127
  {  
128
  
129
  Lauflicht = 0;
130
131
  PORTB &=~(1<<PB3);    // Schieberegister RESET
132
133
  
134
135
  task_RCK();
136
  
137
  
138
  }  
139
140
141
142
    if(Lauflicht ==1)
143
    {
144
  PORTB |= (1<<PB3);      //RESET aus
145
146
    PORTB |= (1<<PB0);    //SER  high , LED1 an
147
    task_SCK();
148
149
    task_RCK();
150
151
  long_delay(100);
152
153
  
154
155
  PORTB &=~ (1<<PB0);      //SER low, LED2 an
156
    task_SCK();
157
    task_RCK();
158
159
  long_delay(100);
160
  PORTB &=~ (1<<PB0);
161
    task_SCK();        //LED3an
162
    task_RCK();
163
164
  long_delay(100);    //LED4an
165
  PORTB &=~ (1<<PB0);
166
    task_SCK();
167
    task_RCK();
168
169
  long_delay(100);      //LED5an
170
  PORTB &=~ (1<<PB0);
171
    task_SCK();
172
    task_RCK();
173
174
  long_delay(100);      //LED6an
175
  PORTB &=~ (1<<PB0);
176
    task_SCK();
177
    task_RCK();
178
179
long_delay(100);      //LED7an
180
  PORTB &=~ (1<<PB0);
181
    task_SCK();
182
    task_RCK();
183
184
long_delay(100);      //LED8an
185
  PORTB &=~ (1<<PB0);
186
    task_SCK();
187
    task_RCK();
188
189
long_delay(100);
190
  PORTB &=~ (1<<PB0);
191
    task_SCK();
192
    task_RCK();
193
194
195
PORTB &=~ (1<<PB3);      //Schieberegister RESET
196
197
if(Lauflicht ==0)
198
  break;
199
200
    }
201
202
    
203
204
    
205
206
207
     
208
}
209
    
210
211
  return 0;
212
213
214
215
216
}

das mit dem lauflicht funktioniert soweit. allerdings würde mich 
interessieren, warum ich ins schieberegister 8 mal eine 0 reinschieben 
muss, damit das lauflicht bis zur 8. led läuft.
kann mir jemand erklären warum? hab schon im datenblatt und wiki 
nachgeforscht aber keinen grund gefunden.

dann habe ich noch ein anderes problem. und zwar möchte ich das 
lauflicht mit taster1(an PD1) abbrechen. doch leider läuft das lauflicht 
bisher beim drücken von taster1 ungehindert weiter.
es scheint mir so als würde das lauflicht die abbfrage von taster1 
blockieren.
an was liegt das bzw. wie kann ich dieses problem umgehen?

mfg

von Stk 500 anfänger (Gast)


Lesenswert?

.............................................

von Karl H. (kbuchegg)


Lesenswert?

Stk 500 anfänger schrieb:

> das mit dem lauflicht funktioniert soweit. allerdings würde mich
> interessieren, warum ich ins schieberegister 8 mal eine 0 reinschieben
> muss, damit das lauflicht bis zur 8. led läuft.

Was passiert denn wenn du eine 1 reinschreibst :-)
Welchen Schluss ziehst du daraus, wie ein Schieberegister eigentlich 
arbeitet.

> hab schon im datenblatt und wiki
> nachgeforscht aber keinen grund gefunden.

wie wärs mit ein bischen Nachdenken. Aus der Funktionsweise eines 
Schieberegisters ergibt sich völlig logisch warum das so ist.


schreibs einfacher so
1
int main(void)
2
{
3
  uint8_t i;
4
5
....
6
7
    if(Lauflicht ==1)
8
    {
9
      PORTB |= (1<<PB3);      //RESET aus
10
11
      PORTB |= (1<<PB0);    //SER  high , LED1 an
12
      task_SCK();
13
      task_RCK();
14
15
      for( i = 0; i < 8; ++i )
16
      {
17
        long_delay(100);
18
19
        PORTB &=~ (1<<PB0);      //SER low, LED2 an
20
        task_SCK();
21
        task_RCK();
22
      }
23
24
      PORTB &=~ (1<<PB3);      //Schieberegister RESET
25
26
      if(Lauflicht ==0)
27
        break;
28
    }
29
}

genau dafür wurden Schleifen erfunden, damit man nicht alles x-mal 
wiederholen muss. Dann kannst du auch einfacher experimentieren, indem 
du nur an einer Stelle die Anweisung ändern musst um anstelle einer 0 
lauter 1 nachzuschieben.

und achte ein wenig mehr auf deine Codeformatierung. Die ist ja 
grauenhaft.

> es scheint mir so als würde das lauflicht die abbfrage von taster1
> blockieren.

Nope.
Du hast einen Programmfehler bzw. einen Designfehler. Damit ein 
Tastendruck dein Lauflichtr jederzeit unterbrechen kann, musst du den 
ganzen Aufbau komplett anders gestalten. Im Moment registriert dein 
Programm einen Tastendruck nur dann, wenn genau zum Zeitpunkt, an dem es 
hier angelangt ist
1
if (debounce(&PIND, PD1))             //lauflicht abbrechen mit taster1
2
  {  
3
  
4
  Lauflicht = 0;
5
6
  PORTB &=~(1<<PB3);    // Schieberegister RESET
7
8
  
9
10
  task_RCK();
11
  
12
  
13
  }

die Taste an PD1 gedrückt ist. Wenn dein Programm aber die meiste Zeit 
mit den _delay_ms rumtrödelt, kommt es lange nicht an diese Stelle. 
Drück doch mal den Taster und halte ihn gedrückt.




Fang an deinen Code besser zu formatieren. Viele, viele Leerzeilen 
ziehen den Code nur in die Länge, bringen aber nicht mehr Übersicht.

von Stk 500 anfänger (Gast)


Lesenswert?

jetzt hab ich den code mal so geändert, wie du mir vorgeschlagen hast:
1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include <avr/interrupt.h>
4
5
6
//PB0 auf SER, PB1 auf SCK, PB2 auf RCK, PB3 auf SCL, PB4 auf G
7
8
uint16_t Lauflicht;
9
10
ISR(TIMER0_OVF_vect)
11
{
12
13
14
15
PORTB |= (1<<PB4);
16
17
18
}
19
20
21
ISR(TIMER0_COMP_vect)
22
{
23
24
25
PORTB &=~ (1<<PB4);
26
27
28
}
29
30
31
32
inline uint8_t debounce(volatile uint8_t *port, uint8_t pin)
33
{
34
    if ( ! (*port & (1 << pin)) )
35
    {
36
        /* Pin wurde auf Masse gezogen, 100ms warten   */
37
        _delay_ms(50);  // max. 262.1 ms / F_CPU in MHz
38
        _delay_ms(50); 
39
        if ( *port & (1 << pin) )
40
        {
41
            /* Anwender Zeit zum Loslassen des Tasters geben */
42
            _delay_ms(50);
43
            _delay_ms(50); 
44
            return 1;
45
        }
46
    }
47
    return 0;
48
}
49
50
51
void long_delay(uint16_t ms)
52
{
53
54
for(;ms >0; ms--)
55
  {
56
57
  _delay_ms(1);
58
59
60
  }
61
62
63
}
64
65
66
task_SCK(void)        // Bereitstellen von posiver Flanke an SCK- Eingang
67
{
68
69
70
  PORTB &=~(1<<PB1);  //SCK auf low
71
72
  PORTB |= (1<<PB1);  //SCK auf high
73
74
75
}
76
77
task_RCK(void)
78
{
79
80
PORTB &=~ (1<<PB2);    //RCK auf low
81
82
PORTB |= (1<<PB2);    //RCK auf high
83
84
}
85
86
87
88
89
90
91
92
int main(void)
93
{
94
95
DDRB = 0xFF;   //Gesamtes Portregister als Ausgang
96
DDRD = 0b11110000; // PD0 bis PD3 als Eingang
97
PORTB = 0b00000000;    //Alle Pins von PortB auf 0
98
PORTB |= (1<<PB3);    //SCL auf high => Reset von Schieberegister aus
99
100
101
102
103
TCCR0 |= (1<<CS02);                //Prescaler auf 256
104
105
TIMSK |= (1<<TOIE0) | (1<<OCIE0);    // Interrupt bei Overflow und Compare Match
106
107
108
OCR0= 220;              //Auslösen von Compare Interrupt bei Vergleichswert 128
109
110
111
112
113
sei();                //globale Interrupts ein
114
115
uint8_t i;
116
117
118
while(1)
119
{
120
121
if (debounce(&PIND, PD0))             /* Falls Taster an PIN PD0 gedrueckt..    */
122
   {
123
  Lauflicht = 1;
124
  }  
125
126
127
if (debounce(&PIND, PD1))
128
  {  
129
  
130
  Lauflicht = 0;
131
132
  PORTB &=~(1<<PB3);    // Schieberegister RESET
133
134
  
135
136
  task_RCK();
137
  
138
  
139
  }  
140
141
142
143
    if(Lauflicht ==1)
144
    {
145
  
146
    PORTB |= (1<<PB3);    //RESET aus
147
148
    PORTB |= (1<<PB0);    //SER high
149
150
    task_SCK();
151
    task_RCK();
152
153
154
      for(i=0; i<8; i++)
155
        {
156
157
        long_delay(100);
158
159
        PORTB &=~ (1<<PB0);    //SER low
160
        task_SCK();
161
        task_RCK();
162
163
164
        }
165
166
    PORTB &=~ (1<<PB3);    //RESET
167
    
168
169
    }
170
171
  if(Lauflicht ==0)
172
  break;
173
     
174
175
}  
176
177
  return 0;
178
179
180
181
182
}

allerdings geht jetzt nicht mal mehr das lauflicht. hab ich noch 
irgendwas vergessen zu ändern?

mfg

von Karl H. (kbuchegg)


Lesenswert?

Weiß ich nicht.
Solange du jetzt nicht anfängst deinen Code ein wenig übersichtlicher 
und durchschaubarer zu formatieren, weigere ich mich, mir den noch 
länger anzusehen.

von Falk B. (falk)


Lesenswert?

@  Stk 500 anfänger (Gast)

>jetzt hab ich den code mal so geändert, wie du mir vorgeschlagen hast:

Lies mal was über Netiquette. Längere Quelltexte gehören in den 
Anhang.

MFG
Falk

von Stk 500 anfänger (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Weiß ich nicht.
> Solange du jetzt nicht anfängst deinen Code ein wenig übersichtlicher
> und durchschaubarer zu formatieren, weigere ich mich, mir den noch
> länger anzusehen.
>
>
>
>
>
>     Beitrag melden | Bearbeiten | Löschen |
1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include <avr/interrupt.h>
4
5
6
//PB0 auf SER, PB1 auf SCK, PB2 auf RCK, PB3 auf SCL, PB4 auf G
7
8
uint16_t Lauflicht;
9
10
ISR(TIMER0_OVF_vect)
11
{
12
13
14
15
PORTB |= (1<<PB4);
16
17
18
}
19
20
21
ISR(TIMER0_COMP_vect)
22
{
23
24
25
PORTB &=~ (1<<PB4);
26
27
28
}
29
30
31
32
inline uint8_t debounce(volatile uint8_t *port, uint8_t pin)
33
{
34
    if ( ! (*port & (1 << pin)) )
35
    {
36
        /* Pin wurde auf Masse gezogen, 100ms warten   */
37
        _delay_ms(50);  // max. 262.1 ms / F_CPU in MHz
38
        _delay_ms(50); 
39
        if ( *port & (1 << pin) )
40
        {
41
            /* Anwender Zeit zum Loslassen des Tasters geben */
42
            _delay_ms(50);
43
            _delay_ms(50); 
44
            return 1;
45
        }
46
    }
47
    return 0;
48
}
49
50
51
void long_delay(uint16_t ms)
52
{
53
54
for(;ms >0; ms--)
55
  {
56
57
  _delay_ms(1);
58
59
60
  }
61
62
63
}
64
65
66
task_SCK(void)        // Bereitstellen von posiver Flanke an SCK- Eingang
67
{
68
69
70
  PORTB &=~(1<<PB1);  //SCK auf low
71
72
  PORTB |= (1<<PB1);  //SCK auf high
73
74
75
}
76
77
task_RCK(void)
78
{
79
80
PORTB &=~ (1<<PB2);    //RCK auf low
81
82
PORTB |= (1<<PB2);    //RCK auf high
83
84
}
85
86
87
88
89
90
91
92
int main(void)
93
{
94
95
DDRB = 0xFF;   //Gesamtes Portregister als Ausgang
96
DDRD = 0b11110000; // PD0 bis PD3 als Eingang
97
PORTB = 0b00000000;    //Alle Pins von PortB auf 0
98
PORTB |= (1<<PB3);    //SCL auf high => Reset von Schieberegister aus
99
100
101
102
103
TCCR0 |= (1<<CS02);                //Prescaler auf 256
104
105
TIMSK |= (1<<TOIE0) | (1<<OCIE0);    // Interrupt bei Overflow und Compare Match
106
107
108
OCR0= 220;              //Auslösen von Compare Interrupt bei Vergleichswert 128
109
110
111
112
113
sei();                //globale Interrupts ein
114
115
uint8_t i;
116
117
while(1)
118
{
119
120
    if (debounce(&PIND, PD0))             /* Falls Taster an PIN PD0 gedrueckt..    */
121
       {
122
        Lauflicht = 1;
123
        }  
124
125
126
      if (debounce(&PIND, PD1))             //lauflicht abbrechen mit taster1
127
        {   
128
          Lauflicht = 0;
129
          PORTB &=~(1<<PB3);    // Schieberegister RESET
130
          task_RCK();  
131
         }  
132
133
134
135
            if(Lauflicht ==1)
136
          {
137
            PORTB |= (1<<PB3);      //RESET aus
138
139
              PORTB |= (1<<PB0);    //SER  high , LED1 an
140
              task_SCK();
141
            task_RCK();
142
143
            long_delay(100);
144
145
              for(i=0; i<8; i++)
146
            {
147
     
148
             long_delay(100);
149
150
                PORTB &=~ (1<<PB0);      //SER low, LED2 an
151
                task_SCK();
152
                task_RCK();
153
154
155
156
            }
157
158
159
            PORTB &=~ (1<<PB3);      //Schieberegister RESET
160
161
          }
162
163
164
    if(Lauflicht ==0)
165
      break;
166
167
}
168
     
169
170
    
171
172
  return 0;
173
174
}

für mich zur übung und natürlich auch für dich. ich hoffe nun ist der 
code besser zu lesen.

mfg

von Karl H. (kbuchegg)


Lesenswert?

Stk 500 anfänger schrieb:

> für mich zur übung und natürlich auch für dich. ich hoffe nun ist der
> code besser zu lesen.

Nein. Ist er nicht.
Er ist immer noch so grauenhaft wie vorher.

von Stk 500 anfänger (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Stk 500 anfänger schrieb:
>
>> für mich zur übung und natürlich auch für dich. ich hoffe nun ist der
>> code besser zu lesen.
>
> Nein.
>
>
>
>
>
>     Beitrag melden | Bearbeiten | Löschen |


so vielleicht:
1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include <avr/interrupt.h>
4
5
6
//PB0 auf SER, PB1 auf SCK, PB2 auf RCK, PB3 auf SCL, PB4 auf G
7
8
uint16_t Lauflicht;
9
10
ISR(TIMER0_OVF_vect)
11
{
12
PORTB |= (1<<PB4);
13
}
14
15
    ISR(TIMER0_COMP_vect)
16
    {
17
    PORTB &=~ (1<<PB4);
18
    }
19
20
inline uint8_t debounce(volatile uint8_t *port, uint8_t pin)
21
{
22
    if ( ! (*port & (1 << pin)) )
23
    {
24
        /* Pin wurde auf Masse gezogen, 100ms warten   */
25
        _delay_ms(50);  // max. 262.1 ms / F_CPU in MHz
26
        _delay_ms(50); 
27
        if ( *port & (1 << pin) )
28
        {
29
            /* Anwender Zeit zum Loslassen des Tasters geben */
30
            _delay_ms(50);
31
            _delay_ms(50); 
32
            return 1;
33
        }
34
    }
35
    return 0;
36
}
37
38
void long_delay(uint16_t ms)
39
{
40
41
for(;ms >0; ms--)
42
  {
43
44
  _delay_ms(1);
45
46
47
  }
48
49
50
}
51
52
    task_SCK(void)        // Bereitstellen von posiver Flanke an SCK- Eingang
53
    {
54
        PORTB &=~(1<<PB1);  //SCK auf low
55
        PORTB |= (1<<PB1);  //SCK auf high
56
    }
57
58
      task_RCK(void)
59
      {
60
        PORTB &=~ (1<<PB2);    //RCK auf low
61
        PORTB |= (1<<PB2);    //RCK auf high
62
      }
63
64
int main(void)
65
{
66
67
DDRB = 0xFF;   //Gesamtes Portregister als Ausgang
68
DDRD = 0b11110000; // PD0 bis PD3 als Eingang
69
PORTB = 0b00000000;    //Alle Pins von PortB auf 0
70
PORTB |= (1<<PB3);    //SCL auf high => Reset von Schieberegister aus
71
72
TCCR0 |= (1<<CS02);                //Prescaler auf 256
73
TIMSK |= (1<<TOIE0) | (1<<OCIE0);    // Interrupt bei Overflow und Compare Match
74
75
OCR0= 220;              //Auslösen von Compare Interrupt bei Vergleichswert 128
76
77
sei();                //globale Interrupts ein
78
79
uint8_t i;
80
81
  while(1)
82
  {
83
84
    if (debounce(&PIND, PD0))             /* Falls Taster an PIN PD0 gedrueckt..    */
85
       {
86
        Lauflicht = 1;
87
        }  
88
89
90
      if (debounce(&PIND, PD1))             //lauflicht abbrechen mit taster1
91
        {   
92
          Lauflicht = 0;
93
          PORTB &=~(1<<PB3);    // Schieberegister RESET
94
          task_RCK();  
95
         }  
96
97
98
99
            if(Lauflicht ==1)
100
          {
101
            PORTB |= (1<<PB3);      //RESET aus
102
103
              PORTB |= (1<<PB0);    //SER  high , LED1 an
104
              task_SCK();
105
            task_RCK();
106
107
            long_delay(100);
108
109
                for(i=0; i<8; i++)
110
              {
111
                 long_delay(100);
112
                    PORTB &=~ (1<<PB0);      //SER low, LED2 an
113
                    task_SCK();
114
                    task_RCK();
115
              }
116
117
118
            PORTB &=~ (1<<PB3);      //Schieberegister RESET
119
120
        }
121
122
123
    if(Lauflicht ==0)
124
      break;
125
126
  }
127
     
128
  return 0;
129
130
}
zufrieden?

mfg

von Karl H. (kbuchegg)


Lesenswert?

Stk 500 anfänger schrieb:

> zufrieden?
>

Nein.

Was ist so schwer daran, ein konsitentes Einrückschema durchzuziehen?
Bei einer { gehts um 2 Leerzeichen nach rechts, bei einem } gehts wieder 
um 2 Leerzeichen nach links. Un dabgesehen davon stehen alle anderen 
Ding in ihrer jeweiligen Einrückstufe untereinander.

Dann kann man nämlich ganz leicht erkennen, welche Dinge 
zusammengehören, wo Schleifen anfangen und wo sie aufhören, welche Teile 
innerhalb einer Schleife sind, welche Programmteile von einem if 
abhängen und welche nicht.

Wenn ich wissen will, welche Programmteile zusammen einen Block bilden, 
schau ich einfach wo die zugehörigen { } eine Einrückebene weiter links 
sind und weiss es.

Wenigstens die Unmengen an Leerzeilen hast du zum größten Teil entfernt
1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include <avr/interrupt.h>
4
5
//PB0 auf SER, PB1 auf SCK, PB2 auf RCK, PB3 auf SCL, PB4 auf G
6
7
uint16_t Lauflicht;
8
 
9
ISR(TIMER0_OVF_vect)
10
{
11
  PORTB |= (1<<PB4);
12
}
13
 
14
ISR(TIMER0_COMP_vect)
15
{
16
  PORTB &=~ (1<<PB4);
17
}
18
 
19
inline uint8_t debounce(volatile uint8_t *port, uint8_t pin)
20
{
21
  if ( ! (*port & (1 << pin)) )
22
  {
23
    /* Pin wurde auf Masse gezogen, 100ms warten   */
24
    _delay_ms(50);  // max. 262.1 ms / F_CPU in MHz
25
    _delay_ms(50);
26
    if ( *port & (1 << pin) )
27
    {
28
      /* Anwender Zeit zum Loslassen des Tasters geben */
29
      _delay_ms(50);
30
      _delay_ms(50);
31
      return 1;
32
    }
33
  }
34
  return 0;
35
}
36
 
37
void long_delay(uint16_t ms)
38
{
39
  for(;ms >0; ms--)
40
  {
41
    _delay_ms(1);
42
  }
43
}
44
 
45
void task_SCK(void)        // Bereitstellen von posiver Flanke an SCK-Eingang
46
{
47
  PORTB &=~(1<<PB1);  //SCK auf low
48
  PORTB |= (1<<PB1);  //SCK auf high
49
}
50
 
51
void task_RCK(void)
52
{
53
  PORTB &=~ (1<<PB2);    //RCK auf low
54
  PORTB |= (1<<PB2);    //RCK auf high
55
}
56
 
57
int main(void)
58
{
59
  DDRB = 0xFF;   //Gesamtes Portregister als Ausgang
60
  DDRD = 0b11110000; // PD0 bis PD3 als Eingang
61
  PORTB = 0b00000000;    //Alle Pins von PortB auf 0
62
  PORTB |= (1<<PB3);    //SCL auf high => Reset von Schieberegister aus
63
  
64
  TCCR0 |= (1<<CS02);                //Prescaler auf 256
65
  TIMSK |= (1<<TOIE0) | (1<<OCIE0);    // Interrupt bei Overflow und  Compare Match
66
 
67
  OCR0= 220;              //Auslösen von Compare Interrupt bei  Vergleichswert 128
68
 
69
  sei();                //globale Interrupts ein
70
 
71
  uint8_t i;
72
 
73
  while(1)
74
  {
75
    if (debounce(&PIND, PD0))             /* Falls Taster an PIN PD0  gedrueckt..    */
76
    {
77
      Lauflicht = 1;
78
    }
79
 
80
    if (debounce(&PIND, PD1))             //lauflicht abbrechen mit taster1
81
    {
82
      Lauflicht = 0;
83
      PORTB &=~(1<<PB3);    // Schieberegister RESET
84
      task_RCK();
85
    }
86
87
    if(Lauflicht ==1)
88
    {
89
      PORTB |= (1<<PB3);      //RESET aus
90
      PORTB |= (1<<PB0);    //SER  high , LED1 an
91
      task_SCK();
92
      task_RCK();
93
94
      long_delay(100);
95
 
96
      for(i=0; i<8; i++)
97
      {
98
        long_delay(100);
99
        PORTB &=~ (1<<PB0);      //SER low, LED2 an
100
        task_SCK();
101
        task_RCK();
102
      }
103
104
      PORTB &=~ (1<<PB3);      //Schieberegister RESET
105
    }
106
107
    if(Lauflicht ==0)
108
      break;
109
  }
110
111
  return 0;
112
}

Und jetzt schau mal auf welcher Einrückebene deine Abfrage ganz unten ob 
Lauflicht gleich 0 ist steht und aus welcher Schleife daher 
hinausgebreakt wird. Vom break ausgehen die } in der nächsten 
Ausrückebene aufsuchen ( die } nehm ich weil sie näher liegt). Mit 
dieser Spaltenposition scroll ich dann nach oben, bis ich die zugehörige 
öffnende { in derselben Spalte gefunden habe und direkt darüber steht
1
  while(1)
also die allumfassende Endlosschleife.
Ist ja interessant, wenn Lauflicht 0 sein sollte (was zb bei 
Programmanfang der Fall ist), wird die Hauptschleife verlassen und dein 
Programm ist zu Ende.

Und das nächste mal machst du deine Einrückungen selber und siehst dann 
auch Fehler anstatt raten zu müssen.

von Stk 500 anfänger (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Was ist so schwer daran, ein konsitentes Einrückschema durchzuziehen?
> Bei einer { gehts um 2 Leerzeichen nach rechts, bei einem } gehts wieder
> um 2 Leerzeichen nach links. Un dabgesehen davon stehen alle anderen
> Ding in ihrer jeweiligen Einrückstufe untereinander.

ich hab immer gedacht, dass ich von oben beginnend jeden block weiter 
nach rechts einrücken muss. aber du beginnst ja die "großen Blöcke" ja 
auch immer wieder von links.
ok, ich glaube jetzt habe ich verstanden wie ich es machen muss.

Karl heinz Buchegger schrieb:
> Ist ja interessant, wenn Lauflicht 0 sein sollte (was zb bei
> Programmanfang der Fall ist), wird die Hauptschleife verlassen und dein
> Programm ist zu Ende.

stimmt du hast recht. jetzt hab ich Lauflicht anfangs den wert 2 
zugewiesen um dieses problem zu umgehen:
1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include <avr/interrupt.h>
4
5
//PB0 auf SER, PB1 auf SCK, PB2 auf RCK, PB3 auf SCL, PB4 auf G
6
7
uint16_t Lauflicht= 2;
8
 
9
ISR(TIMER0_OVF_vect)
10
{
11
  PORTB |= (1<<PB4);
12
}
13
 
14
ISR(TIMER0_COMP_vect)
15
{
16
  PORTB &=~ (1<<PB4);
17
}
18
 
19
inline uint8_t debounce(volatile uint8_t *port, uint8_t pin)
20
{
21
  if ( ! (*port & (1 << pin)) )
22
  {
23
    /* Pin wurde auf Masse gezogen, 100ms warten   */
24
    _delay_ms(50);  // max. 262.1 ms / F_CPU in MHz
25
    _delay_ms(50);
26
    if ( *port & (1 << pin) )
27
    {
28
      /* Anwender Zeit zum Loslassen des Tasters geben */
29
      _delay_ms(50);
30
      _delay_ms(50);
31
      return 1;
32
    }
33
  }
34
  return 0;
35
}
36
 
37
void long_delay(uint16_t ms)
38
{
39
  for(;ms >0; ms--)
40
  {
41
    _delay_ms(1);
42
  }
43
}
44
 
45
void task_SCK(void)        // Bereitstellen von posiver Flanke an SCK-Eingang
46
{
47
  PORTB &=~(1<<PB1);  //SCK auf low
48
  PORTB |= (1<<PB1);  //SCK auf high
49
}
50
 
51
void task_RCK(void)
52
{
53
  PORTB &=~ (1<<PB2);    //RCK auf low
54
  PORTB |= (1<<PB2);    //RCK auf high
55
}
56
 
57
int main(void)
58
{
59
  DDRB = 0xFF;   //Gesamtes Portregister als Ausgang
60
  DDRD = 0b11110000; // PD0 bis PD3 als Eingang
61
  PORTB = 0b00000000;    //Alle Pins von PortB auf 0
62
  PORTB |= (1<<PB3);    //SCL auf high => Reset von Schieberegister aus
63
  
64
  TCCR0 |= (1<<CS02);                //Prescaler auf 256
65
  TIMSK |= (1<<TOIE0) | (1<<OCIE0);    // Interrupt bei Overflow und  Compare Match
66
 
67
  OCR0= 220;              //Auslösen von Compare Interrupt bei  Vergleichswert 128
68
 
69
  sei();                //globale Interrupts ein
70
 
71
  uint8_t i;
72
 
73
  while(1)
74
  {
75
    if (debounce(&PIND, PD0))             /* Falls Taster an PIN PD0  gedrueckt..    */
76
    {
77
      Lauflicht = 1;
78
    }
79
 
80
    if (debounce(&PIND, PD1))             //lauflicht abbrechen mit taster1
81
    {
82
      Lauflicht = 0;
83
      PORTB &=~(1<<PB3);    // Schieberegister RESET
84
      task_RCK();
85
    }
86
87
    if(Lauflicht ==1)
88
    {
89
      PORTB |= (1<<PB3);      //RESET aus
90
      PORTB |= (1<<PB0);    //SER  high , LED1 an
91
      task_SCK();
92
      task_RCK();
93
94
      long_delay(100);
95
 
96
      for(i=0; i<8; i++)
97
      {      
98
        PORTB &=~ (1<<PB0);      //SER low, LED2 an
99
        task_SCK();
100
        task_RCK();
101
    long_delay(100);
102
    
103
      }
104
105
      PORTB &=~ (1<<PB3);      //Schieberegister RESET
106
107
    if(Lauflicht ==0)
108
      break;
109
    }
110
111
    
112
  }
113
114
  return 0;
115
}

das lauflicht läuft nun wieder. allerdings funktioniert der abbruch des 
lauflichts(ausgelöst durch
1
if(Lauflicht ==0)
2
      break;
) noch immer nicht.if(Lauflicht ==0)
      break;der for- schleife hängt und damit die wahrscheinlichkeit 
relativ gering ist, dass ich genau in dem moment taster1 drücke, wenn 
das programm ihn abfrägt.   ich habe jetzt schon alles probiert. hab 
diesen teil auch schon in die
1
if(Lauflicht ==0)break;
 auch schon in die for- schleife verschoben aber das lauflicht läuft 
beim drücken von taster1 ungehindert weiter.
irgendwie muss man dieses problem doch umgehen können. was schlägt ihr 
vor?

mfg

von Stk 500 anfänger (Gast)


Lesenswert?

.........................................

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.