Forum: Mikrocontroller und Digitale Elektronik Finde fehler nicht (UART - Attiny2313)


von MC_AVR (Gast)


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 !

von holger (Gast)


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';

von magnetus (Gast)


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

von MC_AVR (Gast)


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

von swen (Gast)


Lesenswert?

MC_AVR schrieb:
> 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 ?


http://www.imb-jena.de/~gmueller/kurse/c_c++/c_volat.html


o-ton. man kann sich auch mal bemühen... ;-)

von Falk B. (falk)


Lesenswert?

Siehe Interrupt

von magnetus (Gast)


Lesenswert?


von MC_AVR (Gast)


Lesenswert?

Hallo !

Ein volatile vor char received_data[10] hat auch die restlichen Probleme 
gelöst. Vielen Dank !

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.