Finde fehler nicht (UART - Attiny2313)

Gast #1662748
Lesenswert?

Guten Abend ! Ich versuche gerade eine Schrittmotorsteuerung aufzubauen 
und steuere den Motor mit Hilfe eines MicroControllers. Ich sende die 
Daten über RS232 an den µC (Attiny2313) und dieser steuert dann den L297 
an.

Mein Problem ist, dass in meinem Code die if-Bedingung in der Funktion: 
void parser(void) gar nicht "reagiert", obwohl rx_flag gesetzt ist.

Zur Überprüfung der einzelnen Stellen, sende ich vom µC zum PC immer 
einzelne Chars z.b. wie  UDR = 'i' für die Aussage, dass die Interrupt 
Routine ausgelöst hat und UDR = 'r' für die Aussage, dass das 
Ausrufungszeichen '!" angekommen ist. Ein ! bedeutet in meinem simplen, 
auch bestimmt nicht so tollen, Protokoll, dass ein Befehl vollständig 
angekommen ist. Wenn ich nun per HTERM an den µC die Zeichenfolge: d! 
schicke, erhalte ich als Status: iir , also zwei mal das i für die 
beiden gesendeten Chars (da die ISR Routine ja zwei mal anspringt) und 
das r, dass das Ausrufungszeichen angekommen ist. Nachdem das ! 
angekommen ist, wird rx_flag auf 1 gesetzt um somit mit dem Parsen der 
empfangen Daten anfangen zu können. Ich erwarte von meinem µC jetzt die 
Meldung: p  (UDR = 'p'), welche aber niemals ankommt... ich hoffe ich 
konnte damit mein Problem und die Funktionsweise des Programmes soweit 
erklären, dass es für eine Problemlösung verständlich ist.

Hier ist das Programm:
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <util/delay.h>
4

5

6
/* Defines bezüglich UART */
7
#define BAUD 9600UL      
8
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
9
/*---ENDE---*/
10

11

12
/* PORT Bezeichnungen für den L297 (Motortreiber) */
13
#define EN PD5
14
#define DIR PD4
15
#define CLK PD3
16
/*---ENDE---*/
17

18

19
/* Prototypen */
20
void init_uart(void);
21
void init_stepper(int en);
22
void turn_stepper(int direc,int steps);
23
void parser(void);
24
/*---ENDE---*/
25

26

27
/* Globale Variablen */
28
char received_data[10]; // Buffer wo die empfangenen Daten gespeichert werden...
29
int  rx_flag;     // Status-Flag für vollständig übertragene Befehle...
30
int i=0;    // Index-Variable für den Daten-Puffer
31
int stop_flag = 0;  // Stop-Flag um den Motor anzuhalten!
32
/*---ENDE---*/  
33

34

35

36
int main(void)
37
{
38

39
  DDRD |= (1<<EN) | (1<<DIR) | (1<<CLK); // Data Direction Register einstellen  
40
  
41
  init_uart();
42
    
43
  init_stepper(1); // Schrittmotor anschalten
44

45
  sei();
46
  
47
  UDR = 'm';  // MAIN Meldung
48
  
49
  while(1)
50
  {
51
    parser();
52
  }
53
  
54
}
55

56

57

58
/***** STEPPER CODE TEIL *****/
59
void init_stepper(int en)
60
{
61
  switch(en)
62
  {
63
    case 1: PORTD |= (1<<EN);
64
    break;
65
    case 0: PORTD &=~(1<<EN);
66
    break;
67
  //  default:
68
  }
69
}
70

71
void turn_stepper(int direc,int steps)
72
{
73
  
74
  int i = 0;
75
  
76
  PORTD |= (direc<<DIR);
77

78
  for(i=0;i<=steps;i++)
79
  {
80
    
81
    PORTD |= (1<<CLK);
82
    _delay_ms(1);
83
    PORTD &=~ (1<<CLK);
84
    _delay_ms(1);
85
  
86
  }
87

88
}
89

90

91

92

93
void parser(void)
94
{
95

96
  //_delay_ms(1000);
97
  
98
  
99
    
100
  if(rx_flag == 1) // Alle Daten empfangen, beginne mit Parsen !
101
  {
102
           
103

104
    UDR = 'p';
105
  
106
     switch (received_data[0])
107
     {    
108
             // Motor drehen.... Buchstabe "d"
109
       case 0x64:  
110
             UDR = 'd';
111
       turn_stepper(1,20);
112
    
113
       break;
114
     
115
       case 0x73: // Motor Stopp.... Buchstabe "s"
116
       stop_flag = 1;
117
       break;
118

119
       case 0x65: //Motor einschalten... Buchstabe "e"
120
       init_stepper(1);
121
       break;
122

123
       case 0x61: //Motor ausschalten... Buchstabe "a"
124
       init_stepper(0);
125
       break;
126

127
      // default:
128
     }
129
  
130
            rx_flag = 0; // Befehl ausgeführt, neue Daten dürfen ankommen       
131

132
       
133
    
134
 }
135
}
136

137

138
/***** UART CODE TEIL *****/
139

140
void init_uart()
141
{
142
      /*UART: 8 Datenbits; keine Parität; 1 Stopbit*/
143
  
144
  UCSRB |= (1<<RXCIE)|(1<<RXEN)|(1<<TXEN);
145
  UCSRC |= (3<<UCSZ0);
146

147
  UBRRH = UBRR_VAL >> 8;
148
  UBRRL = UBRR_VAL;
149
}
150

151

152
ISR(USART_RX_vect)
153
{
154
  received_data[i] = UDR; // Lade die empfangenen Bystes in den Daten-Puffer
155
  
156
  UDR = 'i';  
157

158
  if(received_data[i]==0x21) // !-Zeichen erhalten, Befehl fertig => Flag setzen.
159
  {
160
  UDR = 'r';
161
  rx_flag = 1;
162
  
163
  i=0;
164
  }
165
  else
166
  {
167
  i++;  
168
  }  
169
}

Danke !
Gast #1662779
Lesenswert?

Du prügelst Daten in UDR ohne darauf zu warten das die Daten
gesendet wurden:
1
  UDR = 'i';  
2

3
  if(received_data[i]==0x21) // !-Zeichen erhalten, Befehl fertig => Flag 
4
  {
5
   UDR = 'r';

Und hier
1
    UDR = 'p';
2
  
3
     switch (received_data[0])
4
     {    
5
             // Motor drehen.... Buchstabe "d"
6
       case 0x64:  
7
             UDR = 'd';
Gast #1662785
Lesenswert?

MC_AVR schrieb:
> int  rx_flag;     // Status-Flag für vollständig übertragene Befehle...

Mach da mal ein "volatile" davor.
1
volatile int  rx_flag;     // Status-Flag für vollständig übertragene Befehle...

Gruß,
Magnetus
Gast #1662829
Lesenswert?

@ holger: das stimmt, das sollte ich ändern. Am besten schreibe ich eine 
Funktion, welche die Daten senden, aber davor mit einer If Bedingung 
überprüft ob die Daten alle fertig gesendet sind.

@ magnetus:

Das mit volatile hat funktioniert. Was macht dieses volatile ? benötigt 
man dieses volatile extra, weil die Zuweisung rx_flag = 1 in einer 
Interrupt Routine statt findet ?


Jetzt erhalte ich allerdings nachdem Senden von d! iip, also die 
if-Bedingung reagiert, aber leider erhalte ich nicht das "r" für das 
!-Zeichen. Vielleicht liegt das an dem "prügeln" der Daten in den UDR :)

Ich arbeite daran und werde ich mich ggf. wieder melden !

Vielen Dank an euch beide.

MfG,
MC_AVR

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