发送

6 使用重定义后的printf发送数据

大多数人喜欢使用重定义后的printf发送数据,但是这种方式的效率较为低下,因为在重定义时数据的发送是一个字节一个字节发送的,也就是每发送一个字节就会调用一次HAL_UART_Transmit函数。

先在左侧找到usart.c这个c文件并打开:

在这个文件中的最后的用户代码区添加代码,用户代码区如下(不在这里添加在CUBEMX重新生成代码的时候会被覆盖):

添加后如下,如果报错FILE没有定义需要添加#include "stdio.h"

/* USER CODE BEGIN 1 */

//加入以下代码,支持printf函数,而不需要选择use MicroLIB      
//#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)    
#if 1
//#pragma import(__use_no_semihosting)             
//标准库需要的支持函数                 
struct __FILE 
{ 
    int handle; 
}; 

FILE __stdout;       
//定义_sys_exit()以避免使用半主机模式    
void _sys_exit(int x) 
{ 
    x = x; 
} 
//重定义fputc函数 
int fputc(int ch, FILE *f)
{     
     HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0x0001);  
    return ch;
}
#endif 

/* USER CODE END 1 */

那么重定义就已经完成。下一步进行printf的调用,修改while(1)中的代码如下则完成。

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
        printf("hello");
        HAL_Delay(1000);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }

6 使用优化后的(类)printf发送数据

大家使用Printf只是因为这个函数比较方便。

但是如果一个和printf一样方便且更加高效的函数岂不是可以完全取代printf。

但是大家显然更关注简单而忽略高效,简单对刚刚入门的人来说很重要,但对有经验的人来说高效才是更应该追求的。

找到usart.c这个c文件并打开:

先在这个文件里面添加头文件:#include <stdarg.h>和#include <stdio.h>

然后再用户代码区添加

unsigned char UartTxBuf[128]; 
void Usart1Printf(const char *format,...)
{
    uint16_t len;
    va_list args;    
    va_start(args,format);
    len = vsnprintf((char*)UartTxBuf,sizeof(UartTxBuf)+1,(char*)format,args);
    va_end(args);
    HAL_UART_Transmit(&huart1, UartTxBuf, len,0xff);
}

这个函数与重定义的区别就是此函数可以将多个字符一下子全部发送,而非一个一个发送:

这个函数可以完全当成printf使用。

例如:

  while (1)
  {
        Usart1Printf("hello");
        Usart1Printf("hello%d",10);
        HAL_Delay(1000);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }

接收

并在main.c中添加下列定义:

#include <string.h>
 
#define RXBUFFERSIZE  256     //最大接收字节数
char RxBuffer[RXBUFFERSIZE];   //接收数据
uint8_t aRxBuffer;            //接收中断缓冲
uint8_t Uart1_Rx_Cnt = 0;        //接收缓冲计数

在main()主函数中,调用一次接收中断函数

/* USER CODE BEGIN 2 */
    HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1);
/* USER CODE END 2 */

在main.c下方添加中断回调函数

/* USER CODE BEGIN 4 */
 
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  /* Prevent unused argument(s) compilation warning */
  UNUSED(huart);
  /* NOTE: This function Should not be modified, when the callback is needed,
           the HAL_UART_TxCpltCallback could be implemented in the user file
   */
 
    if(Uart1_Rx_Cnt >= 255)  //溢出判断
    {
        Uart1_Rx_Cnt = 0;
        memset(RxBuffer,0x00,sizeof(RxBuffer));
        HAL_UART_Transmit(&huart1, (uint8_t *)"数据溢出", 10,0xFFFF);     
        
    }
    else
    {
        RxBuffer[Uart1_Rx_Cnt++] = aRxBuffer;   //接收数据转存
    
        if((RxBuffer[Uart1_Rx_Cnt-1] == 0x0A)&&(RxBuffer[Uart1_Rx_Cnt-2] == 0x0D)) //判断结束位
        {
            HAL_UART_Transmit(&huart1, (uint8_t *)&RxBuffer, Uart1_Rx_Cnt,0xFFFF); //将收到的信息发送出去
            while(HAL_UART_GetState(&huart1) == HAL_UART_STATE_BUSY_TX);//检测UART发送结束
            Uart1_Rx_Cnt = 0;
            memset(RxBuffer,0x00,sizeof(RxBuffer)); //清空数组
        }
    }
    
    HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1);   //再开启接收中断
}
/* USER CODE END 4 */

个人笔记,原作者:

https://blog.csdn/as480133937/article/details/99073783

https://blog.csdn/weixin_44584198/article/details/119204872?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522167759408916800215080600%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=167759408916800215080600&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-2-119204872-null-null.142^v73^insert_down1,201^v4^add_ask,239^v2^insert_chatgpt&utm_term=stm32cubemx%20%E4%B8%B2%E5%8F%A3%E4%B8%AD%E6%96%AD%E6%8E%A5%E6%94%B6%20%E4%B8%8Eprintf&spm=1018.2226.3001.4187

更多推荐

NVIC_USART_Printf_Scanf_Getchar_Usart1Printf