Hallo,
Ich habe dies vorher in ein weniger geeignetes Forum geschrieben, tut
mir Leid, nun noch mal.
Ich habe ein kleines Problem das ich nicht ganz verstehe. Ich arbeite an
einem Programm wo man per Tasten, verschiedene Buchstaben zu einer
String hinzufügen kann. Hat man 20 Characters erreicht, so bricht der
input loop ab und es geht in den output loop. Bis hier funktioniert
alles bestens da meine Entprellroutine gut funktioniert (ich entprelle
einfach mehrere Ports gleichzeitig). Nur manchmal wenn ich richtig stark
auf die taste hämmer sodass es ganz schnell geht, springt er wieder zum
Anfang des input modes zurück und ich habe keine Ahnung warum. Danach
kann ich auch noch so langsam drücken und das was beim output mode
erscheinen soll (ein paar LEDs leuchten dann auf) flackert nur kurz auf
und man ist wieder im input mode.
Ich programmiere einen ATmega 2560.
Hier ist mein main.c file:
// If the max string size has been reached, switch to output mode.
43
if (stringSz > MAX_STRING_SIZE - 2)
44
{
45
inputMode = false;
46
outputMode = true;
47
}
48
}
49
50
// Append terminating null character to string.
51
inputString[MAX_STRING_SIZE - 1] = '\0';
52
53
while (outputMode)
54
{
55
PORTB = 0xFF;
56
}
57
58
return 0;
59
}
das Programm fängt wieder beim Eingabe mode an. Ich habe ein paar tests
mit LEDs gemacht und bin mir ziemlich sicher dass das Programm total
resettet, wenn ich nämlich das MSB in PORTL einfach mal auf HI setze
nachdem input mode verlassen wird, ist dieses nicht mehr Gesetzt wenn
dieser "Reset" auftritt. Manchmal habe ich das Problem garnicht, dann
zieh ich den Vcc Stecker, steck ihn wieder rein und dann taucht manchmal
das Problem auf. Ich verstehe nicht wodurch das ausgelöst werden könnte.
Ich hoffe einer von euch hat vielleicht schon mal Erfahrung mit etwas
Ähnlichem gemacht.
Gruß,
Shibby
Ich habe mich mal etwas schlauer gemacht. Ich denke kaum dass es an
einer unstabilen Spannungsquelle liegen kann. Ich benutze den ATmega2560
mit einem der Fertigboards von myAVR. Das Problem tritt sowohl bei
externer Spannungsquelle, als auch USB als Spannungsquelle auf.
Den Watchdog Timer habe ich nicht eingeschaltet (wie ja im Code zu sehe
ist). Auch die Ports die ich als input benutze (E und F) lösen denk ich
mal nicht einen Interrupt aus zu dem die ISR fehlt (was ja auch zum
reset führen würde). Laut Datenblatt haben die Pins dieser Ports zwar
spezielle Eigenschaften (zB für den AD-Wandler) aber diese muss man erst
aktivieren und das habe ich nicht getan.
Komisch ist halt, dass er direkt nach Ende der Eingabe den Reset
ausführt und ich kanns mir leider nicht erklären. Wenn auch irgend
jemand nur eine Vermutung hat, würde ich diese gerne hören.
Falls es hilft kann ich auch meinen gesamten Programmcode zur Verfügung
stellen.
Gruß,
Shibby
> da meine Entprellroutine gut funktioniert
Da würde ich nochmal mit einem Fragezeichen ansetzen...
Und warum nimmst du nicht einfach nur 1 Zustandsvariable mode.
Wenn z.B. mode == 0 dann Input, wenn mode == 1 dann Output.
Danke für eure Antworten,
Ich habe den kompletten Code hinzugefügt und die ein oder andere
vorgeschlagene Änderung vorgenommen.
Falls ihr den Code nicht runterladen wollt, fasse ich hier die
wichtigsten .c Files mal zusammen:
main.c (Das Hauptprogramm)
Timer0_Functions.c (Alles was mit entprellen und dem Timer zu tun hat)
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include "Defines.h"
4
#include "Timer0_Function_Prototypes.h"
5
6
#define MAXCHECKS 10
7
8
// state is used to compare the last MAXCHECKS states of the input port.
9
// index is used to index the array in the ISR.
10
volatile unsigned char statePORTE[MAXCHECKS];
11
volatile unsigned char statePORTF[MAXCHECKS];
12
volatile unsigned char stateIndex;
13
14
void InitTimer(void)
15
{
16
// Fill arrays with 1's.
17
for (int i = 0; i < MAXCHECKS; i++)
18
statePORTE[i] = 0xFF;
19
20
for (int i = 0; i < MAXCHECKS; i++)
21
statePORTF[i] = 0xFF;
22
23
stateIndex = 0;
24
25
// Set register bits.
26
TCCR0A = 0x02;
27
TCCR0B = 0x04;
28
OCR0A = 62;
29
TIMSK0 = 0x02;
30
}
31
32
// This function is used when you want to know which switches are debounced or not (PORTE).
33
char GetDebouncedStateE(void)
34
{
35
char debouncedState = 0x00;
36
37
for (int i = 0; i < MAXCHECKS; i++)
38
debouncedState |= statePORTE[i];
39
40
return debouncedState;
41
}
42
43
// This function is used when you want to know which switches are debounced or not (PORTF).
44
char GetDebouncedStateF(void)
45
{
46
char debouncedState = 0x00;
47
48
for (int i = 0; i < MAXCHECKS; i++)
49
debouncedState |= statePORTF[i];
50
51
return debouncedState;
52
}
53
54
// Interrupt Service Routine.
55
ISR(TIMER0_COMPA_vect)
56
{
57
// The ISR only updates the state array. Use GetDebouncedState to get current debounced status on port.
58
// Very important: Only increment stateIndex after the LAST array has had it's value set!
59
statePORTE[stateIndex] = PINE;
60
statePORTF[stateIndex++] = PINF;
61
62
if (stateIndex >= MAXCHECKS)
63
stateIndex = 0;
64
}
In der ISR werden nur die beiden arrays aktualisiert. Wenn ich den
entprellten Status eines Ports haben möchte, dann verwende ich die
entsprechende Funktion (GetDebouncedStateE() oder GetDebouncedStateF()).
Ich weiß nicht mehr genau wie lange entprellt wird, da muss ich nochmal
meine Settings im Datenblatt überprüfen, aber ich glaube es sind 20ms
was meiner Ansicht nach völlig ausreichend ist.
InputProc_Functions.c (Die Funktionen die für die Verarbeitung des
Inputs verantwortlich sind)
// "None" case cannont be handles as the function is never called under such a circumstance.
121
switch (keyPressed)
122
{
123
case Num0:
124
PORTB = 0x3F;
125
pInputString[*pStringSz] = '0';
126
break;
127
128
case Num1:
129
PORTB = 0x06;
130
pInputString[*pStringSz] = '1';
131
break;
132
133
case Num2:
134
PORTB = 0x5B;
135
pInputString[*pStringSz] = '2';
136
break;
137
138
case Num3:
139
PORTB = 0x4F;
140
pInputString[*pStringSz] = '3';
141
break;
142
143
case Num4:
144
PORTB = 0x66;
145
pInputString[*pStringSz] = '4';
146
break;
147
148
case Num5:
149
PORTB = 0x6D;
150
pInputString[*pStringSz] = '5';
151
break;
152
153
case Num6:
154
PORTB = 0x7D;
155
pInputString[*pStringSz] = '6';
156
break;
157
158
case Num7:
159
PORTB = 0x07;
160
pInputString[*pStringSz] = '7';
161
break;
162
163
case Num8:
164
PORTB = 0x7F;
165
pInputString[*pStringSz] = '8';
166
break;
167
168
case Num9:
169
PORTB = 0x6F;
170
pInputString[*pStringSz] = '9';
171
break;
172
173
case Plus:
174
PORTB = 0x73;
175
pInputString[*pStringSz] = '+';
176
break;
177
178
case Minus:
179
PORTB = 0x40;
180
pInputString[*pStringSz] = '-';
181
break;
182
183
case Multiply:
184
PORTB = 0x80;
185
pInputString[*pStringSz] = '*';
186
break;
187
188
case Divide:
189
PORTB = 0x52;
190
pInputString[*pStringSz] = '/';
191
break;
192
193
case LeftParenthesis:
194
PORTB = 0x39;
195
pInputString[*pStringSz] = '(';
196
break;
197
198
case RightParenthesis:
199
PORTB = 0x0F;
200
pInputString[*pStringSz] = ')';
201
break;
202
}
203
204
// Increment size by 1.
205
(*pStringSz)++;
206
}
Die Prototypen der Funktionen in den einzelnen source files befinden
sich in den entsprechenden Header Dateien. Tut mir Leid dass die
Comments auf Englisch sind, aber Englisch kann ich nunmal leider etwas
besser als Deutsch :).
Ich hoffe mit Hilfe dieser Infos könnt ihr mir helfen, ich bin noch ein
Anfänger und befinde mich schnell in einem Loch wenn ich auf solche
Probleme stoße, aber ich versuche jeden Tag dazu zu lernen weil ichs
einfach sehr interessant finde.
Gruß,
Shibby
Auch wenn ich mittelschnell auf die Taste drücke kommt es vor dass
dieser Reset ausgelöst wird. Ich habe grade den dritten Taster probiert
den ich vorher noch nicht verwendet habe und da ist der Reset auch
aufgetreten. Abgesehen von der Ineffizienz meines Codes muss sich da
irgendwo ein Fehler verbergen.
Gruß,
Shibby
>Abgesehen von der Ineffizienz meines Codes muss sich da>irgendwo ein Fehler verbergen.
Dann solltest du ihn am bsten komplett überarbeiten/neu schreiben...
Sehr lustig. Wenn ich das vorhaben würde interessiere ich mich trotzdem
für den Auslöser für den Reset. Wenn dein Auto total abkackt willste
doch bestimmt auch wissen was passiert ist damit du weißt worauf du beim
neuen besser achten muss.
Die InputProc_Functions.c Funktionen werde ich eh noch überarbeiten und
etwas schneller gestalten, aber ich bin meist etwas besessen von Fehlern
wenn sie auftreten.
Also kleiner Update, die Spannungsquelle ist stabil. Der Reset wird nur
vom Input in den Pins: E4, F5, F6, F7 ausgelöst. Ich habe ins Datenblatt
geschaut aber da stand nichts was ich noch nicht über diese Pins wusste.
Ich habe auch beide Ports gewechselt und es sind immer noch diese Pins
als Übertäter aufgetreten. Deswegen bin ich von einem Softwarefehler
ausgegangen, kann aber bei den Input-Verarbeitenden Funktionen nichts
erkennen und bin daher ratlos, ich glaube ich schreibe das ganze Ding
wirklich nochmal neu, aber obs was bringt, keine Ahnung.