Forum: Mikrocontroller und Digitale Elektronik uart printf vs fprintf atmega328p


von Simon W. (wysi)


Lesenswert?

Hallo zusammen

Mit dem atmega328p möchte ich Text über UART ausgeben. Mit printf() 
funktioniert dies. Mit fprintf() wird immer nur das erste Zeichen des 
Strings über UART ausgegeben.

Versucht habe ich auch FILE str_uart als "static" zu definieren. Dies 
brachte auch keine Verbesserung.

Folgend das minimal Beispiel:
1
//minimal example for UART printf vs fprintf test
2
//compiled with AtmelStudio 6.2
3
//controller: ATMEGA328P (same mikrocontroller as on Arduino UNO)
4
5
#include <stdio.h>
6
#include <avr/io.h>
7
#include <util/delay.h>
8
#include <avr/interrupt.h>
9
10
//F = 16MHz
11
//add under Project/ Toolchain/ AVR/GNU C Compiler -> Symbols -> add F_CPU=16000000UL
12
13
void init_UART(void)
14
{
15
  //Set baud rate 115200
16
  UBRR0H = 0;
17
  UBRR0L = 16;
18
  //Enable receiver and transmitter
19
  UCSR0B = (1<<RXEN0)|(1<<TXEN0);
20
  //Double Clock Speed
21
  UCSR0A = (1<<U2X0);
22
  // Set frame format: 8data, 1stop bit
23
  UCSR0C = (3<<UCSZ00); //(1<<USBS0)|
24
}
25
26
void uart_putchar(char c, FILE *stream){
27
  //wait until buffer empty
28
  while ( !( UCSR0A & (1<<UDRE0)) );
29
  //Put data into buffer
30
  UDR0 = c;
31
}
32
33
int main(void)
34
{
35
  init_UART();
36
  FILE str_uart = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);
37
  stdout = &str_uart;
38
  
39
  //works
40
  printf( "Test UART 1 \n");
41
  
42
  //doesn't work, prints only first char ('T') to UART
43
  fprintf(&str_uart, "Test UART 2 \n");
44
  
45
  
46
  while(1);
47
}


Was ist an obenstehendem Code falsch, dass immer nur das erste Zeichen 
des Strings in fprintf() ausgegeben wird?

Vilen Dank für eure Hilfe.

: Bearbeitet durch User
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Dein printf() wird vermutlich durch ein puts() ersetzt, während
das andere tatsächlich intern in ein vfprintf() verzweigt (dort
enden alle Aufrufe irgendwelcher *printf*-Funktionen).

uart_putchar() soll eine 0 zurückgeben, wenn sie das Zeichen
erfolgreich geschrieben hat.  Möglicherweise ist das ja dein Problem.

von Simon W. (wysi)


Lesenswert?

Vielen Dank für die schnelle und zielführende Hilfe. Nach dem Hinzufügen 
von return 0 in uart_putchar() funktioniert fprintf() auch korrekt.

Hier die komplette, funktionierende Lösung:
1
//minimal example for UART printf vs fprintf test
2
//compiled with AtmelStudio 6.2
3
//controller: ATMEGA328P (same mikrocontroller as on Arduino UNO)
4
5
#include <stdio.h>
6
#include <avr/io.h>
7
#include <util/delay.h>
8
#include <avr/interrupt.h>
9
10
//F = 16MHz
11
//add under Project/ Toolchain/ AVR/GNU C Compiler -> Symbols -> add F_CPU=16000000UL
12
13
void init_UART(void)
14
{
15
  //Set baud rate 115200
16
  UBRR0H = 0;
17
  UBRR0L = 16;
18
  //Enable receiver and transmitter
19
  UCSR0B = (1<<RXEN0)|(1<<TXEN0);
20
  //Double Clock Speed
21
  UCSR0A = (1<<U2X0);
22
  // Set frame format: 8data, 1stop bit
23
  UCSR0C = (3<<UCSZ00); //(1<<USBS0)|
24
}
25
26
int uart_putchar(char c, FILE *stream){
27
  //wait until buffer empty
28
  while ( !( UCSR0A & (1<<UDRE0)) );
29
  //Put data into buffer
30
  UDR0 = c;
31
  
32
  return 0;
33
}
34
35
int main(void)
36
{
37
  init_UART();
38
  FILE str_uart = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);
39
  stdout = &str_uart;
40
  
41
  //works
42
  printf( "Test UART 1 \n");
43
  
44
  //works (after adding "return 0" to "uart_putchar()")
45
  fprintf(&str_uart, "Test UART 2 \n");
46
  
47
  
48
  while(1);
49
}

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Simon W. schrieb:
> // Set frame format: 8data, 1stop bit
>   UCSR0C = (3<<UCSZ00); //(1<<USBS0)|

8N1 ist übrigens die Voreinstellung der UART.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.