当我们在进行开发的时候,通常需要将一些参数进行调整来达到效果,这个时候就需要将单片机上的信息通过串口通信传送到PC机上来直观显示

一、基本的专有名词和原理介绍

        USART:只能异步通信

        USART:同步异步通信均可

        Asynchronous : 异步通信,整个过程,不会阻碍发送者的工作

        Synchronous : 同步, 同步信息一旦发送,发送者必须等到应答,才能继续后续的行为

        Hardware Flow Control:流控,调制解调器使能

        Baud Rate:波特率,表示每秒钟传送的码元符号的个数,是衡量数据传送速率的指标,它用单位时间内载波调制状态改变的次数来表示。对于串口最重要的就是波特率, 常用的波特率为 115200 与 9600

        Parity : 奇偶校验

        Wrod Length : 数据长

        Stop : 停止位

        Single Wire : 单总线, 半双工

二、操作步骤

1、CubeMX设置

        想要打印信息,CubeMX设置很简单,只需要开启串口通信即可

android 串口打印 级别 串口打印信息详解_android 串口打印 级别

         勾选后会自动分配相对应的引脚

特别注意:波特率、数据长、奇偶校验、停止位需要通信双方完全相同!!!

2、业务函数编写

        (一)基本步骤

             先引入stdio.h头文件

                在main函数外面写入printf重定向函数(来自野火)

void Usart_SendString(uint8_t *str)
{
	unsigned int k=0;
  do 
  {
      HAL_UART_Transmit(&huart1,(uint8_t *)(str + k) ,1,1000);
      k++;
  } while(*(str + k)!='\0');
  
}
//重定向c库函数printf到串口DEBUG_USART,重定向后可使用printf函数
int fputc(int ch, FILE *f)
{
	/* 发送一个字节数据到串口DEBUG_USART */
	HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 1000);	
	
	return (ch);
}

//重定向c库函数scanf到串口DEBUG_USART,重写向后可使用scanf、getchar等函数
int fgetc(FILE *f)
{		
	int ch;
	HAL_UART_Receive(&huart1, (uint8_t *)&ch, 1, 1000);	
	return (ch);
}

                接下来即可在while(1)中写printf了

        (二)条件编译

        在开发完之后就不需要继续打印信息了,但是一条一条的注释很麻烦,可以使用条件编译来简化这一过程

        (1)在最前面添加:

#define Log 1 // 打印Log信息,不想打印时改为0即可

        (2)将所有printf包裹上#if Log 与 #endif:

#if Log
printf("[info]main.c:init!\r\n");
#endif

        当不打印时把log值定义为0即可

        (三)可变参数宏(推荐使用)

        每一次打印都需要自己手动添加\r\n,可以通过可变参数宏的办法自动添加

        

#define USER_MAIN_DEBUG 1

#ifdef USER_MAIN_DEBUG
#define user_main_printf(format, ...) printf( format "\r\n", ##__VA_ARGS__)
#define user_main_info(format, ...) printf("[\tmain]info:" format "\r\n", ##__VA_ARGS__)
#define user_main_debug(format, ...) printf("[\tmain]debug:" format "\r\n", ##__VA_ARGS__)
#define user_main_error(format, ...) printf("[\tmain]error:" format "\r\n",##__VA_ARGS__)
#else
#define user_main_printf(format, ...)
#define user_main_info(format, ...)
#define user_main_debug(format, ...)
#define user_main_error(format, ...)
#endif

        如果不需要打印时,注释#define USER_MAIN_DEBUG 1这一行即可

        在打印时只需调用user_main_xxx,会自动加入\r\n

三、错误分析

        1、串口没有显示信息

                Options for Target → Targets → 勾选Use MicroLIB

                或者在重定向语句下添加代码也可解决

#pragma import(__use_no_semihosting)
	struct __FILE
	{
		int a;
	};
	FILE __stdout;
	FILE __stdin;
	void _sys_exit(int x)
	{
	}

        

        2、出现乱码

                不勾选HEX发送,接收

        3、打印不出东西

                printf中最后加上\r\n