STM32学习 1 ----串口通讯--阻塞式收发+支持printf

一、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();串口接收错误函数
相关推荐
AI成长日志2 小时前
【Agentic RL】1.1 什么是Agentic RL:从传统RL到智能体学习
人工智能·学习·算法
UTP协同自动化测试3 小时前
物联网模组测试难点 |APP指令下发+UART 响应+GPIO 电平变化,如何一次性验证?
功能测试·嵌入式硬件·物联网·模块测试
_李小白3 小时前
【OSG学习笔记】Day 38: TextureVisitor(纹理访问器)
android·笔记·学习
杨云龙UP4 小时前
从0到1快速学会Linux操作系统(基础),这一篇就够了!
linux·运维·服务器·学习·ubuntu·centos·ssh
头疼的程序员4 小时前
计算机网络:自顶向下方法(第七版)第八章 学习分享(三)
网络·学习·计算机网络
_李小白5 小时前
【OSG学习笔记】Day 37: NodeVisitor(顶点访问器)
笔记·学习
程序员雷欧5 小时前
大模型应用开发学习第八天
大数据·人工智能·学习
晓晓hh6 小时前
JavaSE学习——set集合和Map映射
学习
4caf16 小时前
作业2:6位数码管静态显示
嵌入式硬件·51单片机
不做无法实现的梦~6 小时前
STM32解析PPM协议
stm32·单片机·嵌入式硬件