Forum: Mikrocontroller und Digitale Elektronik [STM32] und mehrere Interrupts


von Bernhard (Gast)


Lesenswert?

Hallo,

ich habe auf meinem Rechner zwei Programme laufen, die Daten auf zwei 
unterschiedlichen COM Schnittstellen zum Mikrocontroller senden. Der 
Mikrocontroller empfängt die Daten interruptgesteuert und legt diese in 
zwei Ringbuffern ab. Anschließend führt der Mikrocontroller ein paar 
einfache Datenmanipulationen durch und schickt die Daten auf einer 
dritten COM Schnittstelle wieder zum Mikrocontroller zurück. Der Grund 
warum ich so viele Schnittstellen brauch ist, dass hier später mehrere 
PCs Daten zum Mikrocontroller senden sollen. Zum Testen ist es aber ganz 
praktisch, dass erstmal alles auf einem PC laufen zu lassen.

Kurz gesagt kann man sagen, dass der Mikrocontroller die Daten von zwei 
COM Schnittstellen aufsammelt, die Daten verändert und dann gebündelt 
auf eine weitere COM rausschickt.

Wenn ich nur ein Programm am PC laufen lasse und quasi simuliere, dass 
ein PC Daten zum Mikrocontroller sendet, dann funktioniert alles 
problemlos. Der Mikrocontroller empfängt die Daten, verändert sie und 
schickt sie wieder raus. Wenn ich jedoch simuliere, dass zwei PCs Daten 
zum Mikrocontroller schicken, dann produziert der uC irgendwann nen 
Blödsinn. Er schickt dann statt "00410" zum Beispiel "004♥♥" raus. Wenn 
ich die Daten, die ich zum Mikrocontroller sende, etwas langsamer sende 
(als nach jeder Zeile, die ich sende, 0.2 Sekunden warte, dann 
funktioniert es. Meine Vermutung ist nun, dass der Mikrocontroller mit 
den zwei interruptgesteuerten UART Receives irgendwie nicht klarkommt 
und da Müll produziert. Mein Programm sieht so aus:
1
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
2
3
struct __FILE { int handle; };
4
FILE __stdout;
5
FILE __stdin;
6
7
void usart1_init (unsigned long baudrate) {
8
  NVIC->ISER[1] |= 0x00000020;  //enable USART1 Interrupt (Nested Vector Interrupt Controller)
9
10
  RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; //enable GPIOA clock
11
  
12
  GPIOA->CRH &= ~(0x00F0); //clear PA.9 configuration-bit 
13
  GPIOA->CRH   |= (0x0BUL  << 4); //Tx (PA9) - alt. out push-pull
14
15
  GPIOA->CRH &= ~(0x0F00); //clear PA.10 configuration-bit 
16
  GPIOA->CRH   |= (0x04UL  << 8); //Rx (PA10) - floating
17
  RCC->APB2ENR |= RCC_APB2ENR_USART1EN; //enable USART1 clock
18
19
  USART1->BRR  = 8000000L/baudrate; //set baudrate 
20
  
21
  USART1->CR1 |= (USART_CR1_RE | USART_CR1_TE);  //set RX, TX
22
  USART1->CR1 |= USART_CR1_RXNEIE; //enable USART IRQ
23
  USART1->CR1 |= USART_CR1_UE;    //enable USART
24
} 
25
26
void usart2_init (unsigned long baudrate) {
27
  RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; //enable GPIOA clock
28
29
  AFIO->MAPR &= ~(AFIO_MAPR_USART2_REMAP); //no remap of RX & TX
30
  
31
  GPIOA->CRL &= ~(0x0F00); //clear PA.2 configuration-bits 
32
  GPIOA->CRL   |= (0x0BUL  << 8); //Tx (PA.2) - alt. out push-pull
33
34
  GPIOA->CRL &= ~(0xF000); //clear PA.3 configuration-bits 
35
  GPIOA->CRL   |= (0x04UL  << 12); //Rx (PA.3) - floating
36
  RCC->APB1ENR |= RCC_APB1ENR_USART2EN; //enable USART2 clock
37
38
  USART2->BRR  = 8000000L/baudrate; //set baudrate 
39
  
40
  USART2->CR1 |= (USART_CR1_RE | USART_CR1_TE);  //enable RX, TX
41
  USART2->CR1 |= USART_CR1_UE;                    //enable USART
42
} 
43
44
void usart3_init (unsigned long baudrate) {
45
  NVIC->ISER[1] |= 0x00000080;  //enable USART1 Interrupt (Nested Vector Interrupt Controller)
46
  RCC->APB2ENR |= RCC_APB2ENR_IOPBEN; //enable GPIOB clock
47
48
  AFIO->MAPR &= ~(AFIO_MAPR_USART3_REMAP); //no remap of RX & TX
49
  
50
  GPIOB->CRH = GPIOB->CRH & ~(0x00000F00) | (0x00000B00); //PB10 = Tx 
51
  //GPIOA->CRL   |= (0x0BUL  << 8); //Tx (PA.2) - alt. out push-pull
52
    GPIOB->CRH = GPIOB->CRH & ~(0x0000F000) | (0x00004000); //PB11 = Rx 
53
  //GPIOA->CRL &= ~(0xF000); //PB11 = Rx 
54
  //GPIOA->CRL   |= (0x04UL  << 12); //Rx (PA.3) - floating
55
  RCC->APB1ENR |= RCC_APB1ENR_USART3EN; //enable USART3 clock
56
57
  USART3->BRR  = 8000000L/baudrate; //set baudrate 
58
  
59
  USART3->CR1 |= (USART_CR1_RE | USART_CR1_TE);  //enable RX, TX
60
  USART3->CR1 |= USART_CR1_RXNEIE; //enable USART IRQ
61
  USART3->CR1 |= USART_CR1_UE;                    //enable USART
62
} 
63
64
int send_char (char ch)  {
65
  while (!(USART2->SR & USART_SR_TXE));  //data transmit register empty?
66
  USART2->DR = (ch & 0xFF);  //write bytewise
67
  return (ch);
68
} 
69
70
/*let send_char point to printf*/
71
PUTCHAR_PROTOTYPE
72
{
73
  send_char((char) ch);
74
  return ch;
75
} 
76
77
78
79
/*Put the received characters in a ringbuffer*/
80
void USART1_IRQHandler (void){
81
  if((USART1->SR & USART_SR_RXNE)){ 
82
    fifo_write(&fifo[0], USART1->DR);   
83
   }
84
}
85
86
/*Put the received characters in a ringbuffer*/
87
void USART3_IRQHandler (void){
88
  if((USART3->SR & USART_SR_RXNE)){ 
89
    fifo_write(&fifo[1], USART3->DR);   
90
   }
91
}
92
93
int main(void)
94
{ 
95
96
   uint8_t data[2] = {0,0}; 
97
   uint8_t ret[2] = {0,0};  
98
99
   //initialize ringbuffer
100
   fifo_init(&fifo[0]);
101
   fifo_init(&fifo[1]);
102
103
104
   usart1_init(9600); //USART1 used for sending data
105
   usart2_init(9600); //USART2 used for receiving data
106
   usart3_init(9600); //USART3 used for receiving data
107
108
   for(;;){
109
      __disable_irq(); //translate to CPSID i
110
      //try to read from ringbuffer and put read char in 'data' 
111
      ret[0] = fifo_read(&fifo[0], &data[0]);
112
      ret[1] = fifo_read(&fifo[1], &data[1]);
113
      __enable_irq(); //translate to CPSIE i
114
115
     if(ret[0] == SUCCESS){ //if there was new char in ringbuffer
116
        printf("%d", manipulate_data(data[0]));  //manipulate data and write it out  
117
     }
118
     if(ret[1] == SUCCESS){ //new character in buffer?
119
        printf("%d", manipulate_data(data[0]));  //manipulate data and write it out   
120
     }  
121
122
   }
123
}

Ich hab versucht mein Programm aufs Wesentliche zu reduzieren, da ich 
wie gesagt vermute, dass der Fehler irgendwo im Interrupt Management 
liegt. Das mein Ringbuffer zu klein ist und der dann irgendwie die Daten 
überschreibt kann ich mir nicht vorstellen, da die beiden Ringbuffer 
jeweils 256Byte groß sind.

Hat jemand von euch vielleicht ne Idee, was da schief laufen könnte?

von Bernhard (Gast)


Lesenswert?

Sorry, sollte natürlich:
1
if(ret[1] == SUCCESS){ //new character in buffer?
2
        printf("%d", manipulate_data(data[1]));  //manipulate data and write it out   
3
}

heißen

von Bernhard (Gast)


Lesenswert?

Ok, es scheint tatsächlich so, dass der Ringbuffer zu klein ist. Ich hab 
mir jetzt eine LED zum Debuggen hergenommen und die immer dann gesetzt, 
wenn der Ringbuffer überläuft. Ohne Delay sieht man ganz deutlich, dass 
der Buffer überläuft.

Argh! Hätte ich das mal besser gleich überprüft...

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.