Come implementare printf() per inviare messaggi attraverso l'USB

Nel tutorial "Uso della porta seriale" si è visto che è possibile utilizzare il connettore USB presente sulla scheda STM32 NUCLEO per inviare dati da NUCLEO al PC grazie alle funzionalità dell'ST-LINK-v2 presente sulle schede NUCLEO.

Per implementare la funzione printf() tramite porta USB è necessario oltre a configurare l'USART2 (come si è fatto nel tutoria suddetto) reindirizzare la funzione di libreria putchar() utilizzata da printf() sull'USART2.

Per fare questo è necessario aggiungere del codice in 2 sezioni.

Per prima cosa è necessario definire una macro privata da inserire tra /* USER CODE BEGIN PM */ e /* USER CODE END PM */

/* USER CODE BEGIN PM */
#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__ */
/* USER CODE END PM */

Questa macro controlla se è stata inclusa per qualche motivo la libreria GNUC e in caso affermativo sostituisce a PUTCHAR_PROTOTYPE  la funzione putchar() , altrimenti vi sostituisce fputc()

Successivamente, nella parte finale del listato tra /* USER CODE BEGIN 4 */ e /* USER CODE END 4 */ è necessario definire cosa deve fare la funzione associata a PUTCHAR_PROTOTYPE, che nel caso specifico deve inviare il carattere nell'UART2

/* USER CODE BEGIN 4 */
/**
* @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 USART2 and Loop until the end of transmission */
HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, 0xFFFF);

return ch;
}
/* USER CODE END 4 */

È importante sottolineare che questa implementazione con HAL_UART_Transmit() arresta lo svolgimento del programma fino a quando il carattere non viene trasmesso (la funzione infatti lavora in blocking mode). Altrernativamente si potrebbe utilizzare la funzione HAL_UART_Transmit_IT() ignorando l'interrupt emesso alla fine della trasmissione. In questo caso però bisogna stare attenti che il buffer di trasmissione non si riempia creando problemi.

Test del codice

Per testare il codice aggiungere tra /* USER CODE BEGIN PV */ e /* USER CODE END PV */

uint32_t nLoop=0;

e tra /* USER CODE BEGIN 3 */ e  /* USER CODE END 3 */

printf("nLoop == %d \n\r", nLoop); 
nLoop++;
HAL_Delay(500);

Compilare e testare il codice.

Fonti:

La lezione proposta è in parte la traduzione riadattata del tutorial pubblicato alla pagina http://www.emcu.eu/how-to-implement-printf-for-send-message-via-usb-on-stm32-nucleo-boards/ .


Ultime modifiche: domenica, 6 febbraio 2022, 18:17