atmega644 UART-Ringpufferlösung - vollständiger Code: Letzter Fehler- Immer nur drei bytes

OP Persönliche Seite #3497517
Lesenswert?

Hallo,

ich hatte hier vor kurzem bereits Hilfe und dann auch eine (dachte ich) 
funktionierende Version. Nun gibt es ein kleines Problem, auf dessen 
Lösung ich einfach nicht komme:

Ich habe einen Ringpuffer umgesetzt, um interruptgesteuerte 
UART-Kommunikation mit meinem atmega644 aufzubauen. Das merkwürdige:

Der Ringpuffer funktioniert gut, wenn ich max. drei bytes hintereinander 
hineinschreibe. Sende ich mehr, werden die zwischenliegenden Bytes 
zwischen den ersten beiden und dem letzten irgendwie verschluckt. Als 
Beispiel in der Routine unten:

Ich möchte 00 FF AB CD EF 00 schicken.
Am terminal kommt dann aber an: 00 FF 00.

Der Code ist eigentlich recht übersichtlich und funktioniert soweit, er 
kann also gerne verwendet werden (dann hat vll. jemand auch etwas davon, 
sobald der fehler gefunden ist). Wenn ihr mir irgendwie helfen könntet 
wäre das super!!
1
*/ RINGPUFFER: circbuf.h */
2
#ifndef CIRCBUF_H_
3
#define CIRCBUF_H_
4

5
#include <stdbool.h>
6
#include <avr/io.h>
7
#include <stdlib.h>
8
#include <avr/interrupt.h>
9

10

11
#define buffer_size 16      
12

13
struct circ_buffer {
14
  uint8_t data[buffer_size];
15
  uint8_t read_ptr;      // points to last input data
16
  uint8_t write_ptr;      // always points to empty field
17
  };
18

19
void buffer_init (struct circ_buffer *buf);
20
void buffer_write(struct circ_buffer *buf, uint8_t byte);
21
uint8_t buffer_read(struct circ_buffer *buf);
22
uint8_t buffer_is_full (struct circ_buffer *buf);
23
uint8_t buffer_is_empty (struct circ_buffer *buf);
24

25
#endif /*CIRCBUF_H_*/
26
/* END circbuf.h */
27

28

29
/* RINGPUFFER FUNCTIONS  circbuf.c*/
30
#include "circbuf.h"
31

32
void buffer_init (struct circ_buffer *buf)          // Initialization of circular buffer values
33
{
34
  buf->read_ptr=0;
35
  buf->write_ptr=0;
36
}
37

38
void buffer_write(struct circ_buffer *buf, uint8_t byte)  // Write byte into buffer, increment fillcounter and write pointer
39
{
40
  cli();
41
  buf->data[buf->write_ptr] = byte;
42
  
43
  if (buf->write_ptr >= buffer_size-1){
44
    buf->write_ptr = 0;
45
  }
46
  else{
47
    buf->write_ptr = buf->write_ptr + 1;
48
  }
49
  sei();
50
}
51

52
uint8_t buffer_read(struct circ_buffer *buf)        // Read byte out of buffer, decrement fillcounter, increment read ptr
53
{
54
  cli();
55
  uint8_t returnval =0;
56
  
57
  if  (buf->read_ptr == buf->write_ptr){
58
    sei();
59
    return 0;
60
  }
61
  else 
62
  {
63
    returnval= buf->data[buf->read_ptr];
64
    
65
    if (buf->read_ptr >= buffer_size-1){
66
      buf->read_ptr = 0;
67
    }
68
    else{
69
      buf->read_ptr = buf->read_ptr + 1;
70
    }
71
    sei();
72
    return returnval;
73
  }
74

75
}
76

77
uint8_t buffer_is_full (struct circ_buffer *buf)
78
{
79
  if (buf->write_ptr + 1 == buf->read_ptr || buf->read_ptr == 0 && buf->write_ptr + 1 == buffer_size)
80
  return 1;
81
  else return 0;
82
}
83

84
uint8_t buffer_is_empty (struct circ_buffer *buf)
85
{
86
  if (buf->read_ptr == buf->write_ptr) return 1;
87
  else return 0;
88
}
89

90
/* END RINGPUFFER FUNCTIONS circbuf.c */
91

92

93

94
/* UART_functions.h */
95

96
  #ifndef _M_UART_functions_h_
97
  #define _M_UART_functions_h_
98
  
99
  #define F_CPU 20E6 //Systemtakt in Hz
100
  #include <util/delay.h>
101
  
102
  #include "circbuf.h"
103

104
  // FUNCTIONS
105
  void UART_Init();
106
  uint8_t uart_ReceiveByte( struct circ_buffer *buf );
107
  void uart_TransmitByte( struct circ_buffer *buf, uint8_t data );
108

109
  #endif /*_M_UART_functions_h_*/
110

111
/* END UART_functions.h */
112

113

114
/* UART_functions.c */
115

116
#include <avr/io.h>
117
#include <avr/interrupt.h>
118
#include <stdlib.h>
119

120
#include "UART_functions.h"
121
#include <util/delay.h>
122

123

124
 void UART_Init()
125
 {
126
   // baud Calculation: baud = (fosc/ 16*Baudrate)-0.5
127
   // baud = (20 MHz / 16*9600)-0.5 = 129.708 --> = baud = 130
128
   unsigned int baud = 130;
129
   
130
   //* Set baud rate */
131
   UBRR0H = (unsigned char)(baud>>8);
132
   UBRR0L = (unsigned char)baud;
133
   /* Enable receiver and transmitter, Set Interrupts: RXCIE - RX-Complete */
134
   UCSR0B = (1<<RXEN0)|(1<<TXEN0)|(1<<RXCIE0);
135
   /* Set frame format: 8data, 2stop bit */
136
   UCSR0C = (1<<USBS0)|(3<<UCSZ00);
137
 }
138
 
139
uint8_t uart_ReceiveByte( struct circ_buffer *buf )
140
{
141
  while ( buffer_is_empty(buf) );  /* wait for incoming data */
142
  return buffer_read(buf); /* return data */
143
}
144

145

146
void uart_TransmitByte(struct circ_buffer *buf, uint8_t data )
147
{
148
  while ( buffer_is_full(buf) );
149
  buffer_write(buf,data);    /* store data in buffer */
150
  
151
  UCSR0B |= (1<<UDRIE0);      // Enable UDRIE- UART Data Register empty Interrupt - UDRE-ISR is going to put data in UDR
152
}
153

154
/* END UART_functions.c */
155

156

157
/* MAIN.c */
158

159
#include <avr/io.h>
160
#include <avr/interrupt.h>
161
#include <stdlib.h>
162
#include "stdbool.h"
163
#include <string.h>
164

165
#define F_CPU 20E6 //Systemtakt in Hz
166

167
#include "UART_functions.h"
168
#include "circbuf.h"
169
#include <util/delay.h>
170

171
// Global VARIABLES
172
unsigned char byte_buffer;
173
struct circ_buffer uart_rx_buffer;            // Receive-Circular-Buffer
174
struct circ_buffer uart_tx_buffer;            // Send-Circular-Buffer
175

176

177
// UART RX-Complete interrupt: 
178
// Receiving data + buffering (saving)
179
ISR(USART0_RX_vect) 
180
{
181
  unsigned char data;
182
  data = UDR0;
183
  buffer_write(&uart_rx_buffer, data);
184
}
185

186
// UART Data register empty interrupt:
187
// loading new data into UART sending register
188
ISR(USART0_UDRE_vect) 
189
{
190
  if (!buffer_is_empty(&uart_tx_buffer))          // Is buffer filled?
191
  {
192
    UDR0 = buffer_read(&uart_tx_buffer);
193
  }
194
  else
195
  {
196
    UCSR0B &= ~(1<<UDRIE0);              // Disable UDRIE- UART Data Register empty Interrupt 
197
  }
198
}
199

200
int main(void)
201
{
202
  /* Buffer Initialization */
203
  buffer_init(&uart_rx_buffer);
204
  buffer_init(&uart_tx_buffer);
205
  
206
  /* Variables */
207
  char controlbyte;
208
  uint8_t sendbuffer;  
209
  uint32_t adcrec;
210
      
211
  /*********************** Initialization ***********************/
212
  //Port Directions
213
  
214
  DDRA= 0b11011011;              
215
  DDRB= 0b10100110;                            
216
  DDRC= 0b01010001;        // SPI Slave select, LEDs                    
217
  DDRD= 0b00001010;        // UART
218
  
219
  UART_Init();          // UART initialization
220
  sei();              // Global Interrupt enable
221
  
222
  /*********** MAIN LOOP **************/
223
    while(1)
224
    {  
225
      
226
    if (!buffer_is_empty(&uart_rx_buffer))            // Received Commands?
227
    {
228
      controlbyte = uart_ReceiveByte(&uart_rx_buffer);
229
      
230
      switch (controlbyte)
231
      {
232
        case 0xAA: {
233
          sendbuffer =00;
234
          uart_TransmitByte(&uart_tx_buffer, sendbuffer);
235
          
236
          adcrec =  0xFFABCDEF;
237
          
238
          sendbuffer =(adcrec >>24);
239
          uart_TransmitByte(&uart_tx_buffer, sendbuffer);
240
          sendbuffer =(adcrec >>16);
241
          uart_TransmitByte(&uart_tx_buffer, sendbuffer);
242
          sendbuffer =(adcrec >>8);
243
          uart_TransmitByte(&uart_tx_buffer, sendbuffer);
244
          sendbuffer =adcrec;
245
          uart_TransmitByte(&uart_tx_buffer, sendbuffer);    
246
          sendbuffer =00;
247
          uart_TransmitByte(&uart_tx_buffer, sendbuffer);                          
248
          break;
249
        }
250
        case 0xBB: {
251
          break;
252
        }
253
        case 0xCC:{
254
          break;          
255
        }
256
      }
257
    }    
258
    }
259
}
260

261
/* END MAIN.C */


Die Mainloop wartet hier auf den Eingang eines Control-Chars über UART 
und sendet dann (im Falle von 0xAA) die Testsequenz.

Kann mir da jemand helfen? Ich habe die Files auch oben angehängt.

Beste Grüße

Alex
Angehängte Dateien:
Gast #3497609
Lesenswert?

>nen flüchtigkeitsfehler (0x00), daran liegts aber nicht ;)

>Alles in der switch-case loop ist unter vorbehalt zu genießen, da habe
>ich jetzt dauernd herumgefummelt um auf den fehler zu kommen.

Fürn Programmierer bist du aber schwer nachlässig ;).
Das musst du ändern.

Gruß Jonas
Gast #3497624
Lesenswert?

> struct circ_buffer uart_rx_buffer;
> struct circ_buffer uart_tx_buffer;

Mach diese beiden Puffer mal volatile und sorge dafür, dass cli() und 
sei() nicht aus dem Interrupt heraus aufgerufen werden.

Siehe FAX 1. und 8.

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