UART - Verständnisproblem Strings

Gast #2110148
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
Gast #2110182
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.
Gast #2110197
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
Gast #2110365
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!

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.