Вывод printf в UART STM32 в IAR

Я писал статью об USART в STM32, сейчас же речь пойдет о том, как сделать так, что бы при вызове самой обычной printf данные отправлялись в UART.
Это нужно скорее для удобства. Допустим вам нужно организовать вывод дробных чисел. Без использования printf Вам понадобиться написать функцию для преобразования данных в строку. В принципе это не сложно и можно использовать sfprintf, но можно просто перенаправить вывод printf в нужную периферию (в нашем случае UART).

В разных средах программирования это делается по разному (из-за различных компиляторов, а иногда и реализаций библиотечных функций).
Для перенаправления вывода в IAR нужно добавить в проект файл из каталога среды. У меня вот так:

С:\Program Files\IAR Systems\Embedded Workbench 5.0 Evaluation\ARM\src\lib\write.c

Теперь найдите в нем функцию __write и уберите #ifdef чтобы получилось вот так:

size_t __write(int handle, const unsigned char * buffer, size_t size)
{
  /* Remove the #if #endif pair to enable the implementation */
  

  size_t nChars = 0;

  if (buffer == 0)
  {
    /*
     * This means that we should flush internal buffers.  Since we
     * don't we just return.  (Remember, "handle" == -1 means that all
     * handles should be flushed.)
     */
    return 0;
  }

  /* This template only writes to "standard out" and "standard err",
   * for all other file handles it returns failure. */
  if (handle != _LLIO_STDOUT && handle != _LLIO_STDERR)
  {
    return _LLIO_ERROR;
  }

  for (/* Empty */; size != 0; --size)
  {
    if (MyLowLevelPutchar(*buffer++) < 0)
    {
      return _LLIO_ERROR;
    }

    ++nChars;
  }

  return nChars;
}

Отлично, эта библиотека предполагает, что мы реализуем функцию MyLowLevelPutchar, которая и будет заниматься пересылкой байта данных в нужную периферию.

int MyLowLevelPutchar(int x){
  while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
  USART_SendData(USART2, x);
  return x;
}

Думаю эта функцию Вам знакома. Ведь она просто пересылает данные в UART, подождав перед этим пока уйдут предыдущие.
Готово, теперь можем отправлять данные:

int main()
{
  STM_EVAL_LEDInit(LED3);
  STM_EVAL_LEDOn(LED3);
  
  init_usart();

  printf("Hello from stm32 printf!\r\n");
  float b = 132.89f;
  printf("b = %e", b);

  while(1) {
     STM_EVAL_LEDToggle(LED3);
     Delay(0x3FFFFF);           
  }
}

Вот как это выглядит в терминале:

Вывод printf в USART STM32

Как видите все работает ;)
Скачать проект перенаправления printf для IAR

Просмотров:   9077

Комментарии

вс, 08/24/2014 - 18:42
kyb <mailto:i.k...

Плохая практика редактировать исходники стандартных функций. Разработчики предусмотрели весьма элегантное решение.

#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__ */

/** @brief Retargets the C library printf function to the USART.
* @param None
* @retval None
*/
PUTCHAR_PROTOTYPE
{
/** Place your implementation of fputc here. E.g. write a character to the USART */
/** Loop until the end of transmission */
while ( USART_GetFlagStatus (coms[SERIAL_DEBUG_COMx].com, USART_FLAG_TC) == RESET ) {}
USART_SendData (coms[SERIAL_DEBUG_COMx].com, (uint8_t) ch);

/** Loop until the end of transmission */
//while (USART_GetFlagStatus(EVAL_COM1, USART_FLAG_TC) == RESET) {}

return ch;
}

P.S. Добавить бы сюда. выделитель синтаксиса. Или хотя бы моноширный шрифт.

вс, 08/24/2014 - 22:50
FDD03-05S4

Круто

Добавить комментарий

Plain text

  • HTML-теги не обрабатываются и показываются как обычный текст
  • Адреса страниц и электронной почты автоматически преобразуются в ссылки.
  • Строки и параграфы переносятся автоматически.
CAPTCHA
Введи эти символы. Ато роботы одолели!