AVR: RS232 uart och printf(); ?
AVR: RS232 uart och printf(); ?
Hej, jag använder mig av en atmega16 för att kommunicera via RS232. Allt fungerar bra men jag skulle bli väldigt glad om jag lyckades få funktionen printf(); att fungera.
funktionen ligger ju i <stdio.h> och jag måste på något sätt tala om att det är RS232 som ska fungera som Stdout. Hur gör jag detta? Jag har försökt läsa mig runt på massvis med sidor. Men jag har inte hittat någon bra guide för hur man löser detta. Det finns säkert någon här som har råkat ut för detta "problem" och har en lösning.
Jag kör för övrig WinAVR release 090313, AVR studio 4 och använder mig av STK500.
funktionen ligger ju i <stdio.h> och jag måste på något sätt tala om att det är RS232 som ska fungera som Stdout. Hur gör jag detta? Jag har försökt läsa mig runt på massvis med sidor. Men jag har inte hittat någon bra guide för hur man löser detta. Det finns säkert någon här som har råkat ut för detta "problem" och har en lösning.
Jag kör för övrig WinAVR release 090313, AVR studio 4 och använder mig av STK500.
Re: AVR: RS232 uart och printf(); ?
Använd sprintf() istället och skicka sedan ut den skapade strängen på serieporten.
Re: AVR: RS232 uart och printf(); ?
Om du använder avr-libc sätter du uart till stdio via
Kod: Markera allt
FILE uart_str = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);
Re: AVR: RS232 uart och printf(); ?
psynoise: är den funktionen buffrad på något vis, eller måste man ordna det själv, för jag antar att uart_putchar och uart_getchar är pekare till de egna funktionerna man har för uart?
Getchar bör väl ha nån form av timeout? Annars fastnar ju processorn varje gång den vill lyssna efter tecken och det inte kommer något. Hur signalerar man det till printf() att det inte kommit något tecken - genom att returnera -1 i uart_getchar?
Det sista man vill ha är ju ett program som fastnar vid en inmatning.
Själv har jag gjort en liten egen variant (som säkert är inkompatibel med scanf();
) som lägger alla inmatade tecken (upp till en viss gräns) i en buffert ända tills man trycker enter - då sätts en flagga som signaterar "line in" och du har en färdig sträng som avslutas med 13 (Enter). Den hanterar även backsteg och eko av tecken. Om det finns något som heter sscanf() kanske jag kan använda det här???
Sedan behöver bara huvudprogrammet kolla flaggan linein då och då. Om den är satt så börjar man läsa tecken för tecken med funktionen uartRead(); Den returnerar noll då man kommit till slutet (och fortsätter att returnera noll tills en ny sträng kommit in).
(Först tänkte jag ha en rullande buffert så att data kunde fortsätta att matas in även efter "enter", men tyckte det var bökigt, så den börjar om från position noll varje gång. Det betyder att om jag matar in "text"(enter) och fortsätter skriva in text till uart innan förra strängen hunnit bearbetas, så tas tecknen inte emot. Kan vara klumpigt vid automatisk överföring , men vid manuell kommunikation i terminal så väntar jag på ny "prompt" innan jag skriver nästa kommando , och det går bra. Om man ändå skulle mata in ett tecken vid fel tillfälle så ekas det inte tillbaks till terminalen, utan man får tecknet ~ istället.)
hummel: sprintf() - intressant. Ett sätt att omvandla tal till text och vice versa? Det ska jag prova. Bra tips
Getchar bör väl ha nån form av timeout? Annars fastnar ju processorn varje gång den vill lyssna efter tecken och det inte kommer något. Hur signalerar man det till printf() att det inte kommit något tecken - genom att returnera -1 i uart_getchar?
Det sista man vill ha är ju ett program som fastnar vid en inmatning.

Själv har jag gjort en liten egen variant (som säkert är inkompatibel med scanf();

Sedan behöver bara huvudprogrammet kolla flaggan linein då och då. Om den är satt så börjar man läsa tecken för tecken med funktionen uartRead(); Den returnerar noll då man kommit till slutet (och fortsätter att returnera noll tills en ny sträng kommit in).
(Först tänkte jag ha en rullande buffert så att data kunde fortsätta att matas in även efter "enter", men tyckte det var bökigt, så den börjar om från position noll varje gång. Det betyder att om jag matar in "text"(enter) och fortsätter skriva in text till uart innan förra strängen hunnit bearbetas, så tas tecknen inte emot. Kan vara klumpigt vid automatisk överföring , men vid manuell kommunikation i terminal så väntar jag på ny "prompt" innan jag skriver nästa kommando , och det går bra. Om man ändå skulle mata in ett tecken vid fel tillfälle så ekas det inte tillbaks till terminalen, utan man får tecknet ~ istället.)
hummel: sprintf() - intressant. Ett sätt att omvandla tal till text och vice versa? Det ska jag prova. Bra tips

Re: AVR: RS232 uart och printf(); ?
sprintf skriver ut till ett minnesarea men vill du skriva ut "direkt" får du redeklarera putchar(). Allt som printf skriver ut skickas tecken för tecken till putchar() varför en redeklaration ser till att allt kommer dit du vill ha det.
Man kan ändra den till att skriva ut på LCD, serieport eller vad man vill, dock använder jag själv sprintf nästan alltid.
Man kan ändra den till att skriva ut på LCD, serieport eller vad man vill, dock använder jag själv sprintf nästan alltid.
Re: AVR: RS232 uart och printf(); ?
jesse: uart_putchar är buffrad till fördefinierat antal bytes i avr-libc. Hur det fungerar med uart_getchar har jag dock inte koll på men allt det borde stå i dokumentationen.
http://www.nongnu.org/avr-libc/user-manual/index.html
http://www.nongnu.org/avr-libc/user-manual/index.html
Re: AVR: RS232 uart och printf(); ?
Jag brukar avsätta en buffer till varje kommunikationskanal, sedan skriver jag ut vid att använda sprintf() på en buffer som jag sedan "skriver ut" till TX-buffer på den valda kanal. Själva sändningen sker med en interrupt till att sköta tömningen av TX-buffern och TX-buffern är en ringbuffer.
Mottagningen är interruptbaserat också, rutinen fyller på en RX-buffer och när ETX (använder oftast en STV-ETX block protokoll) kommer triggas en timer som indikerar för main-loop att det finns ett block att ta hand om.
Detta sätt fungerar bra då det oftast är en "fråga -> svar" situation, detta betyder att buffrarna bara behöver ta hand om största blocket som kan komma.
Jag har på sin höjd kört ett projekt med 4 st UART i full hastighet samtidig och ingen problem med "proppar" uppstod.
Mottagningen är interruptbaserat också, rutinen fyller på en RX-buffer och när ETX (använder oftast en STV-ETX block protokoll) kommer triggas en timer som indikerar för main-loop att det finns ett block att ta hand om.
Detta sätt fungerar bra då det oftast är en "fråga -> svar" situation, detta betyder att buffrarna bara behöver ta hand om största blocket som kan komma.
Jag har på sin höjd kört ett projekt med 4 st UART i full hastighet samtidig och ingen problem med "proppar" uppstod.
Re: AVR: RS232 uart och printf(); ?
Sen finns det en simplare version av sprintf i gcctest9, den har jag använt nångång när det varit snålt med utrymme.
Här är den med några modifieringar för att få den ännu mindre:
Här är den med några modifieringar för att få den ännu mindre:
Kod: Markera allt
#define SCRATCH 16
int sprintf(uint8_t *buf, const uint8_t *format, ...)
/* simplified sprintf from gcctest9 (modified to be even more simpler) */
{
uint8_t scratch[SCRATCH];
uint8_t format_flag;
uint16_t u_val=0;
uint8_t *ptr;
va_list ap;
va_start (ap, format);
for (;;){
while ((format_flag = *format++) != '%'){ /* Until '%' or '\0' */
if (!format_flag){va_end (ap); return (0);}
*buf = format_flag; buf++; *buf=0;
}
switch (format_flag = *format++){
case 'u': {
u_val = va_arg(ap,int);
ptr = scratch + SCRATCH;
*--ptr = 0;
do {
char ch = u_val % 10 + '0';
if (ch > '9')
ch += 'a' - '9' - 1;
*--ptr = ch;
u_val /= 10;
} while (u_val);
strcat((char*)buf, (char*)ptr);
buf += strlen((char*)ptr);
break;
}
default: {
*buf = format_flag; buf++; *buf=0;
break;
}
}
}
}
Re: AVR: RS232 uart och printf(); ?
File *stream = fopen(..) // öppna/skapa ström mot enhet, fil, port ...
fprintf(stream,"text att skriva", variabler som ska hämtas); // första argumentet är en pekare mot en ström, resten som vanliga printf
Inte provat på mikrokontroller tidigare men vill minnas det funkade fint på PC:n på 90-talet.
fprintf(stream,"text att skriva", variabler som ska hämtas); // första argumentet är en pekare mot en ström, resten som vanliga printf
Inte provat på mikrokontroller tidigare men vill minnas det funkade fint på PC:n på 90-talet.