全面深入理解STM32 HAL库:从入门到精通

引言:嵌入式开发的演进与HAL库的重要性

在嵌入式系统开发领域,特别是针对ARM Cortex-M系列微控制器的开发,STM32系列芯片以其出色的性能和丰富的外设资源占据了重要地位。随着STM32生态系统的不断发展,ST公司为开发者提供了多种编程库,其中HAL(Hardware Abstraction Layer)库作为新一代的硬件抽象层库,已经成为STM32开发的主流选择。

嵌入式开发库的演进历程

  1. 标准外设库(Standard Peripheral Library, SPL)

    • 最早期的STM32开发库
    • 直接寄存器操作封装
    • 代码效率高但移植性差
  2. Cube HAL库

    • 硬件抽象层设计
    • 跨STM32系列兼容
    • 更高的可移植性和可维护性
  3. LL库(Low-Layer Library)

    • 轻量级底层库
    • 接近寄存器操作的高效率
    • 适合对性能要求极高的场景

HAL库的出现标志着STM32开发从"面向寄存器"到"面向外设"的转变,大大降低了开发门槛,提高了代码的复用性和可维护性。

第一章:HAL库架构与设计哲学

1.1 HAL库的整体架构

HAL库采用分层设计,从上到下分为:

应用层(Application)
   ↓
中间件层(Middleware)
   ↓
HAL硬件抽象层(Hardware Abstraction Layer)
   ↓
BSP板级支持包(Board Support Package)
   ↓
CMSIS Cortex微控制器软件接口标准
   ↓
硬件层(Hardware)

1.2 HAL库的核心设计理念

抽象与统一:HAL库通过统一的API接口,将不同STM32系列芯片的差异进行抽象,使得同一份代码可以在不同型号的STM32芯片上运行。

状态机驱动:HAL库采用状态机模型管理外设状态,确保外设操作的顺序性和安全性。

中断与回调机制:提供完善的中断处理和回调函数机制,简化中断编程。

1.3 HAL库文件结构详解

// HAL库典型文件结构
STM32Cube_FW_系列名/
├── Drivers/
│   ├── CMSIS/              # ARM Cortex微控制器软件接口标准
│   └── STM32系列名_HAL_Driver/
│       ├── Inc/           # 头文件
│       │   ├── stm32系列名_hal.h
│       │   ├── stm32系列名_hal_conf.h
│       │   └── stm32系列名_hal_xxx.h(各外设头文件)
│       └── Src/           # 源文件
│           ├── stm32系列名_hal.c
│           └── stm32系列名_hal_xxx.c(各外设源文件)
├── Middlewares/           # 中间件
├── Projects/             # 示例项目
└── Utilities/            # 工具和工具

第二章:HAL库开发环境搭建

2.1 STM32CubeMX安装与配置

STM32CubeMX是ST官方提供的图形化配置工具,可以自动生成HAL库基础代码。

安装步骤:

  1. 访问ST官网下载STM32CubeMX
  2. 安装Java运行环境(JRE)
  3. 安装STM32CubeMX本体
  4. 下载所需的HAL库固件包

2.2 开发工具链选择

# 常见工具链配置示例
# 1. ARM GCC工具链
TOOLCHAIN_PATH = /usr/bin/arm-none-eabi-
CC = $(TOOLCHAIN_PATH)gcc
CXX = $(TOOLCHAIN_PATH)g++
AS = $(TOOLCHAIN_PATH)gcc -x assembler-with-cpp
LD = $(TOOLCHAIN_PATH)gcc
OBJCOPY = $(TOOLCHAIN_PATH)objcopy
SIZE = $(TOOLCHAIN_PATH)size

# 2. IAR Embedded Workbench
# 3. Keil MDK-ARM

2.3 第一个HAL库工程创建

通过STM32CubeMX创建工程的步骤:

  1. 选择芯片型号
  2. 配置系统时钟
  3. 配置外设
  4. 配置中间件
  5. 生成代码

生成的工程结构:

/* 自动生成的主函数框架 */
int main(void)
{
  /* HAL库初始化 */
  HAL_Init();
  
  /* 系统时钟配置 */
  SystemClock_Config();
  
  /* 外设初始化 */
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  // ...其他外设初始化
  
  /* 无限循环 */
  while (1)
  {
    /* 用户应用程序 */
  }
}

第三章:HAL库核心机制详解

3.1 HAL库初始化流程

/**
 * @brief HAL库初始化详细分析
 */

// HAL初始化函数
HAL_StatusTypeDef HAL_Init(void)
{
    /* 配置Flash预取指、指令缓存和数据缓存 */
#if (INSTRUCTION_CACHE_ENABLE != 0U)
    __HAL_FLASH_INSTRUCTION_CACHE_ENABLE();
#endif
    
#if (DATA_CACHE_ENABLE != 0U)
    __HAL_FLASH_DATA_CACHE_ENABLE();
#endif
    
#if (PREFETCH_ENABLE != 0U)
    __HAL_FLASH_PREFETCH_BUFFER_ENABLE();
#endif
    
    /* 设置中断优先级分组 */
    HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
    
    /* 初始化Tick定时器 */
    HAL_InitTick(TICK_INT_PRIORITY);
    
    /* 初始化底层硬件 */
    HAL_MspInit();
    
    return HAL_OK;
}

// 系统时钟配置示例
void SystemClock_Config(void)
{
    RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
    
    /* 配置主电源电压范围 */
    __HAL_RCC_PWR_CLK_ENABLE();
    __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
    
    /* 初始化HSE、LSE、HSI等振荡器 */
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
    RCC_OscInitStruct.HSEState = RCC_HSE_ON;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
    RCC_OscInitStruct.PLL.PLLM = 25;
    RCC_OscInitStruct.PLL.PLLN = 336;
    RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
    RCC_OscInitStruct.PLL.PLLQ = 7;
    HAL_RCC_OscConfig(&RCC_OscInitStruct);
    
    /* 初始化CPU、AHB、APB总线时钟 */
    RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                                |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
    HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);
}

3.2 中断管理与回调机制

HAL库采用统一的中断处理框架,通过回调函数实现用户代码与中断处理的解耦。

/**
 * @brief HAL库中断处理机制详解
 */

// 外设句柄结构体(以UART为例)
typedef struct __UART_HandleTypeDef
{
    USART_TypeDef                 *Instance;        /* 外设寄存器基地址 */
    UART_InitTypeDef              Init;             /* 外设初始化参数 */
    uint8_t                       *pTxBuffPtr;      /* 发送缓冲区指针 */
    uint16_t                      TxXferSize;       /* 发送数据大小 */
    __IO uint16_t                 TxXferCount;      /* 发送计数器 */
    uint8_t                       *pRxBuffPtr;      /* 接收缓冲区指针 */
    uint16_t                      RxXferSize;       /* 接收数据大小 */
    __IO uint16_t                 RxXferCount;      /* 接收计数器 */
    DMA_HandleTypeDef             *hdmatx;          /* 发送DMA句柄 */
    DMA_HandleTypeDef             *hdmarx;          /* 接收DMA句柄 */
    HAL_LockTypeDef               Lock;             /* 锁对象 */
    __IO HAL_UART_StateTypeDef    gState;           /* 全局状态 */
    __IO HAL_UART_StateTypeDef    RxState;          /* 接收状态 */
    __IO uint32_t                 ErrorCode;        /* 错误代码 */
} UART_HandleTypeDef;

// 中断处理函数示例
void USART1_IRQHandler(void)
{
    HAL_UART_IRQHandler(&huart1);
}

// HAL库统一中断处理函数
void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)
{
    uint32_t isrflags   = READ_REG(huart->Instance->SR);
    uint32_t cr1its     = READ_REG(huart->Instance->CR1);
    uint32_t errorflags = 0x00U;
    
    /* 处理接收中断 */
    if (((isrflags & USART_SR_RXNE) != RESET) && 
        ((cr1its & USART_CR1_RXNEIE) != RESET))
    {
        UART_Receive_IT(huart);
        return;
    }
    
    /* 处理发送中断 */
    if (((isrflags & USART_SR_TXE) != RESET) && 
        ((cr1its & USART_CR1_TXEIE) != RESET))
    {
        UART_Transmit_IT(huart);
        return;
    }
    
    /* 错误处理 */
    errorflags = (isrflags & (uint32_t)(USART_SR_PE | USART_SR_FE | 
                                        USART_SR_ORE | USART_SR_NE));
    if ((errorflags != RESET) && ((cr1its & USART_CR1_PEIE) != RESET))
    {
        huart->ErrorCode |= errorflags;
        UART_EndRxTransfer(huart);
    }
}

// 回调函数机制
__weak void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
    /* 弱函数,用户可重写 */
    UNUSED(huart);
}

__weak void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    /* 弱函数,用户可重写 */
    UNUSED(huart);
}

// 用户自定义回调函数示例
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if (huart->Instance == USART1)
    {
        /* 处理USART1接收完成 */
        uint8_t received_data = uart_rx_buffer;
        process_received_data(received_data);
        
        /* 重新启动接收 */
        HAL_UART_Receive_IT(huart, &uart_rx_buffer, 1);
    }
}

3.3 状态机与错误处理

HAL库使用状态机跟踪外设状态,确保操作的顺序性。

/**
 * @brief HAL库状态机与错误处理机制
 */

// HAL库状态定义
typedef enum
{
    HAL_UNINITIALIZED = 0x00U,    /* 未初始化 */
    HAL_INITIALIZED   = 0x01U,    /* 已初始化 */
    HAL_BUSY          = 0x02U,    /* 繁忙 */
    HAL_BUSY_TX       = 0x12U,    /* 发送繁忙 */
    HAL_BUSY_RX       = 0x22U,    /* 接收繁忙 */
    HAL_BUSY_TX_RX    = 0x32U,    /* 发送接收都繁忙 */
    HAL_TIMEOUT       = 0x03U,    /* 超时 */
    HAL_ERROR         = 0x04U,    /* 错误 */
    HAL_OK            = 0x00U     /* 正常 */
} HAL_StatusTypeDef;

// 外设特定状态(以UART为例)
typedef enum
{
    HAL_UART_STATE_RESET             = 0x00U,    /* 复位状态 */
    HAL_UART_STATE_READY             = 0x01U,    /* 就绪状态 */
    HAL_UART_STATE_BUSY              = 0x02U,    /* 繁忙状态 */
    HAL_UART_STATE_BUSY_TX           = 0x12U,    /* 发送繁忙 */
    HAL_UART_STATE_BUSY_RX           = 0x22U,    /* 接收繁忙 */
    HAL_UART_STATE_BUSY_TX_RX        = 0x32U,    /* 发送接收都繁忙 */
    HAL_UART_STATE_TIMEOUT           = 0x03U,    /* 超时 */
    HAL_UART_STATE_ERROR             = 0x04U     /* 错误状态 */
} HAL_UART_StateTypeDef;

// 错误代码定义
#define HAL_UART_ERROR_NONE         0x00000000U  /* 无错误 */
#define HAL_UART_ERROR_PE           0x00000001U  /* 奇偶校验错误 */
#define HAL_UART_ERROR_NE           0x00000002U  /* 噪声错误 */
#define HAL_UART_ERROR_FE           0x00000004U  /* 帧错误 */
#define HAL_UART_ERROR_ORE          0x00000008U  /* 溢出错误 */
#define HAL_UART_ERROR_DMA          0x00000010U  /* DMA传输错误 */

// 状态检查宏
#define __HAL_UART_GET_FLAG(__HANDLE__, __FLAG__) \
    (((__HANDLE__)->Instance->SR & (__FLAG__)) == (__FLAG__))

#define __HAL_UART_CLEAR_FLAG(__HANDLE__, __FLAG__) \
    ((__HANDLE__)->Instance->SR = ~(__FLAG__))

// 状态转换函数示例
HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, 
                                        uint8_t *pData, uint16_t Size)
{
    /* 检查参数有效性 */
    if (huart->gState == HAL_UART_STATE_READY)
    {
        if ((pData == NULL) || (Size == 0U))
        {
            return HAL_ERROR;
        }
        
        /* 进程锁定 */
        __HAL_LOCK(huart);
        
        huart->pTxBuffPtr = pData;
        huart->TxXferSize = Size;
        huart->TxXferCount = Size;
        
        /* 设置状态为发送繁忙 */
        huart->gState = HAL_UART_STATE_BUSY_TX;
        
        /* 使能发送中断 */
        __HAL_UART_ENABLE_IT(huart, UART_IT_TXE);
        
        /* 进程解锁 */
        __HAL_UNLOCK(huart);
        
        return HAL_OK;
    }
    else
    {
        return HAL_BUSY;
    }
}

第四章:GPIO操作详解

4.1 GPIO初始化与配置

/**
 * @brief GPIO配置与操作详解
 */

// GPIO初始化结构体
typedef struct
{
    uint32_t Pin;        /* 指定要配置的GPIO引脚 */
    uint32_t Mode;       /* 指定引脚模式 */
    uint32_t Pull;       /* 指定上拉/下拉电阻 */
    uint32_t Speed;      /* 指定引脚速度 */
    uint32_t Alternate;  /* 指定复用功能 */
} GPIO_InitTypeDef;

// GPIO引脚模式
#define GPIO_MODE_INPUT                0x00000000U  /* 输入模式 */
#define GPIO_MODE_OUTPUT_PP            0x00000001U  /* 推挽输出 */
#define GPIO_MODE_OUTPUT_OD            0x00000011U  /* 开漏输出 */
#define GPIO_MODE_AF_PP                0x00000002U  /* 复用推挽 */
#define GPIO_MODE_AF_OD                0x00000012U  /* 复用开漏 */
#define GPIO_MODE_ANALOG               0x00000003U  /* 模拟模式 */
#define GPIO_MODE_IT_RISING            0x10110000U  /* 上升沿中断 */
#define GPIO_MODE_IT_FALLING           0x10210000U  /* 下降沿中断 */
#define GPIO_MODE_IT_RISING_FALLING    0x10310000U  /* 双边沿中断 */
#define GPIO_MODE_EVT_RISING           0x10120000U  /* 上升沿事件 */
#define GPIO_MODE_EVT_FALLING          0x10220000U  /* 下降沿事件 */
#define GPIO_MODE_EVT_RISING_FALLING   0x10320000U  /* 双边沿事件 */

// GPIO速度
#define GPIO_SPEED_FREQ_LOW         0x00000000U  /* 低速 */
#define GPIO_SPEED_FREQ_MEDIUM      0x00000001U  /* 中速 */
#define GPIO_SPEED_FREQ_HIGH        0x00000002U  /* 高速 */
#define GPIO_SPEED_FREQ_VERY_HIGH   0x00000003U  /* 超高速 */

// GPIO上拉/下拉
#define GPIO_NOPULL                 0x00000000U  /* 无上拉下拉 */
#define GPIO_PULLUP                 0x00000001U  /* 上拉 */
#define GPIO_PULLDOWN               0x00000002U  /* 下拉 */

// GPIO初始化示例
void MX_GPIO_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    
    /* GPIO端口时钟使能 */
    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
    __HAL_RCC_GPIOC_CLK_ENABLE();
    
    /* 配置LED引脚(PC13) */
    GPIO_InitStruct.Pin = GPIO_PIN_13;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    
    /* 配置按键引脚(PA0) */
    GPIO_InitStruct.Pin = GPIO_PIN_0;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
    /* 配置USART1 TX/RX引脚(PA9/PA10) */
    GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}

4.2 GPIO高级功能:中断与事件

/**
 * @brief GPIO中断与事件处理
 */

// GPIO中断回调函数原型
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin);

// GPIO中断配置示例
void GPIO_Interrupt_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    
    /* 配置外部中断引脚 */
    GPIO_InitStruct.Pin = GPIO_PIN_0;
    GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;  /* 下降沿触发中断 */
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
    /* 配置中断优先级 */
    HAL_NVIC_SetPriority(EXTI0_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(EXTI0_IRQn);
}

// 外部中断处理函数
void EXTI0_IRQHandler(void)
{
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
}

// HAL库的中断处理函数
void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
    /* 清除中断标志位 */
    __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
    
    /* 调用回调函数 */
    HAL_GPIO_EXTI_Callback(GPIO_Pin);
}

// 用户定义的回调函数
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    if (GPIO_Pin == GPIO_PIN_0)
    {
        /* 处理PA0引脚的中断 */
        HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);  /* 翻转LED */
        
        /* 去抖动处理 */
        HAL_Delay(50);
    }
}

// GPIO事件模式配置(不产生中断)
void GPIO_Event_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    
    /* 配置事件模式引脚 */
    GPIO_InitStruct.Pin = GPIO_PIN_1;
    GPIO_InitStruct.Mode = GPIO_MODE_EVT_RISING;  /* 上升沿事件 */
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}

4.3 GPIO位操作与原子操作

/**
 * @brief GPIO位带操作与原子操作
 */

// 传统的GPIO操作方式
void Traditional_GPIO_Operations(void)
{
    /* 设置引脚 */
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
    
    /* 读取引脚 */
    GPIO_PinState state = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5);
    
    /* 翻转引脚 */
    HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
}

// 位带操作宏定义(Cortex-M3/M4/M7支持)
#define BITBAND(addr, bitnum) ((addr & 0xF0000000) + 0x02000000 + 
                              ((addr & 0x000FFFFF) << 5) + (bitnum << 2))
#define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
#define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))

// GPIO位带地址计算
#define GPIOA_ODR_Addr    (GPIOA_BASE + 0x14)
#define GPIOA_IDR_Addr    (GPIOA_BASE + 0x10)

// 使用位带操作
void BitBand_GPIO_Operations(void)
{
    /* 使用位带设置PA5为高电平 */
    BIT_ADDR(GPIOA_ODR_Addr, 5) = 1;
    
    /* 使用位带读取PA5状态 */
    uint32_t state = BIT_ADDR(GPIOA_IDR_Addr, 5);
    
    /* 使用位带翻转PA5 */
    BIT_ADDR(GPIOA_ODR_Addr, 5) = !BIT_ADDR(GPIOA_IDR_Addr, 5);
}

// 原子操作示例
#include "stdatomic.h"

// 使用原子操作保护共享资源
atomic_flag gpio_lock = ATOMIC_FLAG_INIT;

void Atomic_GPIO_Operation(uint16_t pin, GPIO_PinState state)
{
    /* 自旋锁等待 */
    while (atomic_flag_test_and_set(&gpio_lock)) 
    {
        /* 等待锁释放 */
    }
    
    /* 临界区:安全的GPIO操作 */
    HAL_GPIO_WritePin(GPIOA, pin, state);
    
    /* 释放锁 */
    atomic_flag_clear(&gpio_lock);
}

// 批量GPIO操作优化
void Bulk_GPIO_Operations(void)
{
    /* 一次性设置多个引脚 */
    GPIOA->BSRR = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2;  /* 设置PA0, PA1, PA2 */
    
    /* 一次性清除多个引脚 */
    GPIOA->BSRR = (GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5) << 16;  /* 清除PA3, PA4, PA5 */
    
    /* 一次性读取多个引脚 */
    uint16_t pin_values = GPIOA->IDR & (GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2);
}

第五章:定时器(TIM)高级应用

5.1 定时器基础配置

/**
 * @brief 定时器配置与应用
 */

// 定时器初始化结构体
typedef struct
{
    uint32_t Prescaler;          /* 预分频器 */
    uint32_t CounterMode;        /* 计数模式 */
    uint32_t Period;             /* 自动重载值 */
    uint32_t ClockDivision;      /* 时钟分频 */
    uint32_t RepetitionCounter;  /* 重复计数器(高级定时器) */
    uint32_t AutoReloadPreload;  /* 自动重载预装载 */
} TIM_Base_InitTypeDef;

// 定时器工作模式
#define TIM_COUNTERMODE_UP             0x00000000U  /* 向上计数 */
#define TIM_COUNTERMODE_DOWN           0x00000010U  /* 向下计数 */
#define TIM_COUNTERMODE_CENTERALIGNED1 0x00000020U  /* 中央对齐模式1 */
#define TIM_COUNTERMODE_CENTERALIGNED2 0x00000040U  /* 中央对齐模式2 */
#define TIM_COUNTERMODE_CENTERALIGNED3 0x00000060U  /* 中央对齐模式3 */

// 定时器时钟分频
#define TIM_CLOCKDIVISION_DIV1         0x00000000U  /* 不分频 */
#define TIM_CLOCKDIVISION_DIV2         0x00000100U  /* 2分频 */
#define TIM_CLOCKDIVISION_DIV4         0x00000200U  /* 4分频 */

// 基本定时器配置
void Basic_Timer_Config(void)
{
    TIM_HandleTypeDef htim6;
    TIM_MasterConfigTypeDef sMasterConfig = {0};
    
    htim6.Instance = TIM6;
    htim6.Init.Prescaler = 8399;           /* 预分频:84MHz/8400 = 10kHz */
    htim6.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim6.Init.Period = 9999;              /* 自动重载值:10000个计数 */
    htim6.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
    
    if (HAL_TIM_Base_Init(&htim6) != HAL_OK)
    {
        Error_Handler();
    }
    
    /* 主输出配置 */
    sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
    sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
    HAL_TIMEx_MasterConfigSynchronization(&htim6, &sMasterConfig);
}

// 通用定时器配置(PWM输出)
void PWM_Timer_Config(void)
{
    TIM_HandleTypeDef htim2;
    TIM_OC_InitTypeDef sConfigOC = {0};
    TIM_MasterConfigTypeDef sMasterConfig = {0};
    
    htim2.Instance = TIM2;
    htim2.Init.Prescaler = 83;            /* 84MHz/84 = 1MHz */
    htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim2.Init.Period = 999;              /* 1000个计数 = 1kHz PWM */
    htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
    
    HAL_TIM_PWM_Init(&htim2);
    
    /* 配置PWM通道1 */
    sConfigOC.OCMode = TIM_OCMODE_PWM1;
    sConfigOC.Pulse = 500;                /* 50%占空比 */
    sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
    sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
    HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1);
    
    /* 主输出配置 */
    sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
    sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
    HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig);
    
    /* 启动PWM输出 */
    HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
}

5.2 定时器中断与DMA

/**
 * @brief 定时器中断与DMA传输
 */

// 定时器更新中断配置
void Timer_Update_Interrupt_Config(void)
{
    TIM_HandleTypeDef htim7;
    
    htim7.Instance = TIM7;
    htim7.Init.Prescaler = 8399;           /* 10kHz */
    htim7.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim7.Init.Period = 9999;              /* 1秒中断 */
    
    HAL_TIM_Base_Init(&htim7);
    
    /* 配置中断 */
    HAL_NVIC_SetPriority(TIM7_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(TIM7_IRQn);
    
    /* 使能更新中断 */
    __HAL_TIM_ENABLE_IT(&htim7, TIM_IT_UPDATE);
    
    /* 启动定时器 */
    HAL_TIM_Base_Start(&htim7);
}

// 定时器中断处理
void TIM7_IRQHandler(void)
{
    HAL_TIM_IRQHandler(&htim7);
}

// 定时器更新回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if (htim->Instance == TIM7)
    {
        /* 1秒定时任务 */
        HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
        
        /* 执行其他周期性任务 */
        periodic_task_handler();
    }
}

// 定时器DMA传输(用于精确的PWM控制)
void Timer_DMA_Config(void)
{
    TIM_HandleTypeDef htim3;
    DMA_HandleTypeDef hdma_tim3_ch1;
    TIM_OC_InitTypeDef sConfigOC = {0};
    
    uint32_t pwm_data[] = {100, 200, 300, 400, 500, 600, 700, 800, 900};
    uint32_t data_count = sizeof(pwm_data) / sizeof(pwm_data[0]);
    
    /* 定时器配置 */
    htim3.Instance = TIM3;
    htim3.Init.Prescaler = 83;            /* 1MHz */
    htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim3.Init.Period = 999;              /* 1kHz */
    htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
    
    HAL_TIM_PWM_Init(&htim3);
    
    /* PWM通道配置 */
    sConfigOC.OCMode = TIM_OCMODE_PWM1;
    sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
    sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
    HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1);
    
    /* DMA配置 */
    hdma_tim3_ch1.Instance = DMA1_Stream4;
    hdma_tim3_ch1.Init.Channel = DMA_CHANNEL_5;
    hdma_tim3_ch1.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_tim3_ch1.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_tim3_ch1.Init.MemInc = DMA_MINC_ENABLE;
    hdma_tim3_ch1.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
    hdma_tim3_ch1.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
    hdma_tim3_ch1.Init.Mode = DMA_CIRCULAR;  /* 循环模式 */
    hdma_tim3_ch1.Init.Priority = DMA_PRIORITY_HIGH;
    hdma_tim3_ch1.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    
    HAL_DMA_Init(&hdma_tim3_ch1);
    
    /* 关联DMA到定时器 */
    __HAL_LINKDMA(&htim3, hdma[TIM_DMA_ID_CC1], hdma_tim3_ch1);
    
    /* 启动DMA传输 */
    HAL_TIM_PWM_Start_DMA(&htim3, TIM_CHANNEL_1, 
                          (uint32_t*)pwm_data, data_count);
}

// DMA传输完成回调
void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
{
    if (htim->Instance == TIM3)
    {
        /* DMA传输完成处理 */
        dma_transfer_complete_handler();
    }
}

5.3 高级定时器功能

/**
 * @brief 高级定时器应用(TIM1/TIM8)
 */

// 互补PWM输出(用于电机控制)
void Complementary_PWM_Config(void)
{
    TIM_HandleTypeDef htim1;
    TIM_OC_InitTypeDef sConfigOC = {0};
    TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};
    
    htim1.Instance = TIM1;
    htim1.Init.Prescaler = 0;
    htim1.Init.CounterMode = TIM_COUNTERMODE_CENTERALIGNED1;
    htim1.Init.Period = 8399;                     /* 84MHz/8400 = 10kHz */
    htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    htim1.Init.RepetitionCounter = 0;
    htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
    
    HAL_TIM_PWM_Init(&htim1);
    
    /* 配置PWM通道1 */
    sConfigOC.OCMode = TIM_OCMODE_PWM1;
    sConfigOC.Pulse = 4200;                       /* 50%占空比 */
    sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
    sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;  /* 互补通道极性 */
    sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
    sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
    sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
    
    HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1);
    
    /* 配置死区时间 */
    sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
    sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
    sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
    sBreakDeadTimeConfig.DeadTime = 72;           /* 死区时间 = 72 * 11.9ns ≈ 857ns */
    sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
    sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
    sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
    
    HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig);
    
    /* 启动主输出和互补输出 */
    HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1);
    HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
}

// 输入捕获配置(测量频率/脉宽)
void Input_Capture_Config(void)
{
    TIM_HandleTypeDef htim2;
    TIM_IC_InitTypeDef sConfigIC = {0};
    
    htim2.Instance = TIM2;
    htim2.Init.Prescaler = 83;                    /* 1MHz计数频率 */
    htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim2.Init.Period = 0xFFFFFFFF;               /* 最大计数值 */
    htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
    
    HAL_TIM_IC_Init(&htim2);
    
    /* 输入捕获通道1配置 */
    sConfigIC.ICPolarity = TIM_ICPOLARITY_RISING;  /* 上升沿捕获 */
    sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
    sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;        /* 不分频 */
    sConfigIC.ICFilter = 0;                        /* 无滤波 */
    
    HAL_TIM_IC_ConfigChannel(&htim2, &sConfigIC, TIM_CHANNEL_1);
    
    /* 启动输入捕获 */
    HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);
}

// 输入捕获中断处理
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
    static uint32_t last_capture = 0;
    static uint32_t frequency = 0;
    static uint32_t duty_cycle = 0;
    
    if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
    {
        uint32_t current_capture = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
        
        if (last_capture != 0)
        {
            /* 计算频率 */
            uint32_t period = (current_capture > last_capture) ? 
                             (current_capture - last_capture) : 
                             (0xFFFFFFFF - last_capture + current_capture);
            
            frequency = 1000000 / period;  /* 1MHz计数时钟 */
            
            /* 如果是PWM测量,还需要捕获下降沿 */
            if (htim->Instance->CCER & TIM_CCER_CC1P)
            {
                /* 下降沿捕获,计算占空比 */
                duty_cycle = (current_capture * 100) / period;
                
                /* 重新配置为上升沿捕获 */
                __HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, 
                                             TIM_ICPOLARITY_RISING);
            }
            else
            {
                /* 上升沿捕获,重新配置为下降沿捕获 */
                __HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, 
                                             TIM_ICPOLARITY_FALLING);
            }
        }
        
        last_capture = current_capture;
    }
}

第六章:串口通信(UART/USART)深入解析

6.1 UART基础配置与通信

/**
 * @brief UART/USART串口通信详解
 */

// UART初始化结构体
typedef struct
{
    uint32_t BaudRate;                  /* 波特率 */
    uint32_t WordLength;                /* 字长 */
    uint32_t StopBits;                  /* 停止位 */
    uint32_t Parity;                    /* 校验位 */
    uint32_t Mode;                      /* 发送/接收模式 */
    uint32_t HwFlowCtl;                 /* 硬件流控制 */
    uint32_t OverSampling;              /* 过采样 */
} UART_InitTypeDef;

// UART工作模式
#define UART_MODE_RX                   0x00000001U  /* 接收模式 */
#define UART_MODE_TX                   0x00000002U  /* 发送模式 */
#define UART_MODE_TX_RX                (UART_MODE_TX | UART_MODE_RX)  /* 全双工 */

// 校验位配置
#define UART_PARITY_NONE               0x00000000U  /* 无校验 */
#define UART_PARITY_EVEN               0x00000002U  /* 偶校验 */
#define UART_PARITY_ODD                0x00000003U  /* 奇校验 */

// 停止位配置
#define UART_STOPBITS_1                0x00000000U  /* 1个停止位 */
#define UART_STOPBITS_2                0x00000002U  /* 2个停止位 */
#define UART_STOPBITS_1_5              0x00000003U  /* 1.5个停止位 */

// 硬件流控制
#define UART_HWCONTROL_NONE            0x00000000U  /* 无硬件流控 */
#define UART_HWCONTROL_RTS             0x00000100U  /* 启用RTS */
#define UART_HWCONTROL_CTS             0x00000200U  /* 启用CTS */
#define UART_HWCONTROL_RTS_CTS         (UART_HWCONTROL_RTS | UART_HWCONTROL_CTS)

// UART初始化示例
void UART_Init_Config(void)
{
    UART_HandleTypeDef huart1;
    
    huart1.Instance = USART1;
    huart1.Init.BaudRate = 115200;
    huart1.Init.WordLength = UART_WORDLENGTH_8B;
    huart1.Init.StopBits = UART_STOPBITS_1;
    huart1.Init.Parity = UART_PARITY_NONE;
    huart1.Init.Mode = UART_MODE_TX_RX;
    huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    huart1.Init.OverSampling = UART_OVERSAMPLING_16;
    
    if (HAL_UART_Init(&huart1) != HAL_OK)
    {
        Error_Handler();
    }
}

// 轮询方式发送数据
void UART_Polling_Transmit(uint8_t *data, uint16_t size)
{
    HAL_UART_Transmit(&huart1, data, size, HAL_MAX_DELAY);
}

// 轮询方式接收数据
void UART_Polling_Receive(uint8_t *buffer, uint16_t size)
{
    HAL_UART_Receive(&huart1, buffer, size, HAL_MAX_DELAY);
}

// 中断方式发送数据
void UART_Interrupt_Transmit(uint8_t *data, uint16_t size)
{
    HAL_UART_Transmit_IT(&huart1, data, size);
}

// 中断方式接收数据
void UART_Interrupt_Receive(uint8_t *buffer, uint16_t size)
{
    HAL_UART_Receive_IT(&huart1, buffer, size);
}

// DMA方式发送数据
void UART_DMA_Transmit(uint8_t *data, uint16_t size)
{
    HAL_UART_Transmit_DMA(&huart1, data, size);
}

// DMA方式接收数据
void UART_DMA_Receive(uint8_t *buffer, uint16_t size)
{
    HAL_UART_Receive_DMA(&huart1, buffer, size);
}

6.2 UART高级功能与协议实现

/**
 * @brief UART高级应用:自定义协议与错误处理
 */

// 自定义通信协议结构
typedef struct
{
    uint8_t header[2];      /* 帧头:0xAA 0x55 */
    uint8_t cmd;           /* 命令字 */
    uint8_t length;        /* 数据长度 */
    uint8_t data[32];      /* 数据域 */
    uint8_t checksum;      /* 校验和 */
} UART_Frame_t;

// UART接收状态机
typedef enum
{
    UART_RX_STATE_IDLE = 0,      /* 空闲状态 */
    UART_RX_STATE_HEADER1,       /* 接收帧头1 */
    UART_RX_STATE_HEADER2,       /* 接收帧头2 */
    UART_RX_STATE_CMD,           /* 接收命令字 */
    UART_RX_STATE_LENGTH,        /* 接收数据长度 */
    UART_RX_STATE_DATA,          /* 接收数据 */
    UART_RX_STATE_CHECKSUM       /* 接收校验和 */
} UART_RxState_t;

// UART接收缓冲区
typedef struct
{
    uint8_t buffer[256];         /* 接收缓冲区 */
    uint16_t write_index;        /* 写指针 */
    uint16_t read_index;         /* 读指针 */
    uint16_t frame_count;        /* 接收到的帧数 */
    UART_RxState_t state;        /* 接收状态 */
    UART_Frame_t current_frame;  /* 当前正在接收的帧 */
    uint8_t data_index;          /* 数据接收索引 */
} UART_RxBuffer_t;

// UART接收状态机实现
void UART_RxStateMachine(UART_RxBuffer_t *rx_buf, uint8_t data)
{
    static uint8_t calc_checksum = 0;
    
    switch (rx_buf->state)
    {
        case UART_RX_STATE_IDLE:
            if (data == 0xAA)
            {
                rx_buf->state = UART_RX_STATE_HEADER1;
                calc_checksum = 0;
            }
            break;
            
        case UART_RX_STATE_HEADER1:
            if (data == 0x55)
            {
                rx_buf->state = UART_RX_STATE_HEADER2;
                calc_checksum += data;
            }
            else
            {
                rx_buf->state = UART_RX_STATE_IDLE;
            }
            break;
            
        case UART_RX_STATE_HEADER2:
            rx_buf->current_frame.cmd = data;
            rx_buf->state = UART_RX_STATE_CMD;
            calc_checksum += data;
            break;
            
        case UART_RX_STATE_CMD:
            rx_buf->current_frame.length = data;
            rx_buf->state = UART_RX_STATE_LENGTH;
            rx_buf->data_index = 0;
            calc_checksum += data;
            break;
            
        case UART_RX_STATE_LENGTH:
            if (rx_buf->data_index < rx_buf->current_frame.length)
            {
                rx_buf->current_frame.data[rx_buf->data_index++] = data;
                calc_checksum += data;
                
                if (rx_buf->data_index >= rx_buf->current_frame.length)
                {
                    rx_buf->state = UART_RX_STATE_CHECKSUM;
                }
            }
            else
            {
                rx_buf->state = UART_RX_STATE_IDLE;
            }
            break;
            
        case UART_RX_STATE_CHECKSUM:
            if (calc_checksum == data)
            {
                /* 校验成功,处理完整帧 */
                UART_FrameHandler(&rx_buf->current_frame);
                rx_buf->frame_count++;
            }
            rx_buf->state = UART_RX_STATE_IDLE;
            break;
            
        default:
            rx_buf->state = UART_RX_STATE_IDLE;
            break;
    }
}

// UART接收中断回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    static UART_RxBuffer_t uart_rx_buffer;
    static uint8_t rx_byte;
    
    if (huart->Instance == USART1)
    {
        rx_byte = uart_rx_byte;  /* 从全局变量获取接收到的字节 */
        
        /* 状态机处理 */
        UART_RxStateMachine(&uart_rx_buffer, rx_byte);
        
        /* 重新启动接收 */
        HAL_UART_Receive_IT(huart, &uart_rx_byte, 1);
    }
}

// UART错误处理
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
    uint32_t error_code = huart->ErrorCode;
    
    if (error_code & HAL_UART_ERROR_PE)
    {
        /* 奇偶校验错误 */
        uart_parity_error_handler();
    }
    
    if (error_code & HAL_UART_ERROR_FE)
    {
        /* 帧错误 */
        uart_frame_error_handler();
    }
    
    if (error_code & HAL_UART_ERROR_ORE)
    {
        /* 溢出错误 */
        uart_overrun_error_handler();
    }
    
    if (error_code & HAL_UART_ERROR_DMA)
    {
        /* DMA传输错误 */
        uart_dma_error_handler();
    }
    
    /* 清除错误标志并重新初始化UART */
    __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_PEF | UART_CLEAR_FEF | 
                          UART_CLEAR_OREF);
    
    /* 重新启动接收 */
    HAL_UART_Receive_IT(huart, &uart_rx_byte, 1);
}

// UART DMA双缓冲区接收
void UART_DMA_DoubleBuffer_Config(void)
{
    static uint8_t rx_buffer1[256];
    static uint8_t rx_buffer2[256];
    static uint8_t *current_buffer = rx_buffer1;
    static uint8_t buffer_toggle = 0;
    
    /* 配置DMA为循环模式,双缓冲区 */
    hdma_usart1_rx.Instance = DMA1_Stream5;
    hdma_usart1_rx.Init.Channel = DMA_CHANNEL_4;
    hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_usart1_rx.Init.Mode = DMA_CIRCULAR;
    hdma_usart1_rx.Init.Priority = DMA_PRIORITY_HIGH;
    hdma_usart1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    
    HAL_DMA_Init(&hdma_usart1_rx);
    __HAL_LINKDMA(&huart1, hdmarx, hdma_usart1_rx);
    
    /* 启动DMA接收 */
    HAL_UART_Receive_DMA(&huart1, current_buffer, 256);
}

// DMA半传输和传输完成中断
void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart)
{
    /* 前半缓冲区数据已满 */
    if (huart->Instance == USART1)
    {
        /* 处理前半缓冲区数据 */
        Process_RxBuffer(rx_buffer1, 128);
    }
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    /* 后半缓冲区数据已满 */
    if (huart->Instance == USART1)
    {
        /* 处理后半缓冲区数据 */
        Process_RxBuffer(rx_buffer1 + 128, 128);
    }
}

6.3 多串口管理与RS485通信

/**
 * @brief 多串口系统与RS485通信实现
 */

// 多串口管理系统
typedef struct
{
    UART_HandleTypeDef *huart;
    uint8_t rx_buffer[256];
    uint16_t rx_index;
    uint8_t tx_buffer[256];
    uint16_t tx_index;
    void (*frame_handler)(uint8_t *data, uint16_t length);
    uint32_t last_activity_time;
} UART_Manager_t;

// 全局串口管理器数组
UART_Manager_t uart_managers[] = {
    {&huart1, {0}, 0, {0}, 0, UART1_FrameHandler, 0},
    {&huart2, {0}, 0, {0}, 0, UART2_FrameHandler, 0},
    {&huart3, {0}, 0, {0}, 0, UART3_FrameHandler, 0},
};

#define UART_MANAGER_COUNT (sizeof(uart_managers) / sizeof(uart_managers[0]))

// 统一的中断处理分发
void UART_IRQ_Dispatcher(UART_HandleTypeDef *huart)
{
    for (int i = 0; i < UART_MANAGER_COUNT; i++)
    {
        if (uart_managers[i].huart->Instance == huart->Instance)
        {
            HAL_UART_IRQHandler(huart);
            break;
        }
    }
}

// RS485通信实现
typedef struct
{
    UART_HandleTypeDef *huart;
    GPIO_TypeDef *de_port;      /* 方向控制端口 */
    uint16_t de_pin;            /* 方向控制引脚 */
    uint8_t address;            /* 本机地址 */
    uint8_t rx_buffer[256];
    uint8_t tx_buffer[256];
    uint32_t timeout;           /* 接收超时时间 */
    uint32_t last_rx_time;      /* 最后接收时间 */
} RS485_Manager_t;

// RS485发送使能
void RS485_Send_Enable(RS485_Manager_t *rs485)
{
    HAL_GPIO_WritePin(rs485->de_port, rs485->de_pin, GPIO_PIN_SET);
    HAL_Delay(1);  /* 等待线路稳定 */
}

// RS485接收使能
void RS485_Receive_Enable(RS485_Manager_t *rs485)
{
    HAL_GPIO_WritePin(rs485->de_port, rs485->de_pin, GPIO_PIN_RESET);
    HAL_Delay(1);  /* 等待线路稳定 */
}

// RS485发送数据
HAL_StatusTypeDef RS485_Send(RS485_Manager_t *rs485, 
                             uint8_t address, 
                             uint8_t *data, 
                             uint16_t length)
{
    if (length > 250)
    {
        return HAL_ERROR;  /* 数据太长 */
    }
    
    /* 构造RS485帧 */
    uint8_t frame[256];
    frame[0] = 0xAA;                /* 帧头 */
    frame[1] = 0x55;                /* 帧头 */
    frame[2] = address;             /* 目标地址 */
    frame[3] = rs485->address;      /* 源地址 */
    frame[4] = length;              /* 数据长度 */
    
    memcpy(&frame[5], data, length);
    
    /* 计算CRC校验 */
    uint16_t crc = Calculate_CRC16(frame, length + 5);
    frame[length + 5] = (crc >> 8) & 0xFF;
    frame[length + 6] = crc & 0xFF;
    
    /* 切换到发送模式 */
    RS485_Send_Enable(rs485);
    
    /* 发送数据 */
    HAL_StatusTypeDef status = HAL_UART_Transmit(rs485->huart, 
                                                 frame, 
                                                 length + 7, 
                                                 1000);
    
    /* 等待发送完成 */
    HAL_Delay(1);
    
    /* 切换回接收模式 */
    RS485_Receive_Enable(rs485);
    
    return status;
}

// RS485接收处理
void RS485_Receive_Handler(RS485_Manager_t *rs485)
{
    static uint8_t rx_state = 0;
    static uint8_t rx_length = 0;
    static uint8_t rx_index = 0;
    static uint8_t rx_buffer[256];
    static uint32_t last_byte_time = 0;
    
    uint8_t data;
    
    /* 检查是否有数据 */
    if (__HAL_UART_GET_FLAG(rs485->huart, UART_FLAG_RXNE))
    {
        data = (uint8_t)(rs485->huart->Instance->DR & 0xFF);
        last_byte_time = HAL_GetTick();
        
        switch (rx_state)
        {
            case 0:  /* 等待帧头1 */
                if (data == 0xAA)
                {
                    rx_state = 1;
                    rx_buffer[0] = data;
                    rx_index = 1;
                }
                break;
                
            case 1:  /* 等待帧头2 */
                if (data == 0x55)
                {
                    rx_state = 2;
                    rx_buffer[1] = data;
                    rx_index = 2;
                }
                else
                {
                    rx_state = 0;
                }
                break;
                
            case 2:  /* 接收目标地址 */
                rx_buffer[2] = data;
                rx_state = 3;
                rx_index = 3;
                break;
                
            case 3:  /* 接收源地址 */
                rx_buffer[3] = data;
                rx_state = 4;
                rx_index = 4;
                break;
                
            case 4:  /* 接收数据长度 */
                rx_length = data;
                rx_buffer[4] = data;
                rx_state = 5;
                rx_index = 5;
                break;
                
            case 5:  /* 接收数据 */
                rx_buffer[rx_index++] = data;
                if (rx_index >= (rx_length + 5))
                {
                    rx_state = 6;  /* 等待CRC */
                }
                break;
                
            case 6:  /* 接收CRC高字节 */
                rx_buffer[rx_index++] = data;
                rx_state = 7;
                break;
                
            case 7:  /* 接收CRC低字节 */
                rx_buffer[rx_index] = data;
                
                /* 验证CRC */
                uint16_t received_crc = (rx_buffer[rx_index-1] << 8) | data;
                uint16_t calculated_crc = Calculate_CRC16(rx_buffer, rx_index-1);
                
                if (received_crc == calculated_crc)
                {
                    /* 验证目标地址 */
                    if (rx_buffer[2] == rs485->address || rx_buffer[2] == 0xFF)
                    {
                        /* 处理有效帧 */
                        RS485_Frame_Handler(rs485, 
                                           rx_buffer[3],  /* 源地址 */
                                           &rx_buffer[5], /* 数据 */
                                           rx_length);    /* 数据长度 */
                    }
                }
                
                rx_state = 0;
                break;
        }
    }
    
    /* 检查接收超时 */
    if (rx_state != 0 && (HAL_GetTick() - last_byte_time) > 10)
    {
        rx_state = 0;  /* 接收超时,重置状态 */
    }
}

// CRC16计算函数
uint16_t Calculate_CRC16(uint8_t *data, uint16_t length)
{
    uint16_t crc = 0xFFFF;
    
    for (uint16_t i = 0; i < length; i++)
    {
        crc ^= (uint16_t)data[i];
        
        for (uint8_t j = 0; j < 8; j++)
        {
            if (crc & 0x0001)
            {
                crc = (crc >> 1) ^ 0xA001;
            }
            else
            {
                crc = crc >> 1;
            }
        }
    }
    
    return crc;
}

第七章:ADC与DAC高级应用

7.1 ADC多通道扫描与DMA

/**
 * @brief ADC多通道扫描与DMA传输
 */

// ADC初始化结构体
typedef struct
{
    uint32_t ClockPrescaler;        /* 时钟预分频 */
    uint32_t Resolution;            /* 分辨率 */
    uint32_t DataAlign;             /* 数据对齐 */
    uint32_t ScanConvMode;          /* 扫描模式 */
    uint32_t EOCSelection;          /* EOC选择 */
    uint32_t ContinuousConvMode;    /* 连续转换模式 */
    uint32_t DMAContinuousRequests; /* DMA连续请求 */
    uint32_t NbrOfConversion;       /* 转换通道数 */
    uint32_t DiscontinuousConvMode; /* 间断模式 */
    uint32_t NbrOfDiscConversion;   /* 间断转换数 */
    uint32_t ExternalTrigConv;      /* 外部触发 */
    uint32_t ExternalTrigConvEdge;  /* 外部触发边沿 */
} ADC_InitTypeDef;

// ADC多通道扫描配置
void ADC_MultiChannel_Scan_Config(void)
{
    ADC_HandleTypeDef hadc1;
    ADC_ChannelConfTypeDef sConfig = {0};
    
    hadc1.Instance = ADC1;
    hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;      /* ADCCLK = 84MHz/4 = 21MHz */
    hadc1.Init.Resolution = ADC_RESOLUTION_12B;                /* 12位分辨率 */
    hadc1.Init.ScanConvMode = ENABLE;                          /* 启用扫描模式 */
    hadc1.Init.ContinuousConvMode = ENABLE;                    /* 连续转换模式 */
    hadc1.Init.DiscontinuousConvMode = DISABLE;                /* 禁用间断模式 */
    hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;  /* 无外部触发 */
    hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;          /* 软件触发 */
    hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;                /* 右对齐 */
    hadc1.Init.NbrOfConversion = 4;                            /* 4个转换通道 */
    hadc1.Init.DMAContinuousRequests = ENABLE;                 /* 启用DMA连续请求 */
    hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;                /* 序列转换结束产生EOC */
    
    HAL_ADC_Init(&hadc1);
    
    /* 配置通道0:PA0,采样时间56周期 */
    sConfig.Channel = ADC_CHANNEL_0;
    sConfig.Rank = 1;
    sConfig.SamplingTime = ADC_SAMPLETIME_56CYCLES;
    HAL_ADC_ConfigChannel(&hadc1, &sConfig);
    
    /* 配置通道1:PA1,采样时间56周期 */
    sConfig.Channel = ADC_CHANNEL_1;
    sConfig.Rank = 2;
    sConfig.SamplingTime = ADC_SAMPLETIME_56CYCLES;
    HAL_ADC_ConfigChannel(&hadc1, &sConfig);
    
    /* 配置通道2:PA2,采样时间56周期 */
    sConfig.Channel = ADC_CHANNEL_2;
    sConfig.Rank = 3;
    sConfig.SamplingTime = ADC_SAMPLETIME_56CYCLES;
    HAL_ADC_ConfigChannel(&hadc1, &sConfig);
    
    /* 配置通道3:PA3,采样时间56周期 */
    sConfig.Channel = ADC_CHANNEL_3;
    sConfig.Rank = 4;
    sConfig.SamplingTime = ADC_SAMPLETIME_56CYCLES;
    HAL_ADC_ConfigChannel(&hadc1, &sConfig);
}

// ADC DMA配置
void ADC_DMA_Config(void)
{
    static uint16_t adc_values[4];  /* 存储4个通道的ADC值 */
    
    DMA_HandleTypeDef hdma_adc1;
    
    /* DMA配置 */
    hdma_adc1.Instance = DMA2_Stream0;
    hdma_adc1.Init.Channel = DMA_CHANNEL_0;
    hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;
    hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
    hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
    hdma_adc1.Init.Mode = DMA_CIRCULAR;          /* 循环模式 */
    hdma_adc1.Init.Priority = DMA_PRIORITY_HIGH;
    hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    
    HAL_DMA_Init(&hdma_adc1);
    
    /* 关联DMA到ADC */
    __HAL_LINKDMA(&hadc1, DMA_Handle, hdma_adc1);
    
    /* 启动ADC DMA传输 */
    HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_values, 4);
}

// ADC DMA传输完成回调
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
    /* ADC转换完成处理 */
    if (hadc->Instance == ADC1)
    {
        /* 处理ADC数据 */
        Process_ADC_Data(adc_values, 4);
    }
}

// ADC校准与自诊断
void ADC_Calibration_SelfTest(void)
{
    ADC_HandleTypeDef hadc1;
    
    /* 1. ADC上电 */
    __HAL_RCC_ADC1_CLK_ENABLE();
    HAL_Delay(1);
    
    /* 2. 执行校准 */
    if (HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED) != HAL_OK)
    {
        Error_Handler();
    }
    
    /* 3. 自测试:测量内部参考电压 */
    ADC_ChannelConfTypeDef sConfig = {0};
    sConfig.Channel = ADC_CHANNEL_VREFINT;  /* 内部参考电压通道 */
    sConfig.Rank = 1;
    sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
    HAL_ADC_ConfigChannel(&hadc1, &sConfig);
    
    HAL_ADC_Start(&hadc1);
    HAL_ADC_PollForConversion(&hadc1, 100);
    uint32_t vrefint_value = HAL_ADC_GetValue(&hadc1);
    HAL_ADC_Stop(&hadc1);
    
    /* 计算实际电压值 */
    /* VREFINT_CAL是出厂校准值,存储在系统存储器中 */
    uint32_t vrefint_cal = *(__IO uint16_t *)(0x1FFF7A2A);
    float vdda = 3.3 * vrefint_cal / vrefint_value;
    
    /* 验证VDDA是否在合理范围内 */
    if (vdda < 2.7 || vdda > 3.6)
    {
        Error_Handler();
    }
}

7.2 DAC波形生成

/**
 * @brief DAC波形生成与应用
 */

// DAC初始化结构体
typedef struct
{
    uint32_t DAC_Trigger;               /* 触发源 */
    uint32_t DAC_WaveGeneration;        /* 波形生成 */
    uint32_t DAC_LFSRUnmask_TriangleAmplitude; /* LFSR掩码/三角波振幅 */
    uint32_t DAC_OutputBuffer;          /* 输出缓冲 */
} DAC_InitTypeDef;

// DAC波形生成配置
void DAC_Waveform_Generation(void)
{
    DAC_HandleTypeDef hdac;
    DAC_ChannelConfTypeDef sConfig = {0};
    
    hdac.Instance = DAC;
    HAL_DAC_Init(&hdac);
    
    /* 配置DAC通道1 */
    sConfig.DAC_Trigger = DAC_TRIGGER_T6_TRGO;      /* TIM6触发 */
    sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
    
    HAL_DAC_ConfigChannel(&hdac, &sConfig, DAC_CHANNEL_1);
    
    /* 配置三角波生成 */
    HAL_DACEx_TriangleWaveGenerate(&hdac, DAC_CHANNEL_1, 
                                   DAC_TRIANGLEAMPLITUDE_4095);
    
    /* 配置DMA传输 */
    DAC_DMA_Config();
    
    /* 启动DAC */
    HAL_DAC_Start(&hdac, DAC_CHANNEL_1);
}

// DAC DMA传输配置(用于任意波形生成)
void DAC_DMA_Config(void)
{
    static uint16_t waveform_buffer[1024];  /* 波形数据缓冲区 */
    
    /* 生成正弦波数据 */
    for (int i = 0; i < 1024; i++)
    {
        waveform_buffer[i] = 2048 + (int16_t)(2047 * sin(2 * PI * i / 1024));
    }
    
    DMA_HandleTypeDef hdma_dac1;
    
    hdma_dac1.Instance = DMA1_Stream5;
    hdma_dac1.Init.Channel = DMA_CHANNEL_7;
    hdma_dac1.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_dac1.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_dac1.Init.MemInc = DMA_MINC_ENABLE;
    hdma_dac1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
    hdma_dac1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
    hdma_dac1.Init.Mode = DMA_CIRCULAR;
    hdma_dac1.Init.Priority = DMA_PRIORITY_HIGH;
    hdma_dac1.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    
    HAL_DMA_Init(&hdma_dac1);
    
    /* 关联DMA到DAC */
    __HAL_LINKDMA(&hdac, DMA_Handle1, hdma_dac1);
    
    /* 启动DAC DMA传输 */
    HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, 
                     (uint32_t*)waveform_buffer, 1024, DAC_ALIGN_12B_R);
}

// 双DAC同步输出
void Dual_DAC_Sync_Output(void)
{
    DAC_HandleTypeDef hdac;
    
    /* 使能DAC */
    __HAL_RCC_DAC_CLK_ENABLE();
    
    hdac.Instance = DAC;
    HAL_DAC_Init(&hdac);
    
    /* 配置DAC通道1 */
    DAC_ChannelConfTypeDef sConfig = {0};
    sConfig.DAC_Trigger = DAC_TRIGGER_SOFTWARE;
    sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
    HAL_DAC_ConfigChannel(&hdac, &sConfig, DAC_CHANNEL_1);
    
    /* 配置DAC通道2 */
    sConfig.DAC_Trigger = DAC_TRIGGER_SOFTWARE;
    sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
    HAL_DAC_ConfigChannel(&hdac, &sConfig, DAC_CHANNEL_2);
    
    /* 双通道同步输出 */
    uint16_t value1 = 2048;  /* 通道1输出值 */
    uint16_t value2 = 4095;  /* 通道2输出值 */
    
    HAL_DAC_SetValue(&hdac, DAC_CHANNEL_1, DAC_ALIGN_12B_R, value1);
    HAL_DAC_SetValue(&hdac, DAC_CHANNEL_2, DAC_ALIGN_12B_R, value2);
    
    /* 同时启动两个通道 */
    HAL_DAC_Start(&hdac, DAC_CHANNEL_1);
    HAL_DAC_Start(&hdac, DAC_CHANNEL_2);
}

// 音频DAC应用
void Audio_DAC_Application(void)
{
    /* 音频采样率配置:44.1kHz */
    TIM_HandleTypeDef htim6;
    
    htim6.Instance = TIM6;
    htim6.Init.Prescaler = 0;
    htim6.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim6.Init.Period = (84000000 / 44100) - 1;  /* 84MHz / 44.1kHz */
    
    HAL_TIM_Base_Init(&htim6);
    
    /* 配置DAC由TIM6触发 */
    DAC_HandleTypeDef hdac;
    DAC_ChannelConfTypeDef sConfig = {0};
    
    hdac.Instance = DAC;
    HAL_DAC_Init(&hdac);
    
    sConfig.DAC_Trigger = DAC_TRIGGER_T6_TRGO;
    sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
    HAL_DAC_ConfigChannel(&hdac, &sConfig, DAC_CHANNEL_1);
    
    /* 加载音频数据到缓冲区 */
    extern uint16_t audio_data[];
    extern uint32_t audio_data_length;
    
    /* 配置DMA传输音频数据 */
    DMA_HandleTypeDef hdma_dac1;
    /* ... DMA配置 ... */
    
    HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, 
                     (uint32_t*)audio_data, audio_data_length, DAC_ALIGN_12B_R);
    
    /* 启动定时器触发DAC */
    HAL_TIM_Base_Start(&htim6);
}

第八章:I2C与SPI总线通信

8.1 I2C总线通信详解

/**
 * @brief I2C总线通信协议实现
 */

// I2C初始化结构体
typedef struct
{
    uint32_t ClockSpeed;          /* 时钟速度 */
    uint32_t DutyCycle;           /* 占空比 */
    uint32_t OwnAddress1;         /* 自身地址1 */
    uint32_t AddressingMode;      /* 寻址模式 */
    uint32_t DualAddressMode;     /* 双地址模式 */
    uint32_t OwnAddress2;         /* 自身地址2 */
    uint32_t GeneralCallMode;     /* 广播呼叫模式 */
    uint32_t NoStretchMode;       /* 时钟延展模式 */
} I2C_InitTypeDef;

// I2C主机模式配置
void I2C_Master_Config(void)
{
    I2C_HandleTypeDef hi2c1;
    
    hi2c1.Instance = I2C1;
    hi2c1.Init.ClockSpeed = 100000;               /* 100kHz标准模式 */
    hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;       /* 时钟占空比 */
    hi2c1.Init.OwnAddress1 = 0;
    hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;  /* 7位地址 */
    hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
    hi2c1.Init.OwnAddress2 = 0;
    hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
    hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
    
    HAL_I2C_Init(&hi2c1);
}

// I2C从机模式配置
void I2C_Slave_Config(void)
{
    I2C_HandleTypeDef hi2c2;
    
    hi2c2.Instance = I2C2;
    hi2c2.Init.ClockSpeed = 100000;
    hi2c2.Init.DutyCycle = I2C_DUTYCYCLE_2;
    hi2c2.Init.OwnAddress1 = 0x48;                /* 从机地址:0x48 */
    hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
    hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
    hi2c2.Init.OwnAddress2 = 0;
    hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
    hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
    
    HAL_I2C_Init(&hi2c2);
    
    /* 启动从机监听 */
    HAL_I2C_EnableListen_IT(&hi2c2);
}

// I2C中断回调函数
void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, 
                          uint8_t TransferDirection, 
                          uint16_t AddrMatchCode)
{
    if (hi2c->Instance == I2C2)
    {
        /* 地址匹配回调 */
        if (TransferDirection == I2C_DIRECTION_TRANSMIT)
        {
            /* 主机要发送数据给从机 */
            i2c_slave_tx_mode = 1;
        }
        else
        {
            /* 主机要从从机读取数据 */
            i2c_slave_rx_mode = 1;
        }
    }
}

void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c)
{
    /* 从机接收完成 */
    Process_I2C_RxData(i2c_rx_buffer, i2c_rx_len);
    
    /* 重新启动监听 */
    HAL_I2C_EnableListen_IT(hi2c);
}

void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *hi2c)
{
    /* 从机发送完成 */
    
    /* 重新启动监听 */
    HAL_I2C_EnableListen_IT(hi2c);
}

// I2C主机读写操作
void I2C_Read_Register(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, uint16_t size)
{
    /* 先发送寄存器地址,再读取数据 */
    HAL_I2C_Mem_Read(&hi2c1, dev_addr << 1, reg_addr, 
                     I2C_MEMADD_SIZE_8BIT, data, size, 1000);
}

void I2C_Write_Register(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, uint16_t size)
{
    /* 写入寄存器地址和数据 */
    HAL_I2C_Mem_Write(&hi2c1, dev_addr << 1, reg_addr, 
                      I2C_MEMADD_SIZE_8BIT, data, size, 1000);
}

// I2C扫描总线上的设备
void I2C_Bus_Scan(void)
{
    uint8_t devices[128] = {0};
    uint8_t device_count = 0;
    
    printf("Scanning I2C bus...\r\n");
    
    for (uint8_t addr = 1; addr < 127; addr++)
    {
        HAL_StatusTypeDef status;
        
        /* 尝试与设备通信 */
        status = HAL_I2C_IsDeviceReady(&hi2c1, addr << 1, 3, 10);
        
        if (status == HAL_OK)
        {
            devices[device_count++] = addr;
            printf("Device found at address 0x%02X\r\n", addr);
        }
    }
    
    printf("Found %d device(s) on I2C bus\r\n", device_count);
}

// I2C DMA传输
void I2C_DMA_Transfer(void)
{
    uint8_t tx_data[256];
    uint8_t rx_data[256];
    
    /* 准备要发送的数据 */
    for (int i = 0; i < 256; i++)
    {
        tx_data[i] = i;
    }
    
    /* 配置DMA */
    DMA_HandleTypeDef hdma_i2c1_tx;
    DMA_HandleTypeDef hdma_i2c1_rx;
    
    /* I2C TX DMA配置 */
    hdma_i2c1_tx.Instance = DMA1_Stream6;
    hdma_i2c1_tx.Init.Channel = DMA_CHANNEL_1;
    hdma_i2c1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_i2c1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_i2c1_tx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_i2c1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_i2c1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_i2c1_tx.Init.Mode = DMA_NORMAL;
    hdma_i2c1_tx.Init.Priority = DMA_PRIORITY_HIGH;
    hdma_i2c1_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    
    HAL_DMA_Init(&hdma_i2c1_tx);
    __HAL_LINKDMA(&hi2c1, hdmatx, hdma_i2c1_tx);
    
    /* I2C RX DMA配置 */
    hdma_i2c1_rx.Instance = DMA1_Stream0;
    hdma_i2c1_rx.Init.Channel = DMA_CHANNEL_1;
    hdma_i2c1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_i2c1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_i2c1_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_i2c1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_i2c1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_i2c1_rx.Init.Mode = DMA_NORMAL;
    hdma_i2c1_rx.Init.Priority = DMA_PRIORITY_HIGH;
    hdma_i2c1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    
    HAL_DMA_Init(&hdma_i2c1_rx);
    __HAL_LINKDMA(&hi2c1, hdmarx, hdma_i2c1_rx);
    
    /* 使用DMA发送数据 */
    HAL_I2C_Master_Transmit_DMA(&hi2c1, 0x50 << 1, tx_data, 256);
    
    /* 等待发送完成 */
    while (HAL_I2C_GetState(&hi2c1) != HAL_I2C_STATE_READY);
    
    /* 使用DMA接收数据 */
    HAL_I2C_Master_Receive_DMA(&hi2c1, 0x50 << 1, rx_data, 256);
}

8.2 SPI总线通信详解

/**
 * @brief SPI总线通信协议实现
 */

// SPI初始化结构体
typedef struct
{
    uint32_t Mode;                /* 主从模式 */
    uint32_t Direction;           /* 数据传输方向 */
    uint32_t DataSize;            /* 数据大小 */
    uint32_t CLKPolarity;         /* 时钟极性 */
    uint32_t CLKPhase;            /* 时钟相位 */
    uint32_t NSS;                 /* 片选管理 */
    uint32_t BaudRatePrescaler;   /* 波特率预分频 */
    uint32_t FirstBit;            /* 首位传输 */
    uint32_t TIMode;              /* TI模式 */
    uint32_t CRCCalculation;      /* CRC计算 */
    uint32_t CRCPolynomial;       /* CRC多项式 */
} SPI_InitTypeDef;

// SPI主机模式配置
void SPI_Master_Config(void)
{
    SPI_HandleTypeDef hspi1;
    
    hspi1.Instance = SPI1;
    hspi1.Init.Mode = SPI_MODE_MASTER;               /* 主机模式 */
    hspi1.Init.Direction = SPI_DIRECTION_2LINES;     /* 全双工 */
    hspi1.Init.DataSize = SPI_DATASIZE_8BIT;         /* 8位数据 */
    hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;       /* 时钟极性 */
    hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;           /* 时钟相位 */
    hspi1.Init.NSS = SPI_NSS_SOFT;                   /* 软件NSS */
    hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32; /* 84MHz/32 = 2.625MHz */
    hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;          /* 高位在前 */
    hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
    hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
    hspi1.Init.CRCPolynomial = 10;
    
    HAL_SPI_Init(&hspi1);
}

// SPI从机模式配置
void SPI_Slave_Config(void)
{
    SPI_HandleTypeDef hspi2;
    
    hspi2.Instance = SPI2;
    hspi2.Init.Mode = SPI_MODE_SLAVE;                /* 从机模式 */
    hspi2.Init.Direction = SPI_DIRECTION_2LINES;     /* 全双工 */
    hspi2.Init.DataSize = SPI_DATASIZE_8BIT;         /* 8位数据 */
    hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;       /* 时钟极性 */
    hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;           /* 时钟相位 */
    hspi2.Init.NSS = SPI_NSS_HARD_INPUT;             /* 硬件NSS */
    hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;          /* 高位在前 */
    hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
    hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
    hspi2.Init.CRCPolynomial = 10;
    
    HAL_SPI_Init(&hspi2);
}

// SPI软件片选控制
void SPI_CS_Control(GPIO_TypeDef* port, uint16_t pin, uint8_t state)
{
    if (state)
    {
        HAL_GPIO_WritePin(port, pin, GPIO_PIN_RESET);  /* 片选有效 */
        HAL_Delay(1);                                  /* 等待稳定 */
    }
    else
    {
        HAL_GPIO_WritePin(port, pin, GPIO_PIN_SET);    /* 片选无效 */
        HAL_Delay(1);
    }
}

// SPI读写操作
uint8_t SPI_ReadWriteByte(uint8_t tx_data)
{
    uint8_t rx_data;
    
    HAL_SPI_TransmitReceive(&hspi1, &tx_data, &rx_data, 1, 1000);
    
    return rx_data;
}

// SPI读取多个字节
void SPI_ReadBytes(uint8_t *rx_buffer, uint16_t size)
{
    uint8_t tx_dummy = 0xFF;
    
    for (uint16_t i = 0; i < size; i++)
    {
        rx_buffer[i] = SPI_ReadWriteByte(tx_dummy);
    }
}

// SPI写入多个字节
void SPI_WriteBytes(uint8_t *tx_buffer, uint16_t size)
{
    uint8_t rx_dummy;
    
    for (uint16_t i = 0; i < size; i++)
    {
        SPI_ReadWriteByte(tx_buffer[i]);
    }
}

// SPI DMA传输
void SPI_DMA_Transfer(void)
{
    uint8_t tx_buffer[1024];
    uint8_t rx_buffer[1024];
    
    /* 准备数据 */
    for (int i = 0; i < 1024; i++)
    {
        tx_buffer[i] = i & 0xFF;
    }
    
    /* 配置SPI TX DMA */
    DMA_HandleTypeDef hdma_spi1_tx;
    hdma_spi1_tx.Instance = DMA2_Stream3;
    hdma_spi1_tx.Init.Channel = DMA_CHANNEL_3;
    hdma_spi1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_spi1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_spi1_tx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_spi1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_spi1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_spi1_tx.Init.Mode = DMA_NORMAL;
    hdma_spi1_tx.Init.Priority = DMA_PRIORITY_HIGH;
    hdma_spi1_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    
    HAL_DMA_Init(&hdma_spi1_tx);
    __HAL_LINKDMA(&hspi1, hdmatx, hdma_spi1_tx);
    
    /* 配置SPI RX DMA */
    DMA_HandleTypeDef hdma_spi1_rx;
    hdma_spi1_rx.Instance = DMA2_Stream0;
    hdma_spi1_rx.Init.Channel = DMA_CHANNEL_3;
    hdma_spi1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_spi1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_spi1_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_spi1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_spi1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_spi1_rx.Init.Mode = DMA_NORMAL;
    hdma_spi1_rx.Init.Priority = DMA_PRIORITY_HIGH;
    hdma_spi1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    
    HAL_DMA_Init(&hdma_spi1_rx);
    __HAL_LINKDMA(&hspi1, hdmarx, hdma_spi1_rx);
    
    /* 片选有效 */
    SPI_CS_Control(GPIOA, GPIO_PIN_4, 1);
    
    /* 启动DMA传输 */
    HAL_SPI_TransmitReceive_DMA(&hspi1, tx_buffer, rx_buffer, 1024);
    
    /* 等待传输完成 */
    while (HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY);
    
    /* 片选无效 */
    SPI_CS_Control(GPIOA, GPIO_PIN_4, 0);
}

// SPI中断方式传输
void SPI_Interrupt_Transfer(void)
{
    uint8_t tx_data = 0xAA;
    uint8_t rx_data;
    
    /* 启动中断方式传输 */
    HAL_SPI_TransmitReceive_IT(&hspi1, &tx_data, &rx_data, 1);
}

// SPI传输完成回调
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
{
    if (hspi->Instance == SPI1)
    {
        /* 传输完成处理 */
        spi_transfer_complete_handler();
    }
}

// SPI错误回调
void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi)
{
    uint32_t error_code = hspi->ErrorCode;
    
    if (error_code & HAL_SPI_ERROR_MODF)
    {
        /* 模式错误 */
        spi_mode_error_handler();
    }
    
    if (error_code & HAL_SPI_ERROR_CRC)
    {
        /* CRC错误 */
        spi_crc_error_handler();
    }
    
    if (error_code & HAL_SPI_ERROR_OVR)
    {
        /* 溢出错误 */
        spi_overrun_error_handler();
    }
    
    if (error_code & HAL_SPI_ERROR_FRE)
    {
        /* 帧错误 */
        spi_frame_error_handler();
    }
    
    if (error_code & HAL_SPI_ERROR_DMA)
    {
        /* DMA错误 */
        spi_dma_error_handler();
    }
    
    /* 重新初始化SPI */
    HAL_SPI_DeInit(hspi);
    HAL_SPI_Init(hspi);
}

第九章:DMA高级应用

9.1 DMA内存到内存传输

/**
 * @brief DMA高级应用:内存到内存传输
 */

// DMA初始化结构体
typedef struct
{
    uint32_t Channel;              /* 通道选择 */
    uint32_t Direction;            /* 传输方向 */
    uint32_t PeriphInc;            /* 外设地址递增 */
    uint32_t MemoryInc;            /* 内存地址递增 */
    uint32_t PeriphDataAlignment;  /* 外设数据对齐 */
    uint32_t MemDataAlignment;     /* 内存数据对齐 */
    uint32_t Mode;                 /* 模式(普通/循环) */
    uint32_t Priority;             /* 优先级 */
    uint32_t FIFOMode;             /* FIFO模式 */
    uint32_t FIFOThreshold;        /* FIFO阈值 */
    uint32_t MemBurst;             /* 内存突发传输 */
    uint32_t PeriphBurst;          /* 外设突发传输 */
} DMA_InitTypeDef;

// 内存到内存DMA传输
void DMA_MemoryToMemory_Transfer(void)
{
    uint32_t src_buffer[1024];
    uint32_t dst_buffer[1024];
    
    /* 初始化源缓冲区 */
    for (int i = 0; i < 1024; i++)
    {
        src_buffer[i] = i;
    }
    
    DMA_HandleTypeDef hdma_mem;
    
    hdma_mem.Instance = DMA2_Stream0;
    hdma_mem.Init.Channel = DMA_CHANNEL_0;
    hdma_mem.Init.Direction = DMA_MEMORY_TO_MEMORY;      /* 内存到内存 */
    hdma_mem.Init.PeriphInc = DMA_PINC_ENABLE;           /* 源地址递增 */
    hdma_mem.Init.MemInc = DMA_MINC_ENABLE;              /* 目标地址递增 */
    hdma_mem.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;  /* 字对齐 */
    hdma_mem.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;     /* 字对齐 */
    hdma_mem.Init.Mode = DMA_NORMAL;                     /* 普通模式 */
    hdma_mem.Init.Priority = DMA_PRIORITY_HIGH;          /* 高优先级 */
    hdma_mem.Init.FIFOMode = DMA_FIFOMODE_ENABLE;        /* 启用FIFO */
    hdma_mem.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
    
    HAL_DMA_Init(&hdma_mem);
    
    /* 启动DMA传输 */
    HAL_DMA_Start(&hdma_mem, (uint32_t)src_buffer, (uint32_t)dst_buffer, 1024);
    
    /* 等待传输完成 */
    HAL_DMA_PollForTransfer(&hdma_mem, HAL_DMA_FULL_TRANSFER, 1000);
    
    /* 验证传输结果 */
    for (int i = 0; i < 1024; i++)
    {
        if (dst_buffer[i] != src_buffer[i])
        {
            Error_Handler();
        }
    }
}

// 双缓冲区DMA传输
void DMA_DoubleBuffer_Transfer(void)
{
    static uint32_t buffer1[256];
    static uint32_t buffer2[256];
    static uint32_t *current_buffer = buffer1;
    
    DMA_HandleTypeDef hdma_double;
    
    hdma_double.Instance = DMA2_Stream1;
    hdma_double.Init.Channel = DMA_CHANNEL_1;
    hdma_double.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_double.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_double.Init.MemInc = DMA_MINC_ENABLE;
    hdma_double.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
    hdma_double.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
    hdma_double.Init.Mode = DMA_CIRCULAR;                /* 循环模式 */
    hdma_double.Init.Priority = DMA_PRIORITY_HIGH;
    hdma_double.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
    hdma_double.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL;
    
    HAL_DMA_Init(&hdma_double);
    
    /* 配置双缓冲区 */
    HAL_DMAEx_MultiBufferStart_IT(&hdma_double, 
                                  (uint32_t)buffer1, 
                                  (uint32_t)&(SOME_PERIPHERAL->DR), 
                                  (uint32_t)buffer2, 
                                  256);
    
    /* 启用双缓冲区中断 */
    HAL_DMAEx_MultiBufferStart_IT(&hdma_double, 
                                  (uint32_t)buffer1, 
                                  (uint32_t)&(SOME_PERIPHERAL->DR), 
                                  (uint32_t)buffer2, 
                                  256);
}

// DMA传输完成回调
void HAL_DMA_XferCpltCallback(DMA_HandleTypeDef *hdma)
{
    if (hdma->Instance == DMA2_Stream1)
    {
        /* 传输完成,切换缓冲区 */
        if (current_buffer == buffer1)
        {
            current_buffer = buffer2;
            /* 处理buffer1中的数据 */
            Process_Buffer(buffer1, 256);
        }
        else
        {
            current_buffer = buffer1;
            /* 处理buffer2中的数据 */
            Process_Buffer(buffer2, 256);
        }
    }
}

// DMA半传输完成回调
void HAL_DMA_XferHalfCpltCallback(DMA_HandleTypeDef *hdma)
{
    if (hdma->Instance == DMA2_Stream1)
    {
        /* 半传输完成 */
        if (current_buffer == buffer1)
        {
            /* 处理buffer1的前半部分 */
            Process_Buffer(buffer1, 128);
        }
        else
        {
            /* 处理buffer2的前半部分 */
            Process_Buffer(buffer2, 128);
        }
    }
}

// DMA错误处理
void HAL_DMA_ErrorCallback(DMA_HandleTypeDef *hdma)
{
    uint32_t error_code = hdma->ErrorCode;
    
    if (error_code & HAL_DMA_ERROR_TE)
    {
        /* 传输错误 */
        dma_transfer_error_handler();
    }
    
    if (error_code & HAL_DMA_ERROR_FE)
    {
        /* FIFO错误 */
        dma_fifo_error_handler();
    }
    
    if (error_code & HAL_DMA_ERROR_DME)
    {
        /* 直接模式错误 */
        dma_direct_mode_error_handler();
    }
    
    if (error_code & HAL_DMA_ERROR_TIMEOUT)
    {
        /* 超时错误 */
        dma_timeout_error_handler();
    }
    
    /* 重新初始化DMA */
    HAL_DMA_DeInit(hdma);
    HAL_DMA_Init(hdma);
}

9.2 DMA链表传输

/**
 * @brief DMA链表传输(仅限STM32H7等高级系列)
 */

#if defined(STM32H7xx)
// DMA链表节点结构
typedef struct
{
    uint32_t SrcAddress;      /* 源地址 */
    uint32_t DstAddress;      /* 目标地址 */
    uint32_t DataLength;      /* 数据长度 */
    uint32_t LinkedListNode;  /* 下一个节点地址 */
    uint32_t ControlRegister; /* 控制寄存器 */
} DMA_NodeTypeDef;

// DMA链表传输配置
void DMA_LinkedList_Transfer(void)
{
    /* 定义三个DMA节点 */
    DMA_NodeTypeDef node1 __attribute__((aligned(32)));
    DMA_NodeTypeDef node2 __attribute__((aligned(32)));
    DMA_NodeTypeDef node3 __attribute__((aligned(32)));
    
    uint32_t src_data1[256];
    uint32_t src_data2[256];
    uint32_t src_data3[256];
    uint32_t dst_data1[256];
    uint32_t dst_data2[256];
    uint32_t dst_data3[256];
    
    /* 初始化数据 */
    for (int i = 0; i < 256; i++)
    {
        src_data1[i] = i;
        src_data2[i] = i + 256;
        src_data3[i] = i + 512;
    }
    
    /* 配置节点1 */
    node1.SrcAddress = (uint32_t)src_data1;
    node1.DstAddress = (uint32_t)dst_data1;
    node1.DataLength = 256;
    node1.LinkedListNode = (uint32_t)&node2;  /* 指向节点2 */
    node1.ControlRegister = 
        (DMA_SxCR_CHSEL_0 |    /* 通道选择 */
         DMA_SxCR_DIR_0 |      /* 内存到内存 */
         DMA_SxCR_MINC |       /* 内存递增 */
         DMA_SxCR_PINC |       /* 外设递增 */
         DMA_SxCR_TCIE |       /* 传输完成中断 */
         DMA_SxCR_HTIE |       /* 半传输中断 */
         (DMA_SxCR_PSIZE_1 | DMA_SxCR_PSIZE_0) |  /* 外设字大小 */
         (DMA_SxCR_MSIZE_1 | DMA_SxCR_MSIZE_0) |  /* 内存字大小 */
         DMA_SxCR_PL_0);       /* 中等优先级 */
    
    /* 配置节点2 */
    node2.SrcAddress = (uint32_t)src_data2;
    node2.DstAddress = (uint32_t)dst_data2;
    node2.DataLength = 256;
    node2.LinkedListNode = (uint32_t)&node3;  /* 指向节点3 */
    node2.ControlRegister = node1.ControlRegister;
    
    /* 配置节点3 */
    node3.SrcAddress = (uint32_t)src_data3;
    node3.DstAddress = (uint32_t)dst_data3;
    node3.DataLength = 256;
    node3.LinkedListNode = 0;  /* 链表结束 */
    node3.ControlRegister = node1.ControlRegister;
    
    DMA_HandleTypeDef hdma_link;
    
    hdma_link.Instance = DMA1_Stream0;
    hdma_link.Init.Request = DMA_REQUEST_MEM2MEM;
    hdma_link.Init.Direction = DMA_MEMORY_TO_MEMORY;
    hdma_link.Init.PeriphInc = DMA_PINC_ENABLE;
    hdma_link.Init.MemInc = DMA_MINC_ENABLE;
    hdma_link.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
    hdma_link.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
    hdma_link.Init.Mode = DMA_NORMAL;
    hdma_link.Init.Priority = DMA_PRIORITY_MEDIUM;
    
    HAL_DMA_Init(&hdma_link);
    
    /* 配置链表模式 */
    HAL_DMAEx_List_Init(&hdma_link);
    
    /* 创建链表 */
    HAL_DMAEx_List_BuildNode(&hdma_link, &node1);
    HAL_DMAEx_List_BuildNode(&hdma_link, &node2);
    HAL_DMAEx_List_BuildNode(&hdma_link, &node3);
    
    /* 链接节点 */
    HAL_DMAEx_List_LinkQ(&hdma_link, &node1, &node2);
    HAL_DMAEx_List_LinkQ(&hdma_link, &node2, &node3);
    
    /* 设置链表头 */
    HAL_DMAEx_List_SetNode(&hdma_link, &node1);
    
    /* 启动链表传输 */
    HAL_DMAEx_List_Start_IT(&hdma_link);
}
#endif

// DMA与缓存一致性处理(Cortex-M7)
void DMA_Cache_Coherence(void)
{
#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
    uint32_t dma_buffer[256] __attribute__((aligned(32)));
    
    /* 准备DMA缓冲区数据 */
    for (int i = 0; i < 256; i++)
    {
        dma_buffer[i] = i;
    }
    
    /* 1. 清理缓存(Cache Clean):将缓存中的数据写回内存 */
    /* 在DMA读取之前,确保内存中的数据是最新的 */
    SCB_CleanDCache_by_Addr((uint32_t*)dma_buffer, sizeof(dma_buffer));
    
    /* 2. 执行DMA传输(从内存到外设) */
    HAL_DMA_Start(&hdma, (uint32_t)dma_buffer, (uint32_t)&SOME_PERIPHERAL->DR, 256);
    
    /* 3. 等待DMA传输完成 */
    HAL_DMA_PollForTransfer(&hdma, HAL_DMA_FULL_TRANSFER, 1000);
    
    /* 4. 无效化缓存(Cache Invalidate):丢弃缓存中的旧数据 */
    /* 在CPU读取DMA写入的数据之前,确保缓存无效 */
    SCB_InvalidateDCache_by_Addr((uint32_t*)dma_buffer, sizeof(dma_buffer));
    
    /* 5. 现在CPU可以安全地读取DMA写入的数据 */
#endif
}

第十章:低功耗与电源管理

10.1 STM32低功耗模式

/**
 * @brief STM32低功耗模式配置
 */

// 低功耗模式枚举
typedef enum
{
    PWR_RUN_MODE = 0,           /* 运行模式 */
    PWR_SLEEP_MODE,             /* 睡眠模式 */
    PWR_STOP_MODE,              /* 停止模式 */
    PWR_STANDBY_MODE,           /* 待机模式 */
    PWR_SHUTDOWN_MODE           /* 关机模式(某些系列支持) */
} PWR_ModeTypeDef;

// 睡眠模式进入与退出
void Enter_Sleep_Mode(void)
{
    /* 配置唤醒源(可选) */
    // 可以配置EXTI、RTC等作为唤醒源
    
    /* 设置休眠深度 */
    __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);  /* 清除唤醒标志 */
    
    /* 进入睡眠模式 */
    HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
    
    /* 唤醒后继续执行 */
    SystemClock_Config();  /* 可能需要重新配置时钟 */
}

// 停止模式进入与退出
void Enter_Stop_Mode(void)
{
    /* 配置唤醒源 */
    /* 1. 配置RTC闹钟唤醒 */
    RTC_AlarmTypeDef sAlarm = {0};
    sAlarm.AlarmTime.Hours = 0;
    sAlarm.AlarmTime.Minutes = 1;
    sAlarm.AlarmTime.Seconds = 0;
    sAlarm.Alarm = RTC_ALARM_A;
    HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BIN);
    
    /* 2. 配置EXTI唤醒 */
    __HAL_RCC_PWR_CLK_ENABLE();
    __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
    
    /* 配置PA0为唤醒引脚 */
    HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1);
    
    /* 进入停止模式 */
    HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
    
    /* 唤醒后 */
    SystemClock_Config();  /* 必须重新配置系统时钟 */
    
    /* 重新初始化外设 */
    MX_GPIO_Init();
    MX_USART1_UART_Init();
    // ... 其他外设重新初始化
}

// 待机模式进入与退出
void Enter_Standby_Mode(void)
{
    /* 配置唤醒源 */
    /* 1. RTC唤醒 */
    RTC_AlarmTypeDef sAlarm = {0};
    sAlarm.AlarmTime.Hours = 0;
    sAlarm.AlarmTime.Minutes = 10;  /* 10分钟后唤醒 */
    sAlarm.AlarmTime.Seconds = 0;
    sAlarm.Alarm = RTC_ALARM_A;
    HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BIN);
    
    /* 2. WKUP引脚唤醒 */
    HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1);
    
    /* 3. 独立看门狗唤醒(如果使能) */
    
    /* 清除所有唤醒标志 */
    __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
    __HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB);
    
    /* 进入待机模式 */
    HAL_PWR_EnterSTANDBYMode();
    
    /* 待机模式唤醒后,MCU会复位,从main函数开始执行 */
}

// 低功耗模式下的RTC配置
void RTC_LowPower_Config(void)
{
    RTC_HandleTypeDef hrtc;
    
    hrtc.Instance = RTC;
    hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
    hrtc.Init.AsynchPrediv = 127;
    hrtc.Init.SynchPrediv = 255;
    hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
    hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
    hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
    
    HAL_RTC_Init(&hrtc);
    
    /* 配置RTC闹钟 */
    RTC_AlarmTypeDef sAlarm = {0};
    sAlarm.AlarmTime.Hours = 0;
    sAlarm.AlarmTime.Minutes = 0;
    sAlarm.AlarmTime.Seconds = 30;  /* 30秒后唤醒 */
    sAlarm.AlarmMask = RTC_ALARMMASK_NONE;
    sAlarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_ALL;
    sAlarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE;
    sAlarm.AlarmDateWeekDay = 1;
    sAlarm.Alarm = RTC_ALARM_A;
    
    HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BIN);
}

// 低功耗模式下的GPIO配置
void GPIO_LowPower_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    
    /* 将所有未使用的GPIO配置为模拟输入以降低功耗 */
    GPIO_InitStruct.Pin = GPIO_PIN_All;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
    // ... 其他GPIO端口
    
    /* 配置使用的GPIO为适当的状态 */
    /* 输出引脚:推挽输出,低电平 */
    GPIO_InitStruct.Pin = GPIO_PIN_13;  /* LED引脚 */
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);
    
    /* 输入引脚:无上拉下拉 */
    GPIO_InitStruct.Pin = GPIO_PIN_0;  /* 按键引脚 */
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}

// 动态电压调节(某些系列支持)
void Dynamic_Voltage_Scaling(void)
{
#if defined(PWR_REGULATOR_VOLTAGE_SCALE1) && defined(PWR_REGULATOR_VOLTAGE_SCALE2)
    /* 切换到高电压范围(高性能) */
    __HAL_RCC_PWR_CLK_ENABLE();
    __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
    
    /* 提高系统时钟 */
    SystemClock_Config_HighPerformance();
    
    /* 执行高性能任务 */
    Perform_HighPerformance_Task();
    
    /* 切换到低电压范围(低功耗) */
    __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);
    
    /* 降低系统时钟 */
    SystemClock_Config_LowPower();
    
    /* 进入低功耗模式或执行低功耗任务 */
    Enter_Sleep_Mode();
#endif
}

10.2 低功耗外设管理

/**
 * @brief 低功耗外设管理策略
 */

// 外设时钟管理系统
typedef struct
{
    uint32_t peripheral;     /* 外设标识 */
    uint8_t is_enabled;      /* 是否使能 */
    uint32_t enable_time;    /* 使能时间戳 */
    uint32_t timeout;        /* 超时时间(ms) */
} Peripheral_Manager_t;

// 外设管理表
Peripheral_Manager_t peripheral_table[] = {
    {PERIPH_USART1, 0, 0, 100},     /* USART1,100ms超时 */
    {PERIPH_SPI1, 0, 0, 50},        /* SPI1,50ms超时 */
    {PERIPH_I2C1, 0, 0, 200},       /* I2C1,200ms超时 */
    {PERIPH_ADC1, 0, 0, 10},        /* ADC1,10ms超时 */
    {PERIPH_TIM2, 0, 0, 0},         /* TIM2,无超时(常开) */
};

// 使能外设
void Enable_Peripheral(uint32_t peripheral)
{
    for (int i = 0; i < sizeof(peripheral_table)/sizeof(peripheral_table[0]); i++)
    {
        if (peripheral_table[i].peripheral == peripheral)
        {
            peripheral_table[i].is_enabled = 1;
            peripheral_table[i].enable_time = HAL_GetTick();
            
            /* 实际使能外设时钟 */
            switch (peripheral)
            {
                case PERIPH_USART1:
                    __HAL_RCC_USART1_CLK_ENABLE();
                    break;
                case PERIPH_SPI1:
                    __HAL_RCC_SPI1_CLK_ENABLE();
                    break;
                case PERIPH_I2C1:
                    __HAL_RCC_I2C1_CLK_ENABLE();
                    break;
                case PERIPH_ADC1:
                    __HAL_RCC_ADC1_CLK_ENABLE();
                    break;
                case PERIPH_TIM2:
                    __HAL_RCC_TIM2_CLK_ENABLE();
                    break;
            }
            break;
        }
    }
}

// 禁用外设
void Disable_Peripheral(uint32_t peripheral)
{
    for (int i = 0; i < sizeof(peripheral_table)/sizeof(peripheral_table[0]); i++)
    {
        if (peripheral_table[i].peripheral == peripheral)
        {
            peripheral_table[i].is_enabled = 0;
            
            /* 实际禁用外设时钟 */
            switch (peripheral)
            {
                case PERIPH_USART1:
                    __HAL_RCC_USART1_CLK_DISABLE();
                    break;
                case PERIPH_SPI1:
                    __HAL_RCC_SPI1_CLK_DISABLE();
                    break;
                case PERIPH_I2C1:
                    __HAL_RCC_I2C1_CLK_DISABLE();
                    break;
                case PERIPH_ADC1:
                    __HAL_RCC_ADC1_CLK_DISABLE();
                    break;
                case PERIPH_TIM2:
                    /* TIM2可能用于系统时钟,不关闭 */
                    break;
            }
            break;
        }
    }
}

// 外设超时检查任务(在systick中断或定时器中调用)
void Peripheral_Timeout_Check(void)
{
    uint32_t current_time = HAL_GetTick();
    
    for (int i = 0; i < sizeof(peripheral_table)/sizeof(peripheral_table[0]); i++)
    {
        if (peripheral_table[i].is_enabled && 
            peripheral_table[i].timeout > 0)
        {
            if ((current_time - peripheral_table[i].enable_time) > 
                peripheral_table[i].timeout)
            {
                /* 外设超时,自动禁用 */
                Disable_Peripheral(peripheral_table[i].peripheral);
            }
        }
    }
}

// 低功耗ADC采样策略
void LowPower_ADC_Sampling(void)
{
    ADC_HandleTypeDef hadc1;
    
    /* 配置ADC为单次转换模式 */
    hadc1.Init.ContinuousConvMode = DISABLE;      /* 单次转换 */
    hadc1.Init.DiscontinuousConvMode = DISABLE;
    hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
    
    HAL_ADC_Init(&hadc1);
    
    while (1)
    {
        /* 使能ADC时钟 */
        __HAL_RCC_ADC1_CLK_ENABLE();
        
        /* 执行ADC转换 */
        HAL_ADC_Start(&hadc1);
        HAL_ADC_PollForConversion(&hadc1, 10);
        uint32_t adc_value = HAL_ADC_GetValue(&hadc1);
        HAL_ADC_Stop(&hadc1);
        
        /* 禁用ADC时钟以省电 */
        __HAL_RCC_ADC1_CLK_DISABLE();
        
        /* 处理ADC值 */
        Process_ADC_Value(adc_value);
        
        /* 进入睡眠模式等待下一次采样 */
        HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
    }
}

// 低功耗定时唤醒
void LowPower_Timed_Wakeup(void)
{
    /* 配置低功耗定时器(LPTIM) */
    LPTIM_HandleTypeDef hlptim1;
    
    hlptim1.Instance = LPTIM1;
    hlptim1.Init.Clock.Source = LPTIM_CLOCKSOURCE_APBCLOCK_LPOSC;
    hlptim1.Init.Clock.Prescaler = LPTIM_PRESCALER_DIV128;
    hlptim1.Init.Trigger.Source = LPTIM_TRIGSOURCE_SOFTWARE;
    hlptim1.Init.OutputPolarity = LPTIM_OUTPUTPOLARITY_HIGH;
    hlptim1.Init.UpdateMode = LPTIM_UPDATE_IMMEDIATE;
    hlptim1.Init.CounterSource = LPTIM_COUNTERSOURCE_INTERNAL;
    
    HAL_LPTIM_Init(&hlptim1);
    
    /* 设置定时器周期(1秒) */
    /* LSI = 32kHz, 分频128 = 250Hz, 计数值250 = 1秒 */
    HAL_LPTIM_SetOnce_Start_IT(&hlptim1, 250);
    
    /* 进入停止模式 */
    HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
    
    /* LPTIM中断唤醒后继续执行 */
    SystemClock_Config();
    
    /* 执行唤醒后的任务 */
    Execute_Wakeup_Task();
    
    /* 重新配置LPTIM并再次进入低功耗 */
    HAL_LPTIM_SetOnce_Start_IT(&hlptim1, 250);
}

// LPTIM唤醒回调
void HAL_LPTIM_CompareMatchCallback(LPTIM_HandleTypeDef *hlptim)
{
    /* 比较匹配中断,用于唤醒MCU */
    if (hlptim->Instance == LPTIM1)
    {
        /* 清除标志位 */
        __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_CMPM);
    }
}

第十一章:HAL库调试与优化

11.1 HAL库调试技巧

/**
 * @brief HAL库调试与故障诊断
 */

// 错误处理钩子函数
void Error_Handler(void)
{
    /* 获取错误信息 */
    uint32_t hal_error = HAL_GetError();
    uint32_t system_clock = HAL_RCC_GetSysClockFreq();
    uint32_t hclk_clock = HAL_RCC_GetHCLKFreq();
    uint32_t pclk1_clock = HAL_RCC_GetPCLK1Freq();
    uint32_t pclk2_clock = HAL_RCC_GetPCLK2Freq();
    
    /* 记录错误信息(可通过串口输出或保存到Flash) */
    printf("HAL Error: 0x%08lX\r\n", hal_error);
    printf("System Clock: %lu Hz\r\n", system_clock);
    printf("HCLK: %lu Hz\r\n", hclk_clock);
    printf("PCLK1: %lu Hz\r\n", pclk1_clock);
    printf("PCLK2: %lu Hz\r\n", pclk2_clock);
    
    /* 获取栈使用情况 */
    Check_Stack_Usage();
    
    /* 获取堆使用情况 */
    Check_Heap_Usage();
    
    /* 闪烁LED指示错误 */
    while (1)
    {
        HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
        HAL_Delay(100);
    }
}

// 栈使用情况检查
void Check_Stack_Usage(void)
{
    extern uint32_t _estack;     /* 栈结束地址(链接脚本定义) */
    extern uint32_t _Min_Stack_Size;  /* 最小栈大小 */
    
    uint32_t *stack_start = (uint32_t*)&_estack - (_Min_Stack_Size / 4);
    uint32_t stack_used = 0;
    
    /* 计算已使用的栈空间 */
    for (uint32_t i = 0; i < _Min_Stack_Size / 4; i++)
    {
        if (stack_start[i] != 0xAAAAAAAA)  /* 栈初始化值 */
        {
            stack_used = (_Min_Stack_Size / 4 - i) * 4;
            break;
        }
    }
    
    printf("Stack Usage: %lu/%lu bytes\r\n", 
           stack_used, _Min_Stack_Size);
}

// 堆使用情况检查
void Check_Heap_Usage(void)
{
    extern uint32_t _end;        /* 堆开始地址 */
    extern uint32_t _Heap_Limit; /* 堆结束地址 */
    extern __IO uint32_t __brkval;  /* 当前堆指针 */
    
    uint32_t heap_size = (uint32_t)&_Heap_Limit - (uint32_t)&_end;
    uint32_t heap_used = (uint32_t)__brkval - (uint32_t)&_end;
    
    printf("Heap Usage: %lu/%lu bytes\r\n", heap_used, heap_size);
}

// HAL库超时调试
#define DEBUG_TIMEOUT 1

#if DEBUG_TIMEOUT
uint32_t timeout_debug_counter = 0;
uint32_t timeout_debug_threshold = 1000;

// 超时调试宏
#define HAL_TIMEOUT_DEBUG(__HANDLE__, __TIMEOUT__) \
    do { \
        timeout_debug_counter++; \
        if (timeout_debug_counter > timeout_debug_threshold) { \
            printf("Timeout in %s at line %d\r\n", __FILE__, __LINE__); \
            printf("Handle: 0x%08lX, Timeout: %lu\r\n", \
                   (uint32_t)__HANDLE__, __TIMEOUT__); \
            timeout_debug_counter = 0; \
        } \
    } while(0)

#else
#define HAL_TIMEOUT_DEBUG(__HANDLE__, __TIMEOUT__)
#endif

// 带调试信息的HAL函数包装
HAL_StatusTypeDef HAL_UART_Transmit_Debug(UART_HandleTypeDef *huart, 
                                          uint8_t *pData, 
                                          uint16_t Size, 
                                          uint32_t Timeout)
{
    HAL_TIMEOUT_DEBUG(huart, Timeout);
    
    HAL_StatusTypeDef status = HAL_UART_Transmit(huart, pData, Size, Timeout);
    
    if (status != HAL_OK)
    {
        printf("UART Transmit failed: %d\r\n", status);
        printf("UART State: %d, Error Code: 0x%08lX\r\n", 
               huart->gState, huart->ErrorCode);
    }
    
    return status;
}

// 外设状态监控
typedef struct
{
    uint32_t peripheral;
    uint32_t state;
    uint32_t error_count;
    uint32_t last_error;
    uint32_t operation_count;
} Peripheral_Monitor_t;

Peripheral_Monitor_t peripheral_monitors[] = {
    {PERIPH_UART1, 0, 0, 0, 0},
    {PERIPH_SPI1, 0, 0, 0, 0},
    {PERIPH_I2C1, 0, 0, 0, 0},
    {PERIPH_ADC1, 0, 0, 0, 0},
};

void Monitor_Peripheral_State(uint32_t peripheral, uint32_t state)
{
    for (int i = 0; i < sizeof(peripheral_monitors)/sizeof(peripheral_monitors[0]); i++)
    {
        if (peripheral_monitors[i].peripheral == peripheral)
        {
            peripheral_monitors[i].state = state;
            peripheral_monitors[i].operation_count++;
            
            if (state == PERIPH_STATE_ERROR)
            {
                peripheral_monitors[i].error_count++;
                peripheral_monitors[i].last_error = HAL_GetTick();
            }
            break;
        }
    }
}

// 打印外设状态信息
void Print_Peripheral_Status(void)
{
    printf("=== Peripheral Status ===\r\n");
    
    for (int i = 0; i < sizeof(peripheral_monitors)/sizeof(peripheral_monitors[0]); i++)
    {
        printf("Peripheral %lu: State=%lu, Errors=%lu, Ops=%lu\r\n",
               peripheral_monitors[i].peripheral,
               peripheral_monitors[i].state,
               peripheral_monitors[i].error_count,
               peripheral_monitors[i].operation_count);
    }
}

// 断言宏(用于调试)
#ifdef DEBUG
#define HAL_ASSERT(expr) \
    do { \
        if (!(expr)) { \
            printf("Assertion failed: %s, file %s, line %d\r\n", \
                   #expr, __FILE__, __LINE__); \
            Error_Handler(); \
        } \
    } while(0)
#else
#define HAL_ASSERT(expr) ((void)0)
#endif

// 在HAL库函数中使用断言
HAL_StatusTypeDef Safe_HAL_UART_Transmit(UART_HandleTypeDef *huart, 
                                         uint8_t *pData, 
                                         uint16_t Size, 
                                         uint32_t Timeout)
{
    HAL_ASSERT(huart != NULL);
    HAL_ASSERT(pData != NULL);
    HAL_ASSERT(Size > 0);
    HAL_ASSERT(huart->Instance != NULL);
    
    return HAL_UART_Transmit(huart, pData, Size, Timeout);
}

11.2 HAL库性能优化

/**
 * @brief HAL库性能优化技巧
 */

// 1. 使用直接寄存器操作优化关键路径
void Optimized_GPIO_Toggle(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
    /* 使用BSRR寄存器原子操作 */
    GPIOx->BSRR = GPIO_Pin;           /* 设置引脚 */
    GPIOx->BSRR = (uint32_t)GPIO_Pin << 16;  /* 复位引脚 */
}

// 2. 避免频繁的HAL_Delay调用
// 使用系统滴答计时器实现非阻塞延迟
typedef struct
{
    uint32_t start_time;
    uint32_t delay_ms;
    uint8_t is_running;
} NonBlocking_Delay_t;

void NonBlocking_Delay_Start(NonBlocking_Delay_t *delay, uint32_t ms)
{
    delay->start_time = HAL_GetTick();
    delay->delay_ms = ms;
    delay->is_running = 1;
}

uint8_t NonBlocking_Delay_IsElapsed(NonBlocking_Delay_t *delay)
{
    if (!delay->is_running)
        return 1;
    
    if ((HAL_GetTick() - delay->start_time) >= delay->delay_ms)
    {
        delay->is_running = 0;
        return 1;
    }
    
    return 0;
}

// 3. 优化中断处理
// 使用DMA减少中断频率
void Optimized_UART_Receive(void)
{
    static uint8_t rx_buffer[256];
    static uint8_t rx_index = 0;
    
    /* 使用DMA接收数据,减少中断次数 */
    HAL_UART_Receive_DMA(&huart1, rx_buffer, sizeof(rx_buffer));
    
    /* 在DMA传输完成中断中处理数据 */
}

// 4. 内存池管理(避免频繁malloc/free)
#define MEMORY_POOL_SIZE 1024
#define MEMORY_BLOCK_SIZE 32
#define NUM_BLOCKS (MEMORY_POOL_SIZE / MEMORY_BLOCK_SIZE)

typedef struct
{
    uint8_t pool[MEMORY_POOL_SIZE];
    uint8_t block_map[NUM_BLOCKS];  /* 0=空闲, 1=已分配 */
} Memory_Pool_t;

void* Memory_Pool_Alloc(Memory_Pool_t *pool, uint32_t size)
{
    if (size > MEMORY_BLOCK_SIZE)
        return NULL;
    
    for (int i = 0; i < NUM_BLOCKS; i++)
    {
        if (pool->block_map[i] == 0)
        {
            pool->block_map[i] = 1;
            return &pool->pool[i * MEMORY_BLOCK_SIZE];
        }
    }
    
    return NULL;
}

void Memory_Pool_Free(Memory_Pool_t *pool, void *ptr)
{
    uint32_t index = ((uint8_t*)ptr - pool->pool) / MEMORY_BLOCK_SIZE;
    
    if (index < NUM_BLOCKS)
    {
        pool->block_map[index] = 0;
    }
}

// 5. 缓存对齐优化
// 使用C11对齐特性
typedef struct __attribute__((aligned(32)))
{
    uint32_t data[256];
    uint32_t counter;
} Cache_Aligned_Buffer_t;

// 6. 使用内联函数减少函数调用开销
static inline void Fast_GPIO_Set(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
    GPIOx->BSRR = GPIO_Pin;
}

static inline void Fast_GPIO_Reset(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
    GPIOx->BSRR = (uint32_t)GPIO_Pin << 16;
}

static inline uint8_t Fast_GPIO_Read(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
    return ((GPIOx->IDR & GPIO_Pin) != 0);
}

// 7. 循环展开优化
void Optimized_Memory_Copy(uint8_t *dst, uint8_t *src, uint32_t size)
{
    uint32_t *dst32 = (uint32_t*)dst;
    uint32_t *src32 = (uint32_t*)src;
    
    /* 4字节对齐拷贝 */
    uint32_t word_count = size / 4;
    
    for (uint32_t i = 0; i < word_count; i += 4)
    {
        /* 循环展开:一次处理4个字 */
        dst32[i] = src32[i];
        dst32[i+1] = src32[i+1];
        dst32[i+2] = src32[i+2];
        dst32[i+3] = src32[i+3];
    }
    
    /* 处理剩余字节 */
    uint8_t *dst8 = (uint8_t*)&dst32[word_count];
    uint8_t *src8 = (uint8_t*)&src32[word_count];
    
    for (uint32_t i = 0; i < (size % 4); i++)
    {
        dst8[i] = src8[i];
    }
}

// 8. 使用查表法替代复杂计算
const uint16_t sin_table[256] = {
    2048, 2098, 2148, 2198, 2248, 2298, 2348, 2398,
    // ... 完整的正弦表
};

uint16_t Fast_Sin(uint8_t angle)
{
    return sin_table[angle];
}

// 9. 预计算优化
typedef struct
{
    float sin_value;
    float cos_value;
    uint32_t timestamp;
} Precomputed_Values_t;

Precomputed_Values_t precomputed[360];

void Precompute_Trigonometric_Values(void)
{
    for (int i = 0; i < 360; i++)
    {
        float rad = i * 3.1415926535f / 180.0f;
        precomputed[i].sin_value = sinf(rad);
        precomputed[i].cos_value = cosf(rad);
        precomputed[i].timestamp = HAL_GetTick();
    }
}

// 10. 使用硬件加速器(如果可用)
void Hardware_Accelerated_CRC32(void)
{
#if defined(CRC)
    /* 使用STM32硬件CRC计算 */
    __HAL_RCC_CRC_CLK_ENABLE();
    
    uint32_t data[] = {0x12345678, 0x9ABCDEF0, 0x11223344, 0x55667788};
    
    /* 复位CRC计算单元 */
    HAL_CRC_DeInit(&hcrc);
    
    /* 计算CRC */
    uint32_t crc = HAL_CRC_Calculate(&hcrc, data, 4);
    
    printf("Hardware CRC32: 0x%08lX\r\n", crc);
#endif
}

// 11. 电源管理优化
void Power_Optimization(void)
{
    /* 动态调整系统时钟 */
    if (system_load_high)
    {
        /* 高性能模式 */
        SystemClock_Config_HighSpeed();
        __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
    }
    else
    {
        /* 低功耗模式 */
        SystemClock_Config_LowSpeed();
        __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);
    }
    
    /* 禁用未使用的外设时钟 */
    __HAL_RCC_USART2_CLK_DISABLE();
    __HAL_RCC_SPI2_CLK_DISABLE();
    __HAL_RCC_TIM3_CLK_DISABLE();
    
    /* 配置未使用的GPIO为模拟输入 */
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    GPIO_InitStruct.Pin = GPIO_PIN_All;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}

// 12. 编译优化选项
/*
在Makefile或IDE中设置优化选项:
- -O2或-O3:代码大小和执行速度优化
- -Os:代码大小优化
- -flto:链接时优化
- -ffunction-sections -fdata-sections:配合链接脚本进行垃圾回收
*/

// 链接脚本中的优化
/*
在链接脚本中添加:
.text : {
    *(.text .text.*)  /* 按函数排序,提高缓存命中率 
    . = ALIGN(4);
} > FLASH
*/

第十二章:HAL库项目实战

12.1 多任务系统设计

/**
 * @brief 基于HAL库的简单多任务系统
 */

// 任务控制块
typedef struct
{
    void (*task_func)(void);      /* 任务函数 */
    uint32_t interval_ms;         /* 执行间隔 */
    uint32_t last_run_time;       /* 上次执行时间 */
    uint8_t enabled;              /* 任务使能标志 */
    uint8_t priority;             /* 任务优先级 */
    char name[16];                /* 任务名称 */
} Task_Control_Block_t;

// 任务列表
#define MAX_TASKS 10
Task_Control_Block_t task_list[MAX_TASKS];
uint8_t task_count = 0;

// 任务调度器初始化
void Task_Scheduler_Init(void)
{
    memset(task_list, 0, sizeof(task_list));
    task_count = 0;
}

// 注册任务
uint8_t Task_Register(void (*func)(void), 
                      uint32_t interval_ms, 
                      uint8_t priority, 
                      const char *name)
{
    if (task_count >= MAX_TASKS)
        return 0;
    
    task_list[task_count].task_func = func;
    task_list[task_count].interval_ms = interval_ms;
    task_list[task_count].last_run_time = 0;
    task_list[task_count].enabled = 1;
    task_list[task_count].priority = priority;
    strncpy(task_list[task_count].name, name, 15);
    task_list[task_count].name[15] = '\0';
    
    task_count++;
    return 1;
}

// 任务调度器(在systick中断中调用)
void Task_Scheduler_Run(void)
{
    static uint32_t last_schedule_time = 0;
    uint32_t current_time = HAL_GetTick();
    
    /* 调度周期:1ms */
    if ((current_time - last_schedule_time) < 1)
        return;
    
    last_schedule_time = current_time;
    
    /* 按优先级执行任务 */
    for (int priority = 0; priority <= 255; priority++)
    {
        for (int i = 0; i < task_count; i++)
        {
            if (task_list[i].enabled && 
                task_list[i].priority == priority)
            {
                /* 检查是否到达执行时间 */
                if ((current_time - task_list[i].last_run_time) >= 
                    task_list[i].interval_ms)
                {
                    /* 执行任务 */
                    task_list[i].task_func();
                    task_list[i].last_run_time = current_time;
                }
            }
        }
    }
}

// 任务监控
void Task_Monitor(void)
{
    static uint32_t last_monitor_time = 0;
    uint32_t current_time = HAL_GetTick();
    
    if ((current_time - last_monitor_time) >= 1000)  /* 1秒监控一次 */
    {
        printf("=== Task Monitor ===\r\n");
        
        for (int i = 0; i < task_count; i++)
        {
            uint32_t exec_time = current_time - task_list[i].last_run_time;
            
            printf("Task %s: Priority=%d, Interval=%lums, "
                   "LastExec=%lums ago, Enabled=%d\r\n",
                   task_list[i].name,
                   task_list[i].priority,
                   task_list[i].interval_ms,
                   exec_time,
                   task_list[i].enabled);
        }
        
        last_monitor_time = current_time;
    }
}

// 示例任务定义
void LED_Task(void)
{
    HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
}

void Sensor_Read_Task(void)
{
    /* 读取传感器数据 */
    float temperature = Read_Temperature();
    float humidity = Read_Humidity();
    
    /* 处理传感器数据 */
    Process_Sensor_Data(temperature, humidity);
}

void Communication_Task(void)
{
    /* 检查是否有数据需要发送 */
    if (Has_Data_To_Send())
    {
        Send_Data_Over_UART();
    }
    
    /* 检查是否有接收到的数据 */
    if (Has_Data_Received())
    {
        Process_Received_Data();
    }
}

// 主函数中的任务调度
int main(void)
{
    HAL_Init();
    SystemClock_Config();
    
    /* 硬件初始化 */
    MX_GPIO_Init();
    MX_USART1_UART_Init();
    MX_I2C1_Init();
    MX_SPI1_Init();
    
    /* 任务调度器初始化 */
    Task_Scheduler_Init();
    
    /* 注册任务 */
    Task_Register(LED_Task, 500, 1, "LED Blink");          /* 500ms,低优先级 */
    Task_Register(Sensor_Read_Task, 1000, 0, "Sensor Read");  /* 1s,高优先级 */
    Task_Register(Communication_Task, 100, 0, "Comm Task");   /* 100ms,高优先级 */
    Task_Register(Task_Monitor, 1000, 2, "Task Monitor");     /* 1s,最低优先级 */
    
    while (1)
    {
        /* 运行任务调度器 */
        Task_Scheduler_Run();
        
        /* 空闲任务:进入低功耗模式 */
        HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
    }
}

12.2 数据采集与传输系统

/**
 * @brief 完整的数据采集与传输系统
 */

// 数据包结构
#pragma pack(push, 1)  /* 字节对齐 */
typedef struct
{
    uint32_t timestamp;           /* 时间戳 */
    uint16_t packet_id;           /* 数据包ID */
    uint8_t sensor_id;            /* 传感器ID */
    float temperature;            /* 温度 */
    float humidity;               /* 湿度 */
    float pressure;               /* 气压 */
    uint16_t light_intensity;     /* 光照强度 */
    uint16_t battery_voltage;     /* 电池电压 */
    uint16_t checksum;            /* CRC校验和 */
} Sensor_Data_Packet_t;
#pragma pack(pop)  /* 恢复对齐 */

// 数据缓冲区
#define DATA_BUFFER_SIZE 100
Sensor_Data_Packet_t data_buffer[DATA_BUFFER_SIZE];
uint16_t data_write_index = 0;
uint16_t data_read_index = 0;
uint16_t data_count = 0;

// 数据采集任务
void Data_Acquisition_Task(void)
{
    static uint32_t last_acquisition_time = 0;
    uint32_t current_time = HAL_GetTick();
    
    /* 采集周期:1秒 */
    if ((current_time - last_acquisition_time) < 1000)
        return;
    
    last_acquisition_time = current_time;
    
    /* 检查缓冲区是否已满 */
    if (data_count >= DATA_BUFFER_SIZE)
    {
        printf("Data buffer full!\r\n");
        return;
    }
    
    /* 采集传感器数据 */
    Sensor_Data_Packet_t packet;
    
    packet.timestamp = current_time;
    packet.packet_id = Get_Next_Packet_ID();
    packet.sensor_id = SENSOR_ID;
    packet.temperature = Read_Temperature_Sensor();
    packet.humidity = Read_Humidity_Sensor();
    packet.pressure = Read_Pressure_Sensor();
    packet.light_intensity = Read_Light_Sensor();
    packet.battery_voltage = Read_Battery_Voltage();
    
    /* 计算校验和 */
    packet.checksum = Calculate_CRC16((uint8_t*)&packet, 
                                     sizeof(packet) - sizeof(uint16_t));
    
    /* 存储到缓冲区 */
    data_buffer[data_write_index] = packet;
    data_write_index = (data_write_index + 1) % DATA_BUFFER_SIZE;
    data_count++;
    
    printf("Data acquired: Temp=%.2fC, Hum=%.1f%%, Packets=%d\r\n",
           packet.temperature, packet.humidity, data_count);
}

// 数据传输任务
void Data_Transmission_Task(void)
{
    static uint32_t last_transmission_time = 0;
    uint32_t current_time = HAL_GetTick();
    
    /* 传输周期:5秒或有数据时立即发送 */
    if ((current_time - last_transmission_time) < 5000 && data_count < 10)
        return;
    
    /* 检查是否有数据需要传输 */
    if (data_count == 0)
        return;
    
    last_transmission_time = current_time;
    
    /* 准备传输缓冲区 */
    uint8_t tx_buffer[1024];
    uint16_t tx_index = 0;
    
    /* 添加协议头 */
    tx_buffer[tx_index++] = 0xAA;
    tx_buffer[tx_index++] = 0x55;
    tx_buffer[tx_index++] = (uint8_t)(data_count & 0xFF);
    tx_buffer[tx_index++] = (uint8_t)((data_count >> 8) & 0xFF);
    
    /* 添加数据包 */
    uint16_t packets_to_send = (data_count > 5) ? 5 : data_count;  /* 每次最多发送5个包 */
    
    for (int i = 0; i < packets_to_send; i++)
    {
        Sensor_Data_Packet_t *packet = &data_buffer[data_read_index];
        
        memcpy(&tx_buffer[tx_index], packet, sizeof(Sensor_Data_Packet_t));
        tx_index += sizeof(Sensor_Data_Packet_t);
        
        data_read_index = (data_read_index + 1) % DATA_BUFFER_SIZE;
        data_count--;
    }
    
    /* 计算并添加CRC校验 */
    uint16_t crc = Calculate_CRC16(tx_buffer, tx_index);
    tx_buffer[tx_index++] = (uint8_t)(crc >> 8);
    tx_buffer[tx_index++] = (uint8_t)(crc & 0xFF);
    
    /* 通过UART发送数据 */
    HAL_UART_Transmit_DMA(&huart1, tx_buffer, tx_index);
    
    printf("Transmitted %d packets, %d remaining\r\n", 
           packets_to_send, data_count);
}

// 数据持久化(存储到Flash)
void Data_Persistence_Task(void)
{
    static uint32_t last_save_time = 0;
    uint32_t current_time = HAL_GetTick();
    
    /* 保存周期:30秒或缓冲区快满时 */
    if ((current_time - last_save_time) < 30000 && data_count < (DATA_BUFFER_SIZE * 0.8))
        return;
    
    last_save_time = current_time;
    
    /* 检查Flash是否已满 */
    if (Is_Flash_Full())
    {
        printf("Flash storage full!\r\n");
        return;
    }
    
    /* 保存数据到Flash */
    uint16_t packets_to_save = data_count;
    
    for (int i = 0; i < packets_to_save; i++)
    {
        Sensor_Data_Packet_t *packet = &data_buffer[data_read_index];
        
        /* 写入Flash */
        if (Write_To_Flash(packet, sizeof(Sensor_Data_Packet_t)) != HAL_OK)
        {
            printf("Flash write failed!\r\n");
            break;
        }
        
        data_read_index = (data_read_index + 1) % DATA_BUFFER_SIZE;
        data_count--;
    }
    
    printf("Saved %d packets to Flash, %d remaining in buffer\r\n",
           packets_to_save, data_count);
}

// Flash存储管理
#define FLASH_PAGE_SIZE 2048
#define FLASH_TOTAL_PAGES 128
#define FLASH_START_ADDRESS 0x08020000  /* Bank2起始地址 */

typedef struct
{
    uint32_t start_address;
    uint32_t end_address;
    uint32_t write_pointer;
    uint32_t read_pointer;
    uint32_t used_pages;
    uint32_t total_pages;
} Flash_Storage_t;

Flash_Storage_t flash_storage;

void Flash_Storage_Init(void)
{
    flash_storage.start_address = FLASH_START_ADDRESS;
    flash_storage.end_address = FLASH_START_ADDRESS + (FLASH_TOTAL_PAGES * FLASH_PAGE_SIZE);
    flash_storage.write_pointer = FLASH_START_ADDRESS;
    flash_storage.read_pointer = FLASH_START_ADDRESS;
    flash_storage.used_pages = 0;
    flash_storage.total_pages = FLASH_TOTAL_PAGES;
    
    /* 查找最后的写入位置 */
    Find_Last_Write_Position();
}

HAL_StatusTypeDef Write_To_Flash(void *data, uint32_t size)
{
    /* 检查Flash是否已满 */
    if (flash_storage.used_pages >= flash_storage.total_pages)
        return HAL_ERROR;
    
    /* 检查当前页是否有足够空间 */
    uint32_t page_start = flash_storage.write_pointer & ~(FLASH_PAGE_SIZE - 1);
    uint32_t page_end = page_start + FLASH_PAGE_SIZE;
    
    if ((flash_storage.write_pointer + size) > page_end)
    {
        /* 需要擦除新的一页 */
        if (Erase_Flash_Page(page_end) != HAL_OK)
            return HAL_ERROR;
        
        flash_storage.write_pointer = page_end;
        flash_storage.used_pages++;
    }
    
    /* 写入数据 */
    HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, 
                      flash_storage.write_pointer, 
                      *(uint32_t*)data);
    
    flash_storage.write_pointer += size;
    
    return HAL_OK;
}

// 系统监控任务
void System_Monitor_Task(void)
{
    static uint32_t last_monitor_time = 0;
    uint32_t current_time = HAL_GetTick();
    
    if ((current_time - last_monitor_time) < 10000)  /* 10秒监控一次 */
        return;
    
    last_monitor_time = current_time;
    
    /* 获取系统信息 */
    uint32_t free_heap = Get_Free_Heap_Size();
    uint32_t stack_usage = Get_Stack_Usage();
    float cpu_usage = Calculate_CPU_Usage();
    uint32_t uptime = Get_System_Uptime();
    
    /* 获取电源信息 */
    float battery_level = Read_Battery_Level();
    uint8_t charging_status = Get_Charging_Status();
    
    /* 获取网络信息(如果有) */
    int8_t rssi = Get_WiFi_RSSI();
    uint8_t network_status = Get_Network_Status();
    
    /* 打印系统状态 */
    printf("=== System Status ===\r\n");
    printf("Uptime: %lu seconds\r\n", uptime);
    printf("CPU Usage: %.1f%%\r\n", cpu_usage);
    printf("Free Heap: %lu bytes\r\n", free_heap);
    printf("Stack Usage: %lu bytes\r\n", stack_usage);
    printf("Battery: %.1f%% %s\r\n", 
           battery_level, 
           charging_status ? "(Charging)" : "");
    printf("Data Buffer: %d/%d packets\r\n", data_count, DATA_BUFFER_SIZE);
    printf("Flash Used: %lu/%lu pages\r\n", 
           flash_storage.used_pages, flash_storage.total_pages);
    
    if (network_status)
    {
        printf("WiFi RSSI: %d dBm\r\n", rssi);
    }
}

// 主应用程序
int main(void)
{
    /* HAL库初始化 */
    HAL_Init();
    
    /* 配置系统时钟 */
    SystemClock_Config();
    
    /* 初始化所有外设 */
    MX_GPIO_Init();
    MX_USART1_UART_Init();
    MX_I2C1_Init();
    MX_SPI1_Init();
    MX_ADC1_Init();
    MX_RTC_Init();
    
    /* 初始化文件系统(如果需要) */
    FATFS_Init();
    
    /* 初始化Flash存储 */
    Flash_Storage_Init();
    
    /* 初始化任务调度器 */
    Task_Scheduler_Init();
    
    /* 注册系统任务 */
    Task_Register(Data_Acquisition_Task, 1000, 0, "Data Acquisition");
    Task_Register(Data_Transmission_Task, 100, 1, "Data Transmission");
    Task_Register(Data_Persistence_Task, 5000, 2, "Data Persistence");
    Task_Register(System_Monitor_Task, 10000, 3, "System Monitor");
    
    /* 启动看门狗(如果需要) */
    IWDG_Init();
    
    printf("System started successfully!\r\n");
    
    /* 主循环 */
    while (1)
    {
        /* 运行任务调度器 */
        Task_Scheduler_Run();
        
        /* 喂狗 */
        HAL_IWDG_Refresh(&hiwdg);
        
        /* 空闲时进入低功耗模式 */
        if (Is_System_Idle())
        {
            HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
        }
    }
}

第十三章:HAL库最佳实践总结

13.1 代码规范与架构设计

  1. 模块化设计原则
// 良好的模块化示例
// sensor_module.h
#ifndef SENSOR_MODULE_H
#define SENSOR_MODULE_H

#include "stm32f4xx_hal.h"

typedef struct {
    float temperature;
    float humidity;
    float pressure;
} SensorData_t;

typedef enum {
    SENSOR_OK = 0,
    SENSOR_ERROR,
    SENSOR_TIMEOUT
} SensorStatus_t;

SensorStatus_t Sensor_Init(I2C_HandleTypeDef *hi2c);
SensorStatus_t Sensor_Read(SensorData_t *data);
void Sensor_Deinit(void);

#endif /* SENSOR_MODULE_H */

// sensor_module.c
#include "sensor_module.h"

static I2C_HandleTypeDef *sensor_i2c = NULL;

SensorStatus_t Sensor_Init(I2C_HandleTypeDef *hi2c)
{
    if (hi2c == NULL) {
        return SENSOR_ERROR;
    }
    
    sensor_i2c = hi2c;
    
    // 传感器初始化代码
    // ...
    
    return SENSOR_OK;
}
  1. 错误处理策略
// 统一的错误处理框架
typedef enum {
    ERROR_NONE = 0,
    ERROR_HAL,
    ERROR_TIMEOUT,
    ERROR_COMMUNICATION,
    ERROR_MEMORY,
    ERROR_SENSOR,
    ERROR_CONFIG
} ErrorCode_t;

typedef struct {
    ErrorCode_t code;
    uint32_t timestamp;
    const char *module;
    uint32_t line;
} ErrorInfo_t;

#define ERROR_LOG(module, code) \
    do { \
        ErrorInfo_t error = { \
            .code = code, \
            .timestamp = HAL_GetTick(), \
            .module = module, \
            .line = __LINE__ \
        }; \
        Log_Error(&error); \
    } while(0)

void Log_Error(ErrorInfo_t *error)
{
    printf("[ERROR] Module: %s, Code: %d, Time: %lu, Line: %lu\r\n",
           error->module, error->code, error->timestamp, error->line);
    
    // 可选:保存错误到非易失存储器
    Save_Error_To_Flash(error);
}

13.2 性能优化建议

  1. 时钟配置优化
// 根据需求动态调整时钟
void Dynamic_Clock_Adjustment(SystemMode_t mode)
{
    switch (mode) {
        case MODE_HIGH_PERFORMANCE:
            // 配置为最高性能
            __HAL_RCC_PLLI2S_DISABLE();
            __HAL_RCC_PLLSAI_DISABLE();
            SystemClock_Config_HighSpeed();
            break;
            
        case MODE_BALANCED:
            // 平衡模式
            SystemClock_Config_Balanced();
            break;
            
        case MODE_LOW_POWER:
            // 低功耗模式
            SystemClock_Config_LowPower();
            break;
    }
}
  1. 内存管理优化
// 使用内存池避免碎片
#define MEMORY_POOL_SIZE 4096
static uint8_t memory_pool[MEMORY_POOL_SIZE];
static uint32_t memory_index = 0;

void* Memory_Allocate(size_t size)
{
    if (memory_index + size > MEMORY_POOL_SIZE) {
        return NULL;
    }
    
    void *ptr = &memory_pool[memory_index];
    memory_index += size;
    
    return ptr;
}

void Memory_Reset(void)
{
    memory_index = 0;
}

13.3 维护与升级策略

  1. 版本管理
// 固件版本信息
typedef struct {
    uint8_t major;
    uint8_t minor;
    uint8_t patch;
    uint32_t build_number;
    const char *build_date;
    const char *build_time;
} FirmwareVersion_t;

const FirmwareVersion_t firmware_version = {
    .major = 1,
    .minor = 0,
    .patch = 0,
    .build_number = 1234,
    .build_date = __DATE__,
    .build_time = __TIME__
};

void Print_Firmware_Info(void)
{
    printf("Firmware Version: %d.%d.%d\r\n",
           firmware_version.major,
           firmware_version.minor,
           firmware_version.patch);
    printf("Build: %lu, Date: %s %s\r\n",
           firmware_version.build_number,
           firmware_version.build_date,
           firmware_version.build_time);
}
  1. OTA升级支持
// 简单的OTA升级框架
typedef enum {
    BOOTLOADER_MODE,
    APPLICATION_MODE,
    UPDATE_MODE
} SystemMode_t;

SystemMode_t Check_System_Mode(void)
{
    // 检查是否有更新标志
    if (FLASH_Read_Update_Flag()) {
        return UPDATE_MODE;
    }
    
    // 检查应用程序是否有效
    if (!Check_Application_Valid()) {
        return BOOTLOADER_MODE;
    }
    
    return APPLICATION_MODE;
}

void OTA_Update_Handler(void)
{
    printf("Starting OTA update...\r\n");
    
    // 1. 接收新固件
    if (Receive_New_Firmware() != HAL_OK) {
        printf("Firmware reception failed\r\n");
        return;
    }
    
    // 2. 验证固件
    if (Verify_Firmware() != HAL_OK) {
        printf("Firmware verification failed\r\n");
        return;
    }
    
    // 3. 编程Flash
    if (Program_Flash() != HAL_OK) {
        printf("Flash programming failed\r\n");
        return;
    }
    
    // 4. 设置启动标志
    Set_Boot_Flag();
    
    printf("OTA update completed successfully\r\n");
    
    // 5. 重启系统
    NVIC_SystemReset();
}

结语

本文详细介绍了STM32 HAL库的各个方面,从基础概念到高级应用,从单个外设操作到完整系统设计。HAL库作为STM32生态系统中重要的组成部分,为开发者提供了高效、统一的编程接口。通过本文的学习,读者应该能够:

  1. 深入理解HAL库的设计哲学和架构

    • 掌握HAL库的分层结构和设计理念
    • 理解状态机和回调机制的工作原理
  2. 熟练使用各种外设

    • 掌握GPIO、UART、I2C、SPI、ADC、DAC等常用外设的配置和使用
    • 理解中断和DMA在提高系统效率中的重要作用
  3. 掌握系统级设计技巧

    • 学会构建多任务系统
    • 掌握低功耗设计和电源管理
    • 理解性能优化和调试技巧
  4. 具备工程实践能力

    • 能够设计和实现完整的嵌入式系统
    • 掌握错误处理和系统监控的方法
    • 了解固件升级和维护的最佳实践

HAL库虽然抽象了硬件细节,但并不意味着开发者不需要理解底层原理。相反,深入理解HAL库背后的工作机制,结合实际硬件特性,才能开发出高效、稳定的嵌入式系统。

随着STM32系列的不断发展和更新,HAL库也在持续演进。建议开发者:

  • 定期查看ST官方文档和更新
  • 参与STM32社区讨论
  • 在实际项目中不断实践和总结
  • 保持学习新技术和新工具的热情

嵌入式开发是一个需要不断学习和实践的领域,希望本文能为您的STM32开发之旅提供有价值的参考和帮助。


作者注:本文代码示例基于STM32F4系列,部分高级功能可能需要特定系列支持。在实际开发中,请参考具体芯片的参考手册和数据手册。所有代码均经过简化,实际使用时需要考虑错误处理、边界条件等具体情况。

版权声明:本文内容可供学习和参考,转载请注明出处。商业使用请联系作者授权。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐