一、MicroLib微库和ARM标准C库有什么区别?
MicroLib是针对以C语言编写的基于ARM嵌入式应用程序的高度优化的库。与ARM Compiler工具链附带的标准C库相比,MicroLib具有明显的代码大小优势。下图可见微库在不同内核下代码量明显少很多:

因为针对MCU,通常存储(代码)资源相对较小,为了使其能用上标准函数,工对标准C库进行了优化,以减小代码量:
1.代码(数据)量更小 (对比上图) 。
2.缺少一些不常用标准库函数,比如:文件 I/O 的库函数。
3.微库最大程度优化代码量,可能会导致有些库代码运行速度更慢。
微库函数也是一种函数,其很多库函数原型在网上都能找到,如果你有特殊需求,可以不用微库,在库函数原型的基础上进行修改。比如:你的项目经过验证,发现微库的代码量,或者运行速度都不理想的情况下,可以自己修改原型函数。当然,在万不得已的情况下才建议修改原型函数。通常还是建议直接使用微库,毕竟经过别人多次验证的库,出现bug的概率更小。
keil上打开MicroLIB

二、修改usart.c
1)usart.h,在头文件头部定义段加入stdio.h
cpp
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USART_H__
#define __USART_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
#include "stdio.h"
/* USER CODE END Includes */
2)重写fputc() & fgetc函数
cpp
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "usart.h"
/* USER CODE BEGIN 0 */
extern UART_HandleTypeDef huart1;
/**
* @brief 重写C标准库fputc函数,重定向printf到串口1
* @param ch 要输出的字符
* @param f 输出流(printf默认传stdout,可忽略)
* @retval 成功输出的字符
*/
int fputc(int ch, FILE *f)
{
// 阻塞式发送字符到串口1(确保发送完成)
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY); ///< 普通串口发送数据
while(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_TC) == RESET)
{
}///<等待发送完成
// 符合标准库返回要求
return ch;
}
/**
* @brief 重写C标准库fgetc函数,重定向scanf/getchar到串口1
* @param f 输入流(scanf默认传stdin,可忽略)
* @retval 成功接收的字符
*/
int fgetc(FILE * f)
{
uint8_t ch = 0;
HAL_UART_Receive(&huart1, &ch, 1, HAL_MAX_DELAY); ///< 普通串口接收数据
while(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_RXNE) == RESET)
{
}///<等待接收完成
// 符合标准库返回要求
return ch;
}
/* USER CODE END 0 */
3)main 函数的测试代码:
cpp
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
printf("STM32 HAL_UART_Transmit Success: %d\r\n", 12345); // 自动调用重写的fputc
4)运行效果

5)串口发送/接收函数
- HAL_UART_Transmit();串口发送数据,使用超时管理机制
- HAL_UART_Receive();串口接收数据,使用超时管理机制
- HAL_UART_Transmit_IT();串口中断模式发送
- HAL_UART_Receive_IT();串口中断模式接收
- HAL_UART_Transmit_DMA();串口DMA模式发送
- HAL_UART_Transmit_DMA();串口DMA模式接收
6)串口中断函数
- HAL_UART_IRQHandler(UART_HandleTypeDef *huart); //串口中断处理函数
- HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart); //串口发送中断回调函数
- HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart); //串口发送一半中断回调函数(用的较少)
- HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart); //串口接收中断回调函数
- HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart);//串口接收一半回调函数(用的较少)
- HAL_UART_ErrorCallback();串口接收错误函数