STM32f407接口

发布时间:2026/8/23 9:48:37
STM32f407接口 嵌入式常用外设速查STM32 版Error_Handler 为开发者提供了一个统一的错误陷阱防止程序在异常状态下继续运行导致更严重问题。在最终产品中可以将其扩展为恢复机制复位、重试或安全停机。LookLook:1. GPIO — 最基础的引脚控制· 时钟__HAL_RCC_GPIOx_CLK_ENABLE()· 输出HAL_GPIO_WritePin() / TogglePin()· 输入HAL_GPIO_ReadPin()· 中断配置为 GPIO_MODE_IT_xxxNVIC 使能重写 HAL_GPIO_EXTI_Callback()· 复用GPIO_MODE_AF_PP AlternateF4/H7或 GPIO_PinAFConfig()F1· 注意开漏输出需外接上拉速度不是越高越好---2. ADC — 模拟量采集· 初始化HAL_ADC_Init() HAL_ADC_ConfigChannel()· 轮询HAL_ADC_Start() → HAL_ADC_PollForConversion() → HAL_ADC_GetValue()· 中断HAL_ADC_Start_IT() HAL_ADC_ConvCpltCallback()· DMAHAL_ADC_Start_DMA() 回调· 多通道必须开启 ScanConvMode并设置 NbrOfConversion· 电压计算Voltage (adc_value * 3300) / 4096mV12位3.3V基准HAL_ADC_Start(ADC句柄); // 启动ADC转换阻塞方式HAL_ADC_Stop(ADC句柄); // 停止ADC转换HAL_ADC_Start_IT(ADC句柄); // 启动ADC转换中断方式HAL_ADC_Stop_IT(ADC句柄); // 停止ADC转换中断方式HAL_ADC_Start_DMA(ADC句柄, 数据指针, 长度); // 启动ADC转换DMA方式HAL_ADC_Stop_DMA(ADC句柄); // 停止ADC转换DMA方式HAL_ADC_PollForConversion(ADC句柄, 超时时间); // 等待ADC转换完成阻塞轮询HAL_ADC_GetValue(ADC句柄); // 获取ADC采样值---3. DMA — 数据传输免 CPU· 方向DMA_DIR_PeripheralToMemory / MemoryToPeripheral / MemoryToMemory· 模式Normal一次传输 / Circular循环· 地址自增外设通常不增内存增· 启动结合具体外设如 HAL_UART_Transmit_DMA() / HAL_ADC_Start_DMA()· 回调HAL_DMA_TxCpltCallback() 等· 注意DMA 中断优先级通常高于外设中断循环模式需要手动重启或自动重载__HAL_DMA_GET_COUNTER(hdma_usart1_rx);用来获取当前剩余待传输数据量即DMA计数器中还剩多少个未传数据【NDTR】。--hdma_usart1_rx在UART.c文件中找到。---4. NVIC — 中断管理· 全局分组HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_2)一次· 设置优先级HAL_NVIC_SetPriority(IRQn, PreemptPriority, SubPriority)· 使能/禁止HAL_NVIC_EnableIRQ() / DisableIRQ()· 数值越小优先级越高· 临界区__disable_irq() / __enable_irq()HAL_GPIO_EXTI_Callback(uint16_t 引脚号); // 外部中断回调GPIO口触发HAL_UART_TxCpltCallback(UART_HandleTypeDef *串口句柄); // UART发送完成回调中断/DMAHAL_UART_RxCpltCallback(UART_HandleTypeDef *串口句柄); // UART接收完成回调中断/DMAHAL_UARTEx_RxEventCallback(UART_HandleTypeDef *串口句柄, uint16_t 数据长度); // UART接收事件回调如IDLE触发接收长度HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *I2C句柄); // I2C主机发送完成回调中断/DMAHAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *I2C句柄); // I2C主机接收完成回调中断/DMAHAL_SPI_TxCpltCallback(SPI_HandleTypeDef *SPI句柄); // SPI发送完成回调中断/DMAHAL_SPI_RxCpltCallback(SPI_HandleTypeDef *SPI句柄); // SPI接收完成回调中断/DMAHAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *SPI句柄); // SPI同时收发完成回调中断/DMAHAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *ADC句柄); // ADC转换完成回调阻塞/中断/DMAHAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *定时器句柄); // 定时器周期溢出回调HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *定时器句柄); // 定时器输入捕获完成回调HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *定时器句柄); // PWM脉冲完成回调---5. USART / UART — 串口通信· 轮询HAL_UART_Transmit() / Receive()· 中断HAL_UART_Transmit_IT() / Receive_IT() 回调 HAL_UART_TxCpltCallback() / RxCpltCallback()· DMAHAL_UART_Transmit_DMA() / Receive_DMA()常用 空闲中断接收不定长数据· printf 重定向重写 fputc 调用 HAL_UART_Transmit· 注意中断/ DMA 接收完成需再次调用启动波特率误差 2.5%HAL_UART_DMAStop(huart1);关掉UART的DMA请求发送DMAR并关闭DMA。HAL_UART_Transmit(串口句柄, 数据指针, 数据长度, 超时时间); // 串口发送阻塞方式HAL_UART_Receive(串口句柄, 数据指针, 数据长度, 超时时间); // 串口接收阻塞方式HAL_UART_Transmit_IT(串口句柄, 数据指针, 数据长度); // 串口发送中断方式HAL_UART_Receive_IT(串口句柄, 数据指针, 数据长度); // 串口接收中断方式HAL_UART_Transmit_DMA(串口句柄, 数据指针, 数据长度); // 串口发送DMA方式HAL_UART_Receive_DMA(串口句柄, 数据指针, 数据长度); // 串口接收DMA方式这些都可以在stm32f4xx_hal_uart.h中大约500行左右用__HAL_UART_ENABLE_IT();时中断写在这---6. TIM — 定时器万能工具· 时基中断HAL_TIM_Base_Start_IT() → 回调 HAL_TIM_PeriodElapsedCallback()· PWM 输出HAL_TIM_PWM_Start() __HAL_TIM_SET_COMPARE() 改占空比· 输入捕获HAL_TIM_IC_Start_IT() → 回调 HAL_TIM_IC_CaptureCallback()· 编码器HAL_TIM_Encoder_Start() __HAL_TIM_GET_COUNTER() 读当前值__HAL_TIM_SetCounter()改变定时器的初始值· 公式计数频率 定时器时钟 / (Prescaler1)溢出时间 (Period1) / 计数频率TIM 定时器定时器基础功能HAL_TIM_Base_InitHAL_TIM_Base_DeInitHAL_TIM_Base_MspInitHAL_TIM_Base_MspDeInitHAL_TIM_Base_StartHAL_TIM_Base_StopHAL_TIM_Base_Start_ITHAL_TIM_Base_Stop_ITHAL_TIM_Base_Start_DMAHAL_TIM_Base_Stop_DM输出比较功能HAL_TIM_OC_InitHAL_TIM_OC_DeInitHAL_TIM_OC_MspInitHAL_TIM_OC_MspDeInitHAL_TIM_OC_StartHAL_TIM_OC_StopHAL_TIM_OC_Start_ITHAL_TIM_OC_Stop_ITHAL_TIM_OC_Start_DMAHAL_TIM_OC_Stop_DMAPWM功能HAL_TIM_PWM_InitHAL_TIM_PWM_DeInitHAL_TIM_PWM_MspInitHAL_TIM_PWM_MspDeInitHAL_TIM_PWM_StartHAL_TIM_PWM_StopHAL_TIM_PWM_Start_ITHAL_TIM_PWM_Stop_ITHAL_TIM_PWM_Start_DMAHAL_TIM_PWM_Stop_DMA输入捕获功能HAL_TIM_IC_InitHAL_TIM_IC_DeInitHAL_TIM_IC_MspInitHAL_TIM_IC_MspDeInitHAL_TIM_IC_StartHAL_TIM_IC_StopHAL_TIM_IC_Start_ITHAL_TIM_IC_Stop_ITHAL_TIM_IC_Start_DMAHAL_TIM_IC_Stop_DMA单脉冲模式HAL_TIM_OnePulse_InitHAL_TIM_OnePulse_DeInitHAL_TIM_OnePulse_MspInitHAL_TIM_OnePulse_MspDeInitHAL_TIM_OnePulse_StartHAL_TIM_OnePulse_StopHAL_TIM_OnePulse_Start_ITHAL_TIM_OnePulse_Stop_IT编码器功能HAL_TIM_Encoder_InitHAL_TIM_Encoder_DeInitHAL_TIM_Encoder_MspInitHAL_TIM_Encoder_MspDeInitHAL_TIM_Encoder_StartHAL_TIM_Encoder_StopHAL_TIM_Encoder_Start_ITHAL_TIM_Encoder_Stop_ITHAL_TIM_Encoder_Start_DMAHAL_TIM_Encoder_Stop_DMA回调函数HAL_TIM_PeriodElapsedCallbackHAL_TIM_PeriodElapsedHalfCpltCallbackHAL_TIM_OC_DelayElapsedCallbackHAL_TIM_IC_CaptureCallbackHAL_TIM_IC_CaptureHalfCpltCallbackHAL_TIM_PWM_PulseFinishedCallbackHAL_TIM_PWM_PulseFinishedHalfCpltCallbackHAL_TIM_TriggerCallbackHAL_TIM_TriggerHalfCpltCallbackHAL_TIM_ErrorCallbacHAL_TIM_Base_Start(定时器句柄); // 启动基本定时器不带中断HAL_TIM_Base_Start_IT(定时器句柄); // 启动基本定时器中断方式HAL_TIM_Base_Stop(定时器句柄); // 停止基本定时器不带中断HAL_TIM_Base_Stop_IT(定时器句柄); // 停止基本定时器中断方式HAL_TIM_PWM_Start(定时器句柄, 通道); // 启动PWM输出HAL_TIM_PWM_Stop(定时器句柄, 通道); // 停止PWM输出HAL_TIM_IC_Start(定时器句柄, 通道); // 启动输入捕获HAL_TIM_IC_Stop(定时器句柄, 通道); // 停止输入捕获HAL_TIM_Encoder_Start(定时器句柄, 通道组合); // 启动编码器模式HAL_TIM_Encoder_Stop(定时器句柄, 通道组合); // 停止编码器模式获取滴答计时器---7. I2C — 双线总线获取总线的状态HAL_I2C_GetState()· 主发送/接收HAL_I2C_Master_Transmit() / Receive()· 读写寄存器HAL_I2C_Mem_Write() / Read()EEPROM、传感器· 地址7 位地址不包含 R/W 位· 中断/DMA_IT / _DMA 后缀函数 回调HAL_I2C_Master/SlaveTx/RxCpltCallback,HAL_I2CErrorCallback,HAL_I2C_MemTxCpltCallback / MemRxCpltCallback 内存寄存器读写完成· 扫描设备HAL_I2C_IsDeviceReady()· 注意必须外接上拉电阻4.7kΩF1 早期硬件有 bug 建议软件模拟.I2C协议中每个字节传输后都需要一个应答位ACK/NACK。前面的代码示例中并没有忽略应答只是因为 STM32 HAL 库的 HAL_I2C_Master_Transmit 等函数已经内部自动处理了应答包括发送完每个字节后检查从机的应答以及接收最后一个字节时自动发送 NACKHAL_I2C_Master_Transmit(I2C句柄, 设备地址, 数据指针, 数据长度, 超时时间); // 主机发送数据阻塞方式HAL_I2C_Master_Receive(I2C句柄, 设备地址, 数据指针, 数据长度, 超时时间); // 主机接收数据阻塞方式HAL_I2C_Master_Transmit_IT(I2C句柄, 设备地址, 数据指针, 数据长度); // 主机发送数据中断方式HAL_I2C_Master_Receive_IT(I2C句柄, 设备地址, 数据指针, 数据长度); // 主机接收数据中断方式HAL_I2C_Master_Transmit_DMA(I2C句柄, 设备地址, 数据指针, 数据长度); // 主机发送数据DMA方式HAL_I2C_Master_Receive_DMA(I2C句柄, 设备地址, 数据指针, 数据长度); // 主机接收数据DMA方式---8. SPI — 四线全双工虽未专门总结但常用· 模式CPOL/CPHA 决定时钟极性和相位· 常用函数HAL_SPI_Transmit() / Receive() / TransmitReceive()· 中断/DMA_IT / _DMA 版本· 注意片选通常软件控制HAL_SPI_Transmit(SPI句柄, 数据指针, 数据长度, 超时时间); // 发送数据阻塞方式HAL_SPI_Receive(SPI句柄, 数据指针, 数据长度, 超时时间); // 接收数据阻塞方式HAL_SPI_TransmitReceive(SPI句柄, 发送指针, 接收指针, 数据长度, 超时时间); // 同时收发阻塞方式HAL_SPI_Transmit_IT(SPI句柄, 数据指针, 数据长度); // 发送数据中断方式HAL_SPI_Receive_IT(SPI句柄, 数据指针, 数据长度); // 接收数据中断方式HAL_SPI_TransmitReceive_IT(SPI句柄, 发送指针, 接收指针, 数据长度); // 同时收发中断方式HAL_SPI_Transmit_DMA(SPI句柄, 数据指针, 数据长度); // 发送数据DMA方式HAL_SPI_Receive_DMA(SPI句柄, 数据指针, 数据长度); // 接收数据DMA方式HAL_SPI_TransmitReceive_DMA(SPI句柄, 发送指针, 接收指针, 数据长度); // 同时收发DMA方式---9. DAC — 数字转电压· 配置触发源软件/定时器、输出缓冲· 输出HAL_DAC_SetValue()软件触发· 波形配合定时器 DMA 输出正弦波等· 公式输出电压 (DAC值 / 2^12) × Vref· 注意引脚设为模拟模式输出缓冲驱动能力有限---10. IWDG — 独立看门狗· 启动HAL_IWDG_Init()设预分频、重载值· 喂狗HAL_IWDG_Refresh()· 超时超时 Reload × (Prescaler) / LSI_freqLSI ≈ 32kHz· 注意启动后不可停止在调试时可冻结DBGMCU主循环中喂狗不要在中断---11. FSMC / FMC — 并行总线扩展· 用途外扩 SRAM、NOR、NAND、LCD8080 接口· 配置时序结构体建立时间、保持时间等 控制结构体数据宽度、片选等· 访问直接指针操作映射地址如 0x60000000· 注意时序必须匹配外部器件手册地址/数据复用需配置---12. ISP — 串口烧录· 硬件BOOT01, BOOT10复位进入系统 Bootloader· 引脚USART1PA9 TX, PA10 RX需 USB 转 TTL· 软件STM32CubeProgrammer、FlyMcu 等· 注意烧录后 BOOT0 恢复 0使用 DTR/RTS 自动复位下载---13. SPL — 标准外设库老项目· 特点轻量、直接、无抽象层效率高但可移植性差· 常用函数GPIO_Init()、USART_SendData()、DMA_Init() 等· 对比 HALSPL 手动清中断标志HAL 用回调SPL 停止维护HAL 是未来--- 通用开发小贴士· 任何外设都需要先使能时钟。· 中断中不要用 HAL_Delay它依靠 SysTick 中断优先级问题可能导致死等。· 使用 DMA 时注意数据缓冲区生命周期不能是局部变量被释放。· 调试时善用 HAL_GetTick() 做超时避免死循环。· 低功耗下需在睡眠前配置唤醒源EXTI、定时器等。