UART + Tasterabfrage vertragen sich nicht

Gast #3541666
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
  }
Gast #3541683
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).
Gast #3541691
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
}
Gast #3541800
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
Gast #3541821
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
  }
Gast #3541848
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren