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
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
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
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.
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
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 ... :-)
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
/* Anwender Zeit zum Loslassen des Tasters geben */
42
_delay_ms(50);
43
_delay_ms(50);
44
return1;
45
}
46
}
47
return0;
48
}
49
50
51
voidlong_delay(uint16_tms)
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
intmain(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
return0;
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
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
intmain(void)
2
{
3
uint8_ti;
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.
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.
@ 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
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
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.
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
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
/* Anwender Zeit zum Loslassen des Tasters geben */
29
_delay_ms(50);
30
_delay_ms(50);
31
return1;
32
}
33
}
34
return0;
35
}
36
37
voidlong_delay(uint16_tms)
38
{
39
for(;ms>0;ms--)
40
{
41
_delay_ms(1);
42
}
43
}
44
45
voidtask_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
voidtask_RCK(void)
52
{
53
PORTB&=~(1<<PB2);//RCK auf low
54
PORTB|=(1<<PB2);//RCK auf high
55
}
56
57
intmain(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_ti;
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
return0;
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.
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
/* Anwender Zeit zum Loslassen des Tasters geben */
29
_delay_ms(50);
30
_delay_ms(50);
31
return1;
32
}
33
}
34
return0;
35
}
36
37
voidlong_delay(uint16_tms)
38
{
39
for(;ms>0;ms--)
40
{
41
_delay_ms(1);
42
}
43
}
44
45
voidtask_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
voidtask_RCK(void)
52
{
53
PORTB&=~(1<<PB2);//RCK auf low
54
PORTB|=(1<<PB2);//RCK auf high
55
}
56
57
intmain(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_ti;
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
return0;
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