Hallo,
für meine WS2812B Leds möchte ich in einer Interruptroutine einen String einlesen, der aus einem C# Programm alle 10ms gesendet wird (sofern eine Änderung erfolgte).
Der Stream sieht wie folgt aus
"<ff,ff,ff,ff>"
Beginn des Streams ist ein '<', das Ende ein '>'
Die Werte dazwischen werden als Hex-Char gesendet. 00 - ff.
Feld 1 ist für das Setzen interessant. Zum einen, welche Led angesprochen wird, und ob sich in den Felder 2 - 4 RGB oder HSV Werte befinden.
Wo ihr nun rüberschauen dürft ist zum einen ISR(USART_RX_vect) im ersten Quellcode Teil, sowie den dritten Quellcode Teil.
Was ich damit vor habe,
es soll mit einem '<' signalisiert werden, dass ein neuer Stream angefangen hat. Wurde der letzte Stream nicht abgeschlossen, startet hier ein neuer.
Werden mehr Werte als nötig eingelesen, gibt es ebenfalls einen Abbruch. Hierbei sind 5 Felder vorgesehen mit je 2 Zeichen (getrennt von einem ','
/*
* uart.h
*
* Created: 08.12.2015 21:00:19
* Author: sschultewolter
*/
#ifndef UART_H_
#define UART_H_
#define BAUD 250000
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <util/setbaud.h>
#include <stdlib.h>
#define UART_STRING_MAX 14
extern volatile char uart_string[UART_STRING_MAX + 1];
extern volatile uint8_t uart_strComplete;
extern void uart_init(void);
extern void uart_putc(char c);
extern void uart_puts(char *s);
extern void uart_puts_p(const char *s);
#define uart_puts_P(__S) uart_puts_p(PSTR(__S))
#define UART_CLEAR uart_puts_P("\E[H\E[J")
#define UART_CR uart_puts_P("\r")
#define UART_NL uart_puts_P("\n")
#define UART_CRNL uart_puts_P("\r\n")
#endif /* UART_H_ */
/*
* uart.c
*
* Created: 08.12.2015 21:00:10
* Author: sschultewolter
*/
#include "uart.h"
volatile char uart_string[UART_STRING_MAX + 1];
volatile uint8_t uart_strComplete = 0;
volatile uint8_t uart_strCount = 0;
extern void uart_init(void)
{
UBRR0 = UBRR_VALUE;
#if USE_2X
UCSR0A |= (1 << U2X0);
#else
UCSR0A &= ~(1 << U2X0);
#endif
// UART Tx, Rx Interrupt, Rx einschalten
UCSR0B |= (1 << TXEN0) | (1 << RXCIE0) | (1 << RXEN0);
// Asynchron 8N1
UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);
}
extern void uart_putc(char c)
{
while(!(UCSR0A & (1 << UDRE0))) ;
UDR0 = c;
}
extern void uart_puts(char *s)
{
while(*s)
{
uart_putc(*s);
s++;
}
}
extern void uart_puts_p(const char *s)
{
register char c;
while((c = pgm_read_byte(s++)))
uart_putc(c);
}
ISR(USART_RX_vect)
{
// Zeichen aus Puffer lesen
char c = UDR0;
// wenn uart_strComplete gesetzt ist, werden neue Zeichen verworfen
if(!uart_strComplete)
{
// Erstes zu empfangende Zeichen
// Sollten Zeichen vor '<' empfangen worden sein, wird der Zaehler (uart_strCount)
// zurueckgesetzt und die Zeichenkette (uart_string) mit '\0' terminiert
if(c == '<')
{
uart_strCount = 0;
uart_string[uart_strCount] = '\0';
}
// Das letzte zu empfangende Zeichen erhalten
else if(c == '>')
{
uart_string[uart_strCount] = '\0';
uart_strCount = 0;
uart_strComplete = 1;
}
// Zeichen einlesen und Zaehler (uart_strCount) inkrementieren
else if(c != '\r' && '\n' && uart_strCount < UART_STRING_MAX)
{
uart_string[uart_strCount++] = c;
}
else
{
uart_strCount = 0;
uart_string[uart_strCount] = '\0';
}
}
}
/*
* m328p_bottlelightv2.c
*
* Created: 08.12.2015 20:55:04
* Author: sschultewolter
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include <string.h>
#include "uart.h"
//#define DEBUG_UART
#ifdef DEBUG_UART
char buf_debug[32];
#endif
uint8_t getValues(char *s, uint8_t *values, uint8_t maxValues)
{
#ifdef DEBUG_UART
// Empfangen String ausgeben
sprintf(buf_debug, "Eingabe\t\t: <%s>", (char*)uart_string);
uart_puts(buf_debug);
#endif
const char delimter[] = ",;";
char *ptr = (char*)strtok((char*)uart_string, delimter);
uint8_t ct = 0;
while(ptr != NULL)
{
if(ct < maxValues - 1)
{
// Speichere Hex-Zeichen als Zahl
values[ct] = strtol(ptr, NULL, 16);
#ifdef DEBUG_UART
sprintf(buf_debug, "\r\n\tWert[%d]\t: %d", ct, values[ct]);
uart_puts(buf_debug);
#endif
}
// Zaehler ct solange einlesen, bis ptr == NULL (Fehlererkennung)
ct++;
ptr = strtok(NULL, delimter);
}
if(ct == (maxValues - 1))
{
#ifdef DEBUG_UART
sprintf(buf_debug, "\r\n! %d Feld(er) empfangen", (maxValues - 1));
uart_puts(buf_debug);
#endif
return 1;
}
else if (ct < (maxValues - 1))
{
#ifdef DEBUG_UART
sprintf(buf_debug, "\r\n! %d Feld(er) nicht empfangen", (maxValues - 1) - ct);
uart_puts(buf_debug);
#endif
return 0;
}
else
{
#ifdef DEBUG_UART
sprintf(buf_debug, "\r\n! %d Feld(er) zu viel empfangen", ct - (maxValues - 1));
uart_puts(buf_debug);
#endif
return 0;
}
}
int main(void)
{
uart_init();
sei();
const uint8_t numValues = 5;
uint8_t values[5];
while (1)
{
if(uart_strComplete)
{
uint8_t tmpValues[numValues];
// Neue Werte uebernehmen
if(getValues((char*)uart_string, tmpValues, numValues))
{
strncpy((char*)values, (char*)tmpValues, numValues);
#ifdef DEBUG_UART
sprintf(buf_debug, "\r\n%3d, %3d, %3d, %3d\r\n", values[0], values[1], values[2], values[3]);
uart_puts(buf_debug);
#endif
}
uart_strComplete = 0;
}
}
}