AVR: RS232 uart och printf(); ?

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
myrek
Inlägg: 38
Blev medlem: 7 april 2009, 09:52:15

AVR: RS232 uart och printf(); ?

Inlägg av myrek »

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.
hummel
Inlägg: 2546
Blev medlem: 28 november 2009, 10:40:52
Ort: Stockholm

Re: AVR: RS232 uart och printf(); ?

Inlägg av hummel »

Använd sprintf() istället och skicka sedan ut den skapade strängen på serieporten.
Användarvisningsbild
psynoise
EF Sponsor
Inlägg: 7230
Blev medlem: 26 juni 2003, 19:23:36
Ort: Landvetter

Re: AVR: RS232 uart och printf(); ?

Inlägg av psynoise »

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);
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: AVR: RS232 uart och printf(); ?

Inlägg av jesse »

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. :x

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 :tumupp:
Användarvisningsbild
Icecap
Inlägg: 26659
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: AVR: RS232 uart och printf(); ?

Inlägg av Icecap »

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.
Användarvisningsbild
psynoise
EF Sponsor
Inlägg: 7230
Blev medlem: 26 juni 2003, 19:23:36
Ort: Landvetter

Re: AVR: RS232 uart och printf(); ?

Inlägg av psynoise »

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
Användarvisningsbild
Icecap
Inlägg: 26659
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: AVR: RS232 uart och printf(); ?

Inlägg av Icecap »

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.
Användarvisningsbild
stekern
Inlägg: 453
Blev medlem: 2 november 2008, 08:24:18
Ort: Esbo, Finland

Re: AVR: RS232 uart och printf(); ?

Inlägg av stekern »

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:

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;
			}
	}

  }
}

Användarvisningsbild
Borgen
Inlägg: 39
Blev medlem: 21 januari 2009, 17:50:43
Skype: henrikborg
Ort: Botkyrka
Kontakt:

Re: AVR: RS232 uart och printf(); ?

Inlägg av Borgen »

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.
Skriv svar