Как перенастроить printf() на STM32F10x?
Я использую этот код для ретаргетинга printf()
, Но это не работает
#ifdef __GNUC__
/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
PUTCHAR_PROTOTYPE
{
/* Place your implementation of fputc here */
/* e.g. write a character to the LCD */
lcd_Data_Write((u8)ch);
return ch;
}
Я использую STM32F103RBT6
компилятор: GCC с редактором emBitz
3 ответа
Танк ты Бенс Кауликс
Я использую библиотеку tinyprintf, и она работала довольно хорошо: ссылка на github
Попробуйте угнать функцию _write следующим образом:
#define STDOUT_FILENO 1
#define STDERR_FILENO 2
int _write(int file, char *ptr, int len)
{
switch (file)
{
case STDOUT_FILENO: /*stdout*/
// Send the string somewhere
break;
case STDERR_FILENO: /* stderr */
// Send the string somewhere
break;
default:
return -1;
}
return len;
}
В качестве альтернативы, вы можете написать свой собственный printf()
использование функции, функции переменных аргумента (va_list).
С va_list
Пользовательская функция печати выглядит следующим образом:
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
void vprint(const char *fmt, va_list argp)
{
char string[200];
if(0 < vsprintf(string,fmt,argp)) // build string
{
HAL_UART_Transmit(&huart1, (uint8_t*)string, strlen(string), 0xffffff); // send message via UART
}
}
void my_printf(const char *fmt, ...) // custom printf() function
{
va_list argp;
va_start(argp, fmt);
vprint(target, fmt, argp);
va_end(argp);
}
Пример использования:
uint16_t year = 2016;
uint8_t month = 10;
uint8_t day = 02;
char* date = "date";
// "Today's date: 2015-12-18"
my_printf("Today's %s: %d-%d-%d\r\n", date, year, month, day);
Обратите внимание, что хотя это решение предоставляет вам удобную функцию, оно медленнее, чем отправка необработанных данных или использование даже sprintf()
, Я использовал это решение как на AVR, так и на микроконтроллерах STM32.
Вы могли бы дополнительно изменить vprint
как это, где periphery_t
это простой enum
тип:
void vprint(periphery_t target, const char *fmt, va_list argp)
{
char string[200];
if(0 < vsprintf(string,fmt,argp))
{
switch(target)
{
case PC: PC_send_str(string);
break;
case GSM: GSM_send_str(string);
break;
case LCD: LCD_print_str(string);
break;
default: LCD_print_str(string);
break;
}
}
}
Просто не забудьте добавить в код инициализации следующее:
// Turn off buffers, so I/O occurs immediately
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);