PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : probleme mit printf()



anabolik
13.03.2006, 16:59
hallo.
bin anfänger. heute habe ich mich mit dem UART von ATmega8 beschäftigt. wollte ein programm schreiben, welches einfach einen zählerzustand auf hyperterminal ausgibt.
mein problem ist folgender: die formartierung mit PrintF() klappt irgendwie nicht. auf hyperterminal wird dann "Counter: d" an stelle von "Counter:0" , "Counter:1", "Counter:2" u.s.w. ausgegeben. was mache ich falsch?

CODE:
#include <avr/io.h>
#include <avr/delay.h>
#include "datentypen.h"

#define F_CPU 3686400
#define UART_BAUD_RATE 9600
#define MYUBRR F_CPU/(UART_BAUD_RATE * 16L) - 1

int PrintF(const u8 *format, ...);
void uart_putc(u8 c);
void InitUART(u16);

int main(void)
{

PORTD|=(1<<PD2);
InitUART(MYUBRR);

u16 cnt=0;

while(1)
{
if(!(PIND & (1<<PD2)))
{
_delay_ms(80);
if(PIND & (1<<PD2))
cnt=0;
}
PrintF("Counter:%d\r\n",cnt);
cnt+=1;
_delay_ms(1000);
}

}


int PrintF(const u8 *format, ...)
{

u8 buffer;

while(*format != '\0')
{
if(*format=='%')
*format++;
buffer=*format;
uart_putc(buffer);
*format++;
}

}


void uart_putc(u8 c)
{
while (!(UCSRA & (1<<UDRE))); /* warten bis Senden moeglich */
UDR = c; /* sende Zeichen */
}


void InitUART(u16 ubrr)
{
/* Set baud rate */
UBRRH = (u8)(ubrr>>8);
UBRRL = (u8)ubrr;
/* Enable receiver and transmitter */
UCSRB = (1<<RXEN)|(1<<TXEN);
UCSRC |= (1<<URSEL)|(3<<UCSZ0); // Asynchron 8N1

}

ogni42
13.03.2006, 17:24
Du musst, wenn Du %d erkennst, das nächste Element aus der Parameterliste nehmen. Im Moment wirfst Du nur das `%`weg und gibts das nächste Zeichen aus.

anabolik
13.03.2006, 17:39
wie könnte man das realisieren?

PasstScho
13.03.2006, 18:03
Hi,
Am PC gibt es sprintf, das deine Sachen in einen String formatiert.
Gibts sicher auch für den µC.
MfG Alex

ogni42
13.03.2006, 19:34
Einfacher Weg: Es gibt für printf und sprintf schon Lösungen in der libc des avr-gcc. Ist in der doku zur libc beschrieben.

Nicht ganz so einfacher, aber sehr lehrreicher Weg: Erst mal mit der Vararbeitung von ellipsen in parametern wie name(arg, ...) vertraut machen. Tipp: Dafür gibt es zwei Makros va_start() und va_arg() mit denen Du die Ellipse abarbeiten kannst.

Die gelesenen Werte aus der Ellipse musst Du dann noch - abhängig vom geparsten Formatstring, also z.B. %d, vom Quelldatentyp hier: int - in den Zieldatentyp, hier: char[], wandeln.

Ich hoffe, das hilft ein bisschen weiter.

anabolik
13.03.2006, 21:10
kann ich dann <stdio.h> mit int printf (const char * __fmt, ...) verwenden? (habe eigentlich schon versuch, geht nicht)

anabolik
13.03.2006, 21:37
ok! danke leute, habe es geschafft!! steht ja alles in stdio.h.
DANKE!!!

anabolik
13.03.2006, 21:49
noch eine frage. meine verzögerung von 1 sekunde funktioniert nicht richtig(weit wenigel als 1 sekunde, ca. 100ms). ich kriege folgende warnung "warning: #warning "This file has been moved to <util/delay.h>." ". liegt der fehler in dieser warnung? wieso und welcher file wurde verschoben?

neuer CODE:

#include <stdio.h>
#include <avr/io.h>
#include <avr/delay.h>
#include "datentypen.h"

#define F_CPU 3686400
#define UART_BAUD_RATE 9600
#define MYUBRR F_CPU/(UART_BAUD_RATE * 16L) - 1


static int uart_putchar(char c, FILE *stream);

static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL,
_FDEV_SETUP_WRITE);

static int uart_putchar(char c, FILE *stream);


void InitUART(u16);




int main(void)
{

PORTD|=(1<<PD2);
InitUART(MYUBRR);

u16 cnt=0;

while(1)
{
if(!(PIND & (1<<PD2)))
{
_delay_ms(80);
if(PIND & (1<<PD2))
cnt=0;
}
stdout = &mystdout;
printf("Counter:%d\r\n",cnt);
cnt+=1;
_delay_ms(1000);
}

}





void InitUART(u16 ubrr)
{
/* Set baud rate */
UBRRH = (u8)(ubrr>>8);
UBRRL = (u8)ubrr;
/* Enable receiver and transmitter */
UCSRB = (1<<RXEN)|(1<<TXEN);
UCSRC |= (1<<URSEL)|(3<<UCSZ0); // Asynchron 8N1

}

static int
uart_putchar(char c, FILE *stream)
{


loop_until_bit_is_set(UCSRA, UDRE);
UDR = c;
return 0;
}

anabolik
13.03.2006, 22:03
ist das (The maximal possible delay is 262.14 ms / F_CPU in MHz.) die antwort?

izaseba
13.03.2006, 22:06
"warning: #warning "This file has been moved to <util/delay.h>."




#include <avr/delay.h>


:-k

anabolik
13.03.2006, 22:14
habe nicht verstanden. <avr/delay.h> habe ich doch eingefügt.

izaseba
13.03.2006, 22:26
immer noch nicht verstanden?
Was kommt für eine Warnung?


"warning: #warning "This file has been moved to <util/delay.h>."

Das wichtige schreibe ich hier mal groß "<UTIL/delay.h>" , Du schreibst es aber bitte klein :-$
Gruß Sebastian

anabolik
13.03.2006, 22:47
uups, ich habe davor immer "until" geschrieben. aber das mit "The maximal possible delay is 262.14 ms / F_CPU in MHz" stimmt oder?

izaseba
13.03.2006, 23:12
aber das mit "The maximal possible delay is 262.14 ms / F_CPU in MHz" stimmt oder?


Ja Du kannst nicht unendlich hoch gehen, sehe auch Seite (http://www.nongnu.org/avr-libc/user-manual/group__util__delay.html)
die jeder der avr-gcc verwendet kennen sollte.
wenn Du höher mit der Warteschleife gehen willst mach Dir doch eine schicke for oder while schleife:


uint8_t i =255:
while (i) {
_delay_ms(100);
i--;
}

als Beispiel

Gruß Sebastian