Forum: Compiler & IDEs UART - Verständnisproblem Strings


von Michael (Gast)


Lesenswert?

Hallo,
mein Name ist Michael und ich programmiere in der Schule schon etwas 
länger mit µC. Jetzt haben wir jedoch mit dem UART begonnen und ich habe 
irgendwie ein Verstädnis problem bei einem kleinen privaten Projekt...

Ich nutze HTerm zum senden über die Serielle Schnittstelle vom PC aus. 
Mein µC ist ein AtMega8. Der Empfang funktioniert tadellos.
Jetzt möchte ich vom PC aus einen "String" an dem µC senden.
Und zwar will ich z.B. die Zeichenfolge "000 100 200 255 150 050" 
senden.
Ich habe 6 LED's an den AtMega angeschlossen und wollte diese 
Zahlenwerte nun als Helligkeitswerte der jeweiligen LED's verwenden 
(Soft-PWM). Also
LED1 = 000 ->aus
LED2 = 100 ->etwas hell...
usw...
(8-Bit 0-255)

Mein Problem liegt jetzt darin das ich es nicht hinbekomme die einzelnen 
Zahlenwerte in eine uint8_t Variable abzulegen.

Hier mal mein bisheriger Code. Über einige Tipps würde ich mich sehr 
freuen.
1
#include <avr/io.h>
2
#include <avr/delay.h>
3
#include <stdlib.h>
4
#include <avr/interrupt.h> 
5
6
#define UART_SIZE 3
7
#define F_CPU 14745600L
8
#define USART_BAUDRATE 9600UL
9
10
volatile int8_t uart_count;
11
volatile char uart_buffer[UART_SIZE];
12
volatile uint8_t pwm_soll;
13
volatile uint8_t pwm_phase;
14
15
ISR(USART_RXC_vect) {
16
  while (uart_count < UART_SIZE) {
17
    uart_buffer[uart_count++] = UDR;
18
  };
19
  UDR = uart_buffer;
20
  pwm_soll = atoi(uart_buffer);
21
  
22
  
23
  for(int i=0;i<UART_SIZE;i++) {
24
      uart_buffer[i] = 0;
25
      uart_count=0;
26
  }  
27
  //pwm_soll = 2;
28
}
29
30
void prepare_usart(void) {
31
  // Senden und empfangen aktivieren und Empfang Interrupt aktivieren
32
  UCSRB |= (1<<TXEN) | (1<<RXEN) |(1<<RXCIE); 
33
  //Kommunikation asynchron "8N1"
34
  UCSRC = (1<<URSEL) | (1<<UCSZ0) | (1<<UCSZ1);
35
  //Geschwindigkeit berechnen
36
  UBRRL = ((F_CPU)/((USART_BAUDRATE)*16L)-1);
37
  uart_count = 0;
38
  sei();
39
  
40
}
41
42
int main(void) {
43
  prepare_usart();
44
  int tmp = 0;
45
  pwm_soll = 255; 
46
  pwm_phase = 0;
47
48
  DDRB |= (1<<PB0); // Pin PB0 an Port B als Ausgang
49
   
50
  while( 1 ) {
51
    tmp++;
52
    
53
    if( pwm_soll == pwm_phase ) {
54
        PORTB |= (1<<PB0); 
55
    }
56
57
    pwm_phase++;
58
59
    if( pwm_phase == 255 ) {
60
      pwm_phase = 0;
61
      PORTB &= ~(1<<PB0);
62
    }
63
  }
64
  return 0;
65
}

Mit freundlichen Grüßen
Michael

von der mechatroniker (Gast)


Lesenswert?

Nur kurz den Quelltext überflogen. Es scheint ein Verständnisproblem 
bezüglich der Arbeitsweise des USART_RXC_vect vorzuliegen. Der Interrupt 
wird jedesmal erzeugt, wenn ein Zeichen empfangen wurde und nicht erst, 
wenn genug Zeichen für deinen Buffer da sind. Denk immer dran: die 
Controllerhardware weiß von deinem Buffer nix.

Das heißt deine Buffer-Füll-Schleife:
1
  while (uart_count < UART_SIZE) {
2
    uart_buffer[uart_count++] = UDR;
3
  };

fliegt zwangsläufig auf die Nase.

Die korrekte Vorgehensweise wäre:
1. Das empfangene Zeichen in den Buffer schreiben
2. wenn ausreichend Daten im Buffer, auswerten. Wenn nicht, erstmal nix 
machen.

von Michael (Gast)


Lesenswert?

Danke erstmal für deine schnelle Antwort...
Also müsste ich im Prinzip, wenn ich weis wieviele Zeichen ich sende, 
den ganzen Zeichenstrom in einen buffer legen und diesen dann wenn alle 
Zeichen da sind aufteilen !?würde im Buffer denn auch wirklich "255 000" 
usw. liegen wenn ich diese Zeichenkette als ASCII zeichen sende?

MfG
Michael

von der mechatroniker (Gast)


Lesenswert?

Im Prinzip ist es genau so. Was du dir jetzt noch überlegen musst:
* Wie sind deine Strings terminiert (z.B. durch Linefeed)?
* Was passiert, wenn du als erste Nachricht nach dem Einschalten ein 
Fragment empfängst (was ja, wenn der Sender bereits sendet, schnell 
passieren kann)? Wie schaffst du es, das Fragment zu verwerfen und 
zumindest die folgende Nachricht korrekt zu empfangen?
* Was passiert, wenn du aus welchen Gründen auch immer kompletten Unsinn 
empfängst? Kannst du sicherstellen, dass dein Programm nicht komplett 
aussteigt?

Wenn du dir das überlegt hast, dann fröhliches Programmieren. Du kannst 
ja mal dein Zwischenergebnis hier posten!

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.