Forum: Mikrocontroller und Digitale Elektronik Unerklärter Reset


von Shibby (Gast)


Lesenswert?

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:
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <util/delay.h>
4
#include "Defines.h"
5
#include "Timer0_Function_Prototypes.h"
6
#include "Port_Initialization_Function_Prototypes.h"
7
#include "InputProc_Function_Prototypes.h"
8
#include "Output_Function_Prototype.h"
9
#include "Key_Enum.h"
10
11
#define MAX_STRING_SIZE 20
12
13
int main(void)
14
{
15
  InitPorts();
16
  InitTimer();
17
  sei();
18
19
  // No key is pressed at the beginning.
20
  KeyPressed keyPressed = None;
21
  unsigned char debouncedStateE = 0xFF;
22
  unsigned char debouncedStateF = 0xFF;
23
  
24
  // Mode variables.
25
  bool inputMode = true;
26
  bool outputMode = false;
27
28
  // String to store characters.
29
  unsigned char inputString[MAX_STRING_SIZE];
30
  unsigned char stringSz = 0;
31
32
  while (inputMode)
33
  {
34
    debouncedStateE = GetDebouncedStateE();
35
    debouncedStateF = GetDebouncedStateF();
36
    
37
    if (GetInputE(&keyPressed, debouncedStateE))
38
      InputProc(keyPressed, inputString, &stringSz);  
39
    else if (GetInputF(&keyPressed, debouncedStateF))
40
      InputProc(keyPressed, inputString, &stringSz);
41
      
42
    // 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

von Shibby (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

Du zeigst viel zu viel Code nicht, als das man da irgendetwas 
verlässliches sagen könnte.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> 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.

von Shibby (Gast)


Angehängte Dateien:

Lesenswert?

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)
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include "Defines.h"
4
#include "Timer0_Function_Prototypes.h"
5
#include "Port_Initialization_Function_Prototypes.h"
6
#include "InputProc_Function_Prototypes.h"
7
#include "Output_Function_Prototype.h"
8
#include "Key_Enum.h"
9
10
#define MAX_STRING_SIZE 20
11
12
int main(void)
13
{
14
  InitPorts();
15
  InitTimer();
16
  sei();
17
18
  // No key is pressed at the beginning.
19
  KeyPressed keyPressed = None;
20
  unsigned char debouncedStateE = 0xFF;
21
  unsigned char debouncedStateF = 0xFF;
22
  
23
  // Mode variable.
24
  unsigned char mode = 0;
25
26
  // String to store characters.
27
  unsigned char inputString[MAX_STRING_SIZE];
28
  unsigned char stringSz = 0;
29
30
  PORTL = 0x01;
31
32
  while (true)
33
  {
34
    while (mode == 0)
35
    {
36
      debouncedStateE = GetDebouncedStateE();
37
      debouncedStateF = GetDebouncedStateF();
38
    
39
      if (GetInputE(&keyPressed, debouncedStateE))
40
        InputProc(keyPressed, inputString, &stringSz);  
41
      else if (GetInputF(&keyPressed, debouncedStateF))
42
        InputProc(keyPressed, inputString, &stringSz);
43
      
44
      // If the max string size has been reached, switch to output mode.
45
      if (stringSz > MAX_STRING_SIZE - 2)
46
      {
47
        mode = 1;
48
      }          
49
    }
50
51
    // Append terminating null character to string.
52
    inputString[MAX_STRING_SIZE - 1] = '\0';
53
54
    PORTL = 0x80;
55
56
    while (mode == 1)
57
    {
58
      OutputString(inputString, stringSz);
59
    }
60
  }
61
62
  return 0;
63
}

Port_Initialization_Function.c (Ports konfigurieren)
1
#include <avr/io.h>
2
#include "Port_Initialization_Function_Prototypes.h"
3
4
void InitPorts(void)
5
{
6
  DDRB = 0xFF;
7
  PORTB = 0x00;
8
9
  DDRL = 0xFF;
10
  PORTL = 0x00;
11
12
  DDRE = 0x00;
13
  PORTE = 0xFF;
14
15
  DDRF = 0x00;
16
  PORTF = 0xFF;
17
}

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)
1
#include <avr/io.h>
2
#include "Defines.h"
3
#include "Key_Enum.h"
4
#include "InputProc_Function_Prototypes.h"
5
6
bool GetInputE(KeyPressed* pKeyPressed, unsigned char debouncedStateE)
7
{
8
  // i represents the pin to be checked.
9
  for (int i = 0; i < 8; i++)
10
  {
11
    if (!(debouncedStateE & (1 << i)) && *pKeyPressed == None)
12
    {
13
      switch (i)
14
      {
15
        case 0:
16
          *pKeyPressed = Num0;
17
          return true;
18
19
        case 1:
20
          *pKeyPressed = Num1;
21
          return true;
22
23
        case 2:
24
          *pKeyPressed = Num2;
25
          return true;
26
27
        case 3:
28
          *pKeyPressed = Num3;
29
          return true;
30
31
         case 4:
32
          *pKeyPressed = Num4;
33
          return true;
34
35
         case 5:
36
          *pKeyPressed = Num5;
37
          return true;
38
39
         case 6:
40
          *pKeyPressed = Num6;
41
          return true;
42
43
         case 7:
44
          *pKeyPressed = Num7;
45
          return true;
46
      }
47
    }
48
    else if (debouncedStateE & (1 << i) && *pKeyPressed - 1 == i)
49
    {
50
      // If we arrive here, it means that the bit being checked is NOT set,
51
      // i.e. the button is not pressed or debounced BUT *pKeyPressed says that it is.
52
      // This means the key was previously pressed and was released.
53
      *pKeyPressed = None;
54
    }
55
  }
56
57
  // No changes in keys being pressed (on this port). Some might have been released.
58
  return false;
59
}
60
61
bool GetInputF(KeyPressed* pKeyPressed, unsigned char debouncedStateF)
62
{
63
  // i represents the pin to be checked.
64
  for (int i = 0; i < 8; i++)
65
  {
66
    if (!(debouncedStateF & (1 << i)) && *pKeyPressed == None)
67
    {
68
      switch (i)
69
      {
70
        case 0:
71
          *pKeyPressed = Num8;
72
          return true;
73
74
        case 1:
75
          *pKeyPressed = Num9;
76
          return true;
77
78
        case 2:
79
          *pKeyPressed = Plus;
80
          return true;
81
82
        case 3:
83
          *pKeyPressed = Minus;
84
          return true;
85
86
         case 4:
87
          *pKeyPressed = Multiply;
88
          return true;
89
90
         case 5:
91
          *pKeyPressed = Divide;
92
          return true;
93
94
         case 6:
95
          *pKeyPressed = LeftParenthesis;
96
          return true;
97
98
         case 7:
99
          *pKeyPressed = RightParenthesis;
100
          return true;
101
      }
102
    }
103
    else if (debouncedStateF & (1 << i) && *pKeyPressed - Num8 == i)
104
    {
105
      // Notice + Num8 here. Num8 and up are the integer values 9 and up in the enum KeyPressed.
106
      // If we arrive here, it means that the bit being checked is NOT set,
107
      // i.e. the button is not pressed or debounced BUT *pKeyPressed says that it is.
108
      // This means the key was previously pressed and was released.
109
      *pKeyPressed = None;
110
    }
111
  }
112
113
  // No changes in keys being pressed (on this port). Some might have been released.
114
  return false;
115
}  
116
117
// This function processes input.
118
void InputProc(KeyPressed keyPressed, unsigned char* pInputString, unsigned char* pStringSz)
119
{
120
  // "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

von special swine flu (Gast)


Lesenswert?

Du hast oben von ''hammer'' gesprochen...du erzeugst dabei einen 
Wackelkontakt ....und ein Reset !

von Shibby (Gast)


Lesenswert?

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

von STK500-Besitzer (Gast)


Lesenswert?

>Abgesehen von der Ineffizienz meines Codes muss sich da
>irgendwo ein Fehler verbergen.

Dann solltest du ihn am bsten komplett überarbeiten/neu schreiben...

von Shibby (Gast)


Lesenswert?

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.

von Shibby (Gast)


Lesenswert?

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.

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.