Forum: Mikrocontroller und Digitale Elektronik UART + Tasterabfrage vertragen sich nicht


von Peter (Gast)


Lesenswert?

Hallo zusammen,

ich habe Programm geschrieben, dass 2 Taster einliest (Berücksichtigt 
ist das Pollen des Tasters)

Neben dem Einlesen des Tasters kommen anfragen (interruptgesteuert) üben 
den(?) UART. Bei einer bestimmten Bitfolge im Protokoll, soll das 
Program sich ändernde Tasterzustände übermitteln.

Auf Variablen mit volatile wurde geachtet.

Die Tasterabfrage funktioniert grundsätzlich. Allerdings kommt es 
mitunter vor, dass Zustandswechel nicht erkannt werden. Ich habe nun 
nochmal verschiedene Artikel über Interruots gelesen, um herauszufinden 
ob es Variablenprobleme gibt. Ich weiss, dass es Probleme geben kann, 
wenn der der C-Code in Assembler mehrere Befehle nach sich zieht. 
Allerdings habe ich deswegen um die Tasterabfrage die Interrupts 
ausgeschaltet.

Oder sehe ich vielleicht ein anderes Problem vor lauter Versteifung auf 
die Interrupts nicht?

Vielleicht könnt ihr mir helfen
1
//Für Variablen, die in beiden Modulen verwendet werden müsse
2
//Globale Variablen
3
volatile char uart_str_complete = 0;                     // 1 .. String komplett empfangen
4
volatile char uart_str_count = 0;
5
volatile char uart_string[20] = "";
6
7
char eingang1_flag = 0x01;          //Positiv oder Negativ
8
char eingang2_flag = 0x01;          //Als erstes Positiv
9
char eingang3_flag = 0x01;
10
char eingang4_flag = 0x01;
11
12
13
14
ISR(USART_RXC_vect)
15
{
16
  unsigned char nextChar;
17
  // Daten aus dem Puffer lesen
18
  nextChar = UDR;
19
  if( uart_str_complete == 0 ) {  // wenn uart_string gerade in Verwendung, neues Zeichen verwerfen
20
 
21
    // Daten werden erst in string geschrieben, wenn nicht String-Ende/max Zeichenlänge erreicht ist/string gerade verarbeitet wird
22
    if( //nextChar != '!' &&
23
        //nextChar != '\r' &&
24
    (nextChar != 0xFF) &&  (uart_str_count < 20 - 1 )) {
25
      uart_string[uart_str_count] = nextChar;
26
      uart_str_count++;
27
    }
28
    else {
29
      uart_string[uart_str_count] = '\0';
30
      uart_str_count = 0;
31
      uart_str_complete = 1;
32
    }
33
  }
34
}
35
36
37
38
und dann das Hauptprogramm:
39
40
  FOREVER_START
41
  //Tasten einlesen
42
  count++;
43
  cli();
44
  checkIncome();
45
  sei();
46
  if (uart_str_complete ==1) {
47
  
48
      if (uart_string[byte_start] == '#') {
49
        
50
        if (checkToken(uart_string) == 1) 
51
        {
52
          
53
          if (checkSum(uart_string) == 1)
54
          {
55
            writePort(uart_string);
56
            writeBack(answer_as_slave);
57
            //matrix_eingaenge = 0;        //löscht Informationen intern, weil schon verschickt wurde
58
            IchWarDavor = 1;
59
          }
60
          else {
61
            writeBack(answer_wrong_checksum);
62
          }
63
        }
64
        else if ((IchWarDavor == 1) && (checkToken != 1))
65
        {
66
          matrix_eingaenge = 0; IchWarDavor = 0;
67
        }
68
      }
69
      else {
70
        //uart_puts("Fehler");
71
        }
72
      
73
      
74
      uart_str_complete = 0;
75
76
      
77
  }
78
  FOREVER_END
79
80
81
82
83
und die EINLESEROUTINE
84
85
void checkIncome ()
86
{
87
  //Taster 1
88
  if (eingang1_flag == 0x01){                //positive Flanke
89
    if ((PIND & (1<<eingang1))&&((count % 20) == 0)){
90
      //PORTD ^= (1<<ausgang2);
91
      matrix_eingaenge ^= 0x01;            //sorgt dafür dass es umgesetzt wird
92
      eingang1_flag ^= 0x01;
93
    }
94
  }
95
  else {                          //negative Flanke
96
    if (!(PIND & (1<<eingang1))&&((count % 20) == 0)){
97
      //PORTD ^= (1<<ausgang2);
98
      matrix_eingaenge ^= 0x01;
99
      eingang1_flag ^= 0x01;
100
    }
101
  }
102
  //Taster 2
103
  if (eingang2_flag == 0x01){                //positive Flanke
104
    if ((PIND & (1<<eingang2))&&((count % 20) == 0)){
105
      //PORTD ^= (1<<ausgang3);
106
      matrix_eingaenge ^= 0x02;            //sorgt dafür dass es umgesetzt wird
107
      eingang2_flag ^= 0x01;
108
      
109
    }
110
  }
111
  else {                          //negative Flanke
112
    if (!(PIND & (1<<eingang2))&&((count % 20) == 0)){
113
      //PORTD ^= (1<<ausgang3);
114
      matrix_eingaenge ^= 0x02;
115
      eingang2_flag ^= 0x01;
116
    }
117
  }
118
  //Taster 3
119
  if (eingang3_flag == 0x01){                //positive Flanke
120
    if ((PIND & (1<<eingang3))&&((count % 20) == 0)){
121
      //PORTD ^= (1<<ausgang3);
122
      matrix_eingaenge ^= 0x04;            //sorgt dafür dass es umgesetzt wird
123
      eingang3_flag ^= 0x01;
124
    ;
125
    }
126
  }
127
  else {                          //negative Flanke
128
    if (!(PIND & (1<<eingang3))&&((count % 20) == 0)){
129
      //PORTD ^= (1<<ausgang3);
130
      matrix_eingaenge ^= 0x04;
131
      eingang3_flag ^= 0x01;
132
    }
133
  }

von Peter II (Gast)


Lesenswert?

1
 if (eingang1_flag == 0x01){                //positive Flanke
2
    if ((PIND & (1<<eingang1))&&((count % 20) == 0)){
3
      //PORTD ^= (1<<ausgang2);
4
      matrix_eingaenge ^= 0x01;            //sorgt dafür dass es umgesetzt wird
5
      eingang1_flag ^= 0x01;
6
    }
7
  }
8
  else {                          //negative Flanke
9
    if (!(PIND & (1<<eingang1))&&((count % 20) == 0)){
10
      //PORTD ^= (1<<ausgang2);
11
      matrix_eingaenge ^= 0x01;
12
      eingang1_flag ^= 0x01;
13
    }
14
  }
das sieht mir extrem umständlich aus.

wenn bei dir (count % 20) == 0 ist, dann wird auch bei einer erkannte 
Flanke die variable eingang1_flag nicht mit angepasst. Das führt dazu, 
das eingang1_flag nicht mehr synchron zur echten flanke ist.

So etwas solle man einfach setzen und nicht per xor.

(bin mir nicht 100%sicher - der code ist nicht schön zu lesen).

von Peter II (Gast)


Lesenswert?

Nachtrag:

ich würde es in der Art machen:
1
uint8_t tmp = (PIND & (1<<eingang1);
2
if ( eingang1_flag != tmp ) {
3
   eingang1_flag = tmp;
4
   // optional abfrage ob positive oder negative flanke
5
   // if ( tmp ) 
6
   matrix_eingaenge ^= 0x01; 
7
}

von Peter (Gast)


Lesenswert?

Hallo,

schonmal Danke für den Hilfeversuch, leider konnte der Tip das Problem 
nicht lösen, weiterhin zufällige Wechsel :(. Ich habe zusätzlich nun die 
count-Variable mit innerhalb der Interruptfreien Befehle gesetzt. 
Allerdings führt das auch zu keinem Ergebnis.

Gibt es weitere Ideen?

Gruss Peter

von Peter II (Gast)


Lesenswert?

Peter schrieb:
> Gibt es weitere Ideen?

zeig mal den geänderten code.

von Peter (Gast)


Lesenswert?

Hier ist der veränderte Code, habe dann zusätzlich nochmal geguckt, ob 
es vielleicht an dem Pollen liegen kann, daher den auskommentierte Teil.

Hinweis, aus Schaltungsgründen musste ich den Eingang2 verwenden
1
  /*
2
  if ((count % 50)==0){
3
    temp = (PIND & (1<<eingang2));
4
  }
5
  */
6
  uint8_t temp = 0;
7
  temp = (PIND & (1<<eingang2));
8
9
  if (eingang2_flag != temp){
10
    eingang2_flag = temp;
11
    matrix_eingaenge ^= 0x02;
12
    temp = 0;
13
  }

von Peter II (Gast)


Lesenswert?

dann versuche bitte noch mal genau zu beschreiben was nicht geht? 
Regiert der Taster zu oft oder gar nicht?

von Peter (Gast)


Lesenswert?

Das Drücken oder loslassen des Tasters wird grundsätzlich erkannt. Und 
es wird der Zustandswechsel auch korrekt über uart an den Rechner 
geschickt. Dieser schtickt die Anfrage mit einer Baudrate von 19200 etwa 
alle 20ms.

Das Problem ist:
Nicht jeder ZustandsWechsel (Drücken oder loslassen) wird erkannt und 
entsprechend über den Bus verschickt.

von Peter D. (peda)


Lesenswert?

Compilierbarer Code als Dateianhang.
Schaltplan ist auch sinnvoll.

Wir sind schließlich keine Hellseher.

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.