www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Unerklärter Reset


Autor: Shibby (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "Defines.h"
#include "Timer0_Function_Prototypes.h"
#include "Port_Initialization_Function_Prototypes.h"
#include "InputProc_Function_Prototypes.h"
#include "Output_Function_Prototype.h"
#include "Key_Enum.h"

#define MAX_STRING_SIZE 20

int main(void)
{
  InitPorts();
  InitTimer();
  sei();

  // No key is pressed at the beginning.
  KeyPressed keyPressed = None;
  unsigned char debouncedStateE = 0xFF;
  unsigned char debouncedStateF = 0xFF;
  
  // Mode variables.
  bool inputMode = true;
  bool outputMode = false;

  // String to store characters.
  unsigned char inputString[MAX_STRING_SIZE];
  unsigned char stringSz = 0;

  while (inputMode)
  {
    debouncedStateE = GetDebouncedStateE();
    debouncedStateF = GetDebouncedStateF();
    
    if (GetInputE(&keyPressed, debouncedStateE))
      InputProc(keyPressed, inputString, &stringSz);  
    else if (GetInputF(&keyPressed, debouncedStateF))
      InputProc(keyPressed, inputString, &stringSz);
      
    // If the max string size has been reached, switch to output mode.
    if (stringSz > MAX_STRING_SIZE - 2)
    {
      inputMode = false;
      outputMode = true;
    }          
  }

  // Append terminating null character to string.
  inputString[MAX_STRING_SIZE - 1] = '\0';

  while (outputMode)
  {
    PORTB = 0xFF;
  }

  return 0;
}

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

Autor: Shibby (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

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

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Shibby (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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)
#include <avr/io.h>
#include <avr/interrupt.h>
#include "Defines.h"
#include "Timer0_Function_Prototypes.h"
#include "Port_Initialization_Function_Prototypes.h"
#include "InputProc_Function_Prototypes.h"
#include "Output_Function_Prototype.h"
#include "Key_Enum.h"

#define MAX_STRING_SIZE 20

int main(void)
{
  InitPorts();
  InitTimer();
  sei();

  // No key is pressed at the beginning.
  KeyPressed keyPressed = None;
  unsigned char debouncedStateE = 0xFF;
  unsigned char debouncedStateF = 0xFF;
  
  // Mode variable.
  unsigned char mode = 0;

  // String to store characters.
  unsigned char inputString[MAX_STRING_SIZE];
  unsigned char stringSz = 0;

  PORTL = 0x01;

  while (true)
  {
    while (mode == 0)
    {
      debouncedStateE = GetDebouncedStateE();
      debouncedStateF = GetDebouncedStateF();
    
      if (GetInputE(&keyPressed, debouncedStateE))
        InputProc(keyPressed, inputString, &stringSz);  
      else if (GetInputF(&keyPressed, debouncedStateF))
        InputProc(keyPressed, inputString, &stringSz);
      
      // If the max string size has been reached, switch to output mode.
      if (stringSz > MAX_STRING_SIZE - 2)
      {
        mode = 1;
      }          
    }

    // Append terminating null character to string.
    inputString[MAX_STRING_SIZE - 1] = '\0';

    PORTL = 0x80;

    while (mode == 1)
    {
      OutputString(inputString, stringSz);
    }
  }

  return 0;
}

Port_Initialization_Function.c (Ports konfigurieren)
#include <avr/io.h>
#include "Port_Initialization_Function_Prototypes.h"

void InitPorts(void)
{
  DDRB = 0xFF;
  PORTB = 0x00;

  DDRL = 0xFF;
  PORTL = 0x00;

  DDRE = 0x00;
  PORTE = 0xFF;

  DDRF = 0x00;
  PORTF = 0xFF;
}

Timer0_Functions.c (Alles was mit entprellen und dem Timer zu tun hat)
#include <avr/io.h>
#include <avr/interrupt.h>
#include "Defines.h"
#include "Timer0_Function_Prototypes.h"

#define MAXCHECKS 10

// state is used to compare the last MAXCHECKS states of the input port.
// index is used to index the array in the ISR.
volatile unsigned char statePORTE[MAXCHECKS];
volatile unsigned char statePORTF[MAXCHECKS];
volatile unsigned char stateIndex;

void InitTimer(void)
{
  // Fill arrays with 1's.
  for (int i = 0; i < MAXCHECKS; i++)
    statePORTE[i] = 0xFF;

  for (int i = 0; i < MAXCHECKS; i++)
    statePORTF[i] = 0xFF;

  stateIndex = 0;

  // Set register bits.
  TCCR0A = 0x02;
  TCCR0B = 0x04;
  OCR0A = 62;
  TIMSK0 = 0x02;
}

// This function is used when you want to know which switches are debounced or not (PORTE).
char GetDebouncedStateE(void)
{
  char debouncedState = 0x00;

  for (int i = 0; i < MAXCHECKS; i++)
    debouncedState |= statePORTE[i];

  return debouncedState;
}

// This function is used when you want to know which switches are debounced or not (PORTF).
char GetDebouncedStateF(void)
{
  char debouncedState = 0x00;

  for (int i = 0; i < MAXCHECKS; i++)
    debouncedState |= statePORTF[i];

  return debouncedState;
}

// Interrupt Service Routine.
ISR(TIMER0_COMPA_vect)
{
  // The ISR only updates the state array. Use GetDebouncedState to get current debounced status on port.
  // Very important: Only increment stateIndex after the LAST array has had it's value set!
  statePORTE[stateIndex] = PINE;
  statePORTF[stateIndex++] = PINF;

  if (stateIndex >= MAXCHECKS)
    stateIndex = 0;
}


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)
#include <avr/io.h>
#include "Defines.h"
#include "Key_Enum.h"
#include "InputProc_Function_Prototypes.h"

bool GetInputE(KeyPressed* pKeyPressed, unsigned char debouncedStateE)
{
  // i represents the pin to be checked.
  for (int i = 0; i < 8; i++)
  {
    if (!(debouncedStateE & (1 << i)) && *pKeyPressed == None)
    {
      switch (i)
      {
        case 0:
          *pKeyPressed = Num0;
          return true;

        case 1:
          *pKeyPressed = Num1;
          return true;

        case 2:
          *pKeyPressed = Num2;
          return true;

        case 3:
          *pKeyPressed = Num3;
          return true;

         case 4:
          *pKeyPressed = Num4;
          return true;

         case 5:
          *pKeyPressed = Num5;
          return true;

         case 6:
          *pKeyPressed = Num6;
          return true;

         case 7:
          *pKeyPressed = Num7;
          return true;
      }
    }
    else if (debouncedStateE & (1 << i) && *pKeyPressed - 1 == i)
    {
      // If we arrive here, it means that the bit being checked is NOT set,
      // i.e. the button is not pressed or debounced BUT *pKeyPressed says that it is.
      // This means the key was previously pressed and was released.
      *pKeyPressed = None;
    }
  }

  // No changes in keys being pressed (on this port). Some might have been released.
  return false;
}

bool GetInputF(KeyPressed* pKeyPressed, unsigned char debouncedStateF)
{
  // i represents the pin to be checked.
  for (int i = 0; i < 8; i++)
  {
    if (!(debouncedStateF & (1 << i)) && *pKeyPressed == None)
    {
      switch (i)
      {
        case 0:
          *pKeyPressed = Num8;
          return true;

        case 1:
          *pKeyPressed = Num9;
          return true;

        case 2:
          *pKeyPressed = Plus;
          return true;

        case 3:
          *pKeyPressed = Minus;
          return true;

         case 4:
          *pKeyPressed = Multiply;
          return true;

         case 5:
          *pKeyPressed = Divide;
          return true;

         case 6:
          *pKeyPressed = LeftParenthesis;
          return true;

         case 7:
          *pKeyPressed = RightParenthesis;
          return true;
      }
    }
    else if (debouncedStateF & (1 << i) && *pKeyPressed - Num8 == i)
    {
      // Notice + Num8 here. Num8 and up are the integer values 9 and up in the enum KeyPressed.
      // If we arrive here, it means that the bit being checked is NOT set,
      // i.e. the button is not pressed or debounced BUT *pKeyPressed says that it is.
      // This means the key was previously pressed and was released.
      *pKeyPressed = None;
    }
  }

  // No changes in keys being pressed (on this port). Some might have been released.
  return false;
}  

// This function processes input.
void InputProc(KeyPressed keyPressed, unsigned char* pInputString, unsigned char* pStringSz)
{
  // "None" case cannont be handles as the function is never called under such a circumstance.
  switch (keyPressed)
  {
    case Num0:
      PORTB = 0x3F;
      pInputString[*pStringSz] = '0';
      break;
    
    case Num1:
      PORTB = 0x06;
      pInputString[*pStringSz] = '1';
      break;

    case Num2:
      PORTB = 0x5B;
      pInputString[*pStringSz] = '2';
      break;
    
    case Num3:
      PORTB = 0x4F;
      pInputString[*pStringSz] = '3';
      break;

    case Num4:
      PORTB = 0x66;
      pInputString[*pStringSz] = '4';
      break;
    
    case Num5:
      PORTB = 0x6D;
      pInputString[*pStringSz] = '5';
      break;

    case Num6:
      PORTB = 0x7D;
      pInputString[*pStringSz] = '6';
      break;
    
    case Num7:
      PORTB = 0x07;
      pInputString[*pStringSz] = '7';
      break;

    case Num8:
      PORTB = 0x7F;
      pInputString[*pStringSz] = '8';
      break;
    
    case Num9:
      PORTB = 0x6F;
      pInputString[*pStringSz] = '9';
      break;

    case Plus:
      PORTB = 0x73;
      pInputString[*pStringSz] = '+';
      break;

    case Minus:
      PORTB = 0x40;
      pInputString[*pStringSz] = '-';
      break;

    case Multiply:
      PORTB = 0x80;
      pInputString[*pStringSz] = '*';
      break;

    case Divide:
      PORTB = 0x52;
      pInputString[*pStringSz] = '/';
      break;

    case LeftParenthesis:
      PORTB = 0x39;
      pInputString[*pStringSz] = '(';
      break;

    case RightParenthesis:
      PORTB = 0x0F;
      pInputString[*pStringSz] = ')';
      break;
  }

  // Increment size by 1.
  (*pStringSz)++;
}

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

Autor: special swine flu (Gast)
Datum:

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

Autor: Shibby (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: STK500-Besitzer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Abgesehen von der Ineffizienz meines Codes muss sich da
>irgendwo ein Fehler verbergen.

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

Autor: Shibby (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Shibby (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.