找回密码
 立即注册
首页 业界区 安全 STM32学习笔记【大学生电子设计竞赛】【嵌入式】【标准 ...

STM32学习笔记【大学生电子设计竞赛】【嵌入式】【标准库学习】【HAL库学习】

向梦桐 2025-6-11 13:54:34
前言

此篇随笔是博主在打电赛(全国大学生电子设计竞赛)中写下的笔记汇总,备赛历程可见:视频
希望对小白有所帮助。
STM32入门

必备知识

概述

什么是 STM32:什么是STM32
STM32 能做什么:STM32能做什么
ST 官方官方网址:ST官网 (st.com)
ST 官方中文网站:STMCU中文官网
型号

STM32 怎么选型:STM32怎么选型
STM32 F1与F4的区别:【经验分享】ST公司STM32F4与STM32F1的区别
学习资源

1、STM32 学习
STM32 标准库开发:STM32入门教程-2023持续更新中
STM32 HAL库开发:【野火】STM32 HAL库开发实战指南 教学视频 手把手教学STM32全系列
2、Kicad
KiCad 是一款 PCB 设计软件,优点是开源、有许多插件可用、有许多快捷键方便操作
学习路径:KiCad | 6.0 | 简体中文 | Documentation | KiCad
PCB(Printed Circuit Board),中文名称为印制电路板,又称印刷线路板,是重要的电子部件,是电子元器件的支撑体,是电子元器件电气相互连接的载体。由于它是采用电子印刷术制作的,故被称为“印刷”电路板。
PCB 可以粗浅的理解为焊接死的面包板,目的是为了防止连线在搬运的过程中松动导致问题
3、部分项目学习
可以通过学习他人的部分项目,深入对开发过程的理解
智能小车入门:STM32智能小车教程-循迹-避障-蓝牙遥控-跟随-stm32f103c8t6-stm32最小系统-手把手入门教程
智能送药小车标准库:电赛培训-基于21年赛题-智能送药小车
智能送药小车HAL库:电赛“智能送药小车”【干货教程】STM32HAL库CubeMX+pid串级控制+OpenMV数字识别
智能送药小车:2021年电赛F题智能送药小车(国二)开源分享
其他智能送药小车:2021全国电赛真题(F)—— 智能送药小车
小车跟随行驶系统:2022电赛省一-小车跟随行驶系统(C题)
电磁炮:2019电赛----模拟电磁曲射炮
滚球:电赛入坑----2017年电赛国赛真题滚球控制系统
4、电机
电机快速初步了解:有刷电机与无刷电机的原理
电机学习:一个视频学完生活中的所有电机
电机驱动:一个视频了解生活中电机的驱动控制及调速方法
以上均为快速了解,作为科普简单留下感性印象,下面的视频能更完善的学习电机
视频地址:【野火】电机系列教学视频,基于STM32硬件(步进电机,直流有刷电机,直流无刷电机,舵机,永磁同步电机PMSM)PID闭环算法
在线文档:【野火】电机应用开发实战指南—基于STM32
5、PID算法
电机中的 野火视频 有讲解,此外还有一些资源
PID理论学习:从不懂到会用!PID从理论到实践~
6、相关模块学习
灰度传感器:一种双灰度传感器巡黑线方案
相关资料

总体

STM32F10xxx参考手册(中文)STM32F103C8T6/STM32F10xxx参考手册(中文)
数据手册:STM32F103C8T6/STM32F103x8B数据手册(中文)
Cortex-M3权威指南:STM32F103C8T6/Cortex-M3权威指南
野火F103 标准库开发指南:野火STM32库开发实战指南——基于野火MINI开发板
野火F103 HAL库开发指南:野火F103 HAL库开发指南
HC-05模块

概述:【常用模块】HC-05蓝牙串口通信模块使用详解(实例:手机蓝牙控制STM32单片机)
双机通信:两个HC-05蓝牙互相连接方法
所有AT指令:HC-05 嵌入式蓝牙串口通讯模块 AT 指令集
如果接收乱码,注意看波特率是否正确,默认值为9600!
STM32 接受蓝牙信息代码如下:
  1. #include "stm32f10x.h"
  2. void My_USART1_Init(void)
  3. {
  4.     GPIO_InitTypeDef GPIO_InitStrue;
  5.     USART_InitTypeDef USART_InitStrue;
  6.     NVIC_InitTypeDef NVIC_InitStrue;
  7.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);  //GPIO端口使能  
  8.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);  //串口端口使能  
  9.     GPIO_InitStrue.GPIO_Mode=GPIO_Mode_AF_PP;  // 模式: 复用输出
  10.     GPIO_InitStrue.GPIO_Pin=GPIO_Pin_9;  // 引脚: A9
  11.     GPIO_InitStrue.GPIO_Speed=GPIO_Speed_10MHz;  // 速度: 10MHz
  12.     GPIO_Init(GPIOA,&GPIO_InitStrue);
  13.     GPIO_InitStrue.GPIO_Mode=GPIO_Mode_IN_FLOATING;  // 模式: 浮空输入
  14.     GPIO_InitStrue.GPIO_Pin=GPIO_Pin_10;  // 引脚: A10
  15.     GPIO_InitStrue.GPIO_Speed=GPIO_Speed_10MHz;  // 速度: 10MHz
  16.     GPIO_Init(GPIOA,&GPIO_InitStrue);
  17.     USART_InitStrue.USART_BaudRate=9600;  // 波特率: 9600
  18.     USART_InitStrue.USART_HardwareFlowControl=USART_HardwareFlowControl_None;  // 硬件流控制: 无
  19.     USART_InitStrue.USART_Mode=USART_Mode_Tx|USART_Mode_Rx;  // 串口模式: 接受与发送
  20.     USART_InitStrue.USART_Parity=USART_Parity_No;  // 极性: 无
  21.     USART_InitStrue.USART_StopBits=USART_StopBits_1;  // 停止位: 1位
  22.     USART_InitStrue.USART_WordLength=USART_WordLength_8b;  // 数据位长度: 8位
  23.     USART_Init(USART1,&USART_InitStrue);
  24.     USART_Cmd(USART1,ENABLE);  //使能串口1
  25.     USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);  //开启接收中断
  26.     NVIC_InitStrue.NVIC_IRQChannel=USART1_IRQn;
  27.     NVIC_InitStrue.NVIC_IRQChannelCmd=ENABLE;
  28.     NVIC_InitStrue.NVIC_IRQChannelPreemptionPriority=1;  // 优先中断级别: 1
  29.     NVIC_InitStrue.NVIC_IRQChannelSubPriority=1;  // 普通中断级别: 1
  30.     NVIC_Init(&NVIC_InitStrue);
  31. }
  32. void USART1_IRQHandler(void)
  33. {
  34.     u8 res;
  35.     if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)
  36.     {
  37.         res= USART_ReceiveData(USART1);
  38.         USART_SendData(USART1,res);
  39.     }
  40. }
  41. int main(void)
  42. {
  43.     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  44.     My_USART1_Init();
  45.     while(1);
  46. }
复制代码
电机控制

电机驱动与编码器:TB6612与电机编码器
超声波跟随

HC-SR04模块:超声波原理及测距
超声波跟随小车:超声波跟随小车
调试

串口调试:USART-FlyMcu下载程序
配合蓝牙模块可实现无线烧录功能
红外遥控

介绍:STM32 红外遥控器详解
STM32标准库学习

stm32 固件库函数介绍

1、RCC
  1. void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState);
  2. void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);
  3. void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState);
复制代码
2、GPIO 相关函数
  1. void GPIO_AFIODeInit(void);                                                        // 复位AFIO外设
  2. void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);                // 锁定 GPIO 配置
  3. void GPIO_EventOutputConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);        // 配置AFIO事件输出功能
  4. void GPIO_EventOutputCmd(FunctionalState NewState);                                // 配置AFIO事件输出功能
  5. void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState);        // 进行引脚重映射
  6. void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);        // 配置AFIO的数据选择器
  7. void GPIO_ETH_MediaInterfaceConfig(uint32_t GPIO_ETH_MediaInterface);                // 与以太网有关
复制代码
3、EXTI 相关函数
  1. void EXTI_DeInit(void);                                        // 清除 EXTI 配置
  2. void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);        // 初始化 EXTI
  3. void EXTI_StructInit(EXTI_InitTypeDef* EXTI_InitStruct);// 给EXTI结构体赋默认值
  4. void EXTI_GenerateSWInterrupt(uint32_t EXTI_Line);        // 软件触发EXTI外部中断
  5. FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line);        // 获取标志位
  6. void EXTI_ClearFlag(uint32_t EXTI_Line);                // 清空标志位
  7. ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);                // 获取中断标志位
  8. void EXTI_ClearITPendingBit(uint32_t EXTI_Line);        // 清空中断标志位
复制代码
4、中断向量表
中断向量表位于启动文件(start/startup_stm32f10x.md.s)
  1. __Vectors       DCD     __initial_sp               ; Top of Stack
  2.                 DCD     Reset_Handler              ; Reset Handler
  3.                 DCD     NMI_Handler                ; NMI Handler
  4.                 DCD     HardFault_Handler          ; Hard Fault Handler
  5.                 DCD     MemManage_Handler          ; MPU Fault Handler
  6.                 DCD     BusFault_Handler           ; Bus Fault Handler
  7.                 DCD     UsageFault_Handler         ; Usage Fault Handler
  8.                 DCD     0                          ; Reserved
  9.                 DCD     0                          ; Reserved
  10.                 DCD     0                          ; Reserved
  11.                 DCD     0                          ; Reserved
  12.                 DCD     SVC_Handler                ; SVCall Handler
  13.                 DCD     DebugMon_Handler           ; Debug Monitor Handler
  14.                 DCD     0                          ; Reserved
  15.                 DCD     PendSV_Handler             ; PendSV Handler
  16.                 DCD     SysTick_Handler            ; SysTick Handler
  17.                 ; External Interrupts
  18.                 DCD     WWDG_IRQHandler            ; Window Watchdog
  19.                 DCD     PVD_IRQHandler             ; PVD through EXTI Line detect
  20.                 DCD     TAMPER_IRQHandler          ; Tamper
  21.                 DCD     RTC_IRQHandler             ; RTC
  22.                 DCD     FLASH_IRQHandler           ; Flash
  23.                 DCD     RCC_IRQHandler             ; RCC
  24.                 DCD     EXTI0_IRQHandler           ; EXTI Line 0
  25.                 DCD     EXTI1_IRQHandler           ; EXTI Line 1
  26.                 DCD     EXTI2_IRQHandler           ; EXTI Line 2
  27.                 DCD     EXTI3_IRQHandler           ; EXTI Line 3
  28.                 DCD     EXTI4_IRQHandler           ; EXTI Line 4
  29.                 DCD     DMA1_Channel1_IRQHandler   ; DMA1 Channel 1
  30.                 DCD     DMA1_Channel2_IRQHandler   ; DMA1 Channel 2
  31.                 DCD     DMA1_Channel3_IRQHandler   ; DMA1 Channel 3
  32.                 DCD     DMA1_Channel4_IRQHandler   ; DMA1 Channel 4
  33.                 DCD     DMA1_Channel5_IRQHandler   ; DMA1 Channel 5
  34.                 DCD     DMA1_Channel6_IRQHandler   ; DMA1 Channel 6
  35.                 DCD     DMA1_Channel7_IRQHandler   ; DMA1 Channel 7
  36.                 DCD     ADC1_2_IRQHandler          ; ADC1_2
  37.                 DCD     USB_HP_CAN1_TX_IRQHandler  ; USB High Priority or CAN1 TX
  38.                 DCD     USB_LP_CAN1_RX0_IRQHandler ; USB Low  Priority or CAN1 RX0
  39.                 DCD     CAN1_RX1_IRQHandler        ; CAN1 RX1
  40.                 DCD     CAN1_SCE_IRQHandler        ; CAN1 SCE
  41.                 DCD     EXTI9_5_IRQHandler         ; EXTI Line 9..5
  42.                 DCD     TIM1_BRK_IRQHandler        ; TIM1 Break
  43.                 DCD     TIM1_UP_IRQHandler         ; TIM1 Update
  44.                 DCD     TIM1_TRG_COM_IRQHandler    ; TIM1 Trigger and Commutation
  45.                 DCD     TIM1_CC_IRQHandler         ; TIM1 Capture Compare
  46.                 DCD     TIM2_IRQHandler            ; TIM2
  47.                 DCD     TIM3_IRQHandler            ; TIM3
  48.                 DCD     TIM4_IRQHandler            ; TIM4
  49.                 DCD     I2C1_EV_IRQHandler         ; I2C1 Event
  50.                 DCD     I2C1_ER_IRQHandler         ; I2C1 Error
  51.                 DCD     I2C2_EV_IRQHandler         ; I2C2 Event
  52.                 DCD     I2C2_ER_IRQHandler         ; I2C2 Error
  53.                 DCD     SPI1_IRQHandler            ; SPI1
  54.                 DCD     SPI2_IRQHandler            ; SPI2
  55.                 DCD     USART1_IRQHandler          ; USART1
  56.                 DCD     USART2_IRQHandler          ; USART2
  57.                 DCD     USART3_IRQHandler          ; USART3
  58.                 DCD     EXTI15_10_IRQHandler       ; EXTI Line 15..10
  59.                 DCD     RTCAlarm_IRQHandler        ; RTC Alarm through EXTI Line
  60.                 DCD     USBWakeUp_IRQHandler       ; USB Wakeup from suspend
  61. __Vectors_End
复制代码
5、NVIC 相关函数
  1. /* 注意:中断分支整个项目只能进行一次 */
  2. void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);                                // 中断分组
  3. void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);                                        // 初始化 NVIC
  4. void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset);                        // 设置中断向量表
  5. void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState NewState);                // 系统低功耗配置
复制代码
6、TIM 相关函数
基本函数:
  1. /* 初始化配置 */
  2. void TIM_DeInit(TIM_TypeDef* TIMx);                                                                // 恢复缺省配置
  3. void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);        // 时基单元初始化
  4. void TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);                        // 时基单元结构体变量赋默认值
  5. void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);                                        // 使能计数器
  6. void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);                // 使能中断输出信号
  7. void TIM_InternalClockConfig(TIM_TypeDef* TIMx);                                                // 选择内部时钟
  8. void TIM_ITRxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);                // 选择其他定时器的时钟
  9. void TIM_TIxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_TIxExternalCLKSource,
  10.                                 uint16_t TIM_ICPolarity, uint16_t ICFilter);                        // 选择TIx捕获通道的时钟
  11. void TIM_ETRClockMode1Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,
  12.                              uint16_t ExtTRGFilter);                                                // 选择 ETR 通过外部时钟模式1输入的时钟
  13. void TIM_ETRClockMode2Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler,
  14.                              uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter);                // 选择 ETR 通过外部时钟模式2输入的时钟
  15. void TIM_ETRConfig(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,
  16.                    uint16_t ExtTRGFilter);                                                        // 配置 ETR 预分频器、极性、滤波器等参数
  17. /* 更改参数 */
  18. void TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler, uint16_t TIM_PSCReloadMode);        // 更改预分频值
  19. void TIM_CounterModeConfig(TIM_TypeDef* TIMx, uint16_t TIM_CounterMode);                        // 改变计数模式
  20. void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);                                // 改变计数器的预装功能设置
  21. void TIM_SetCounter(TIM_TypeDef* TIMx, uint16_t Counter);                                        // 给计数器写入值
  22. void TIM_SetAutoreload(TIM_TypeDef* TIMx, uint16_t Autoreload);                                        // 给自动重装器写入值
  23. uint16_t TIM_GetCounter(TIM_TypeDef* TIMx);                                                        // 获取当前计数器的值
  24. uint16_t TIM_GetPrescaler(TIM_TypeDef* TIMx);                                                        // 获取当前预分频的值
  25. /* 获取与清除标志位 */
  26. FlagStatus TIM_GetFlagStatus(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);        // 获取标志位
  27. void TIM_ClearFlag(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);                // 清空标志位
  28. ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT);                // 获取中断标志位
  29. void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT);                // 清空中断标志位
复制代码
输出比较函数:
  1. void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);        // 配置输出比较模块
  2. void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);        // 配置输出比较模块
  3. void TIM_OC3Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);        // 配置输出比较模块
  4. void TIM_OC4Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);        // 配置输出比较模块
  5. void TIM_OCStructInit(TIM_OCInitTypeDef* TIM_OCInitStruct);                        // 输出结构体赋默认值
  6. void TIM_ForcedOC1Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);                // 配置强制输出模式,强制输出高电平或低电平
  7. void TIM_ForcedOC2Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);                // 配置强制输出模式,强制输出高电平或低电平
  8. void TIM_ForcedOC3Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);                // 配置强制输出模式,强制输出高电平或低电平
  9. void TIM_ForcedOC4Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);                // 配置强制输出模式,强制输出高电平或低电平
  10. void TIM_OC1PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);                // 配置 CCR 预装值功能
  11. void TIM_OC2PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);                // 配置 CCR 预装值功能
  12. void TIM_OC3PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);                // 配置 CCR 预装值功能
  13. void TIM_OC4PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);                // 配置 CCR 预装值功能
  14. void TIM_OC1FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);                        // 配置快速使能
  15. void TIM_OC2FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);                        // 配置快速使能
  16. void TIM_OC3FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);                        // 配置快速使能
  17. void TIM_OC4FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);                        // 配置快速使能
  18. void TIM_ClearOC1Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);                        // 外部事件时清除 REF 信号
  19. void TIM_ClearOC2Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);                        // 外部事件时清除 REF 信号
  20. void TIM_ClearOC3Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);                        // 外部事件时清除 REF 信号
  21. void TIM_ClearOC4Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);                        // 外部事件时清除 REF 信号
  22. void TIM_OC1PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);                // 设置输出比较的极性
  23. void TIM_OC1NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);        // 设置输出比较的极性(互补通道
  24. void TIM_OC2PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);                // 设置输出比较的极性
  25. void TIM_OC2NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);        // 设置输出比较的极性(互补通道
  26. void TIM_OC3PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);                // 设置输出比较的极性
  27. void TIM_OC3NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);        // 设置输出比较的极性(互补通道
  28. void TIM_OC4PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);                // 设置输出比较的极性
  29. void TIM_CCxCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCx);        // 修改输出使能
  30. void TIM_CCxNCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCxN);        // 修改输出使能
  31. void TIM_SelectOCxM(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_OCMode);// 修改输出比较模式
  32. void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1);                        // 更改 CCR 寄存器的值
  33. void TIM_SetCompare2(TIM_TypeDef* TIMx, uint16_t Compare2);                        // 更改 CCR 寄存器的值
  34. void TIM_SetCompare3(TIM_TypeDef* TIMx, uint16_t Compare3);                        // 更改 CCR 寄存器的值
  35. void TIM_SetCompare4(TIM_TypeDef* TIMx, uint16_t Compare4);                        // 更改 CCR 寄存器的值
复制代码
输入捕获函数:
  1. void TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);        // 输入捕获单元初始化
  2. void TIM_PWMIConfig(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);        // 初始化输入捕获单元,快速配置两个通道,配置为PWMI模式
  3. void TIM_ICStructInit(TIM_ICInitTypeDef* TIM_ICInitStruct);// 输入捕获结构体赋默认值
  4. void TIM_SelectInputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);        // 选择输入触发源(从模式的触发源)
  5. void TIM_SelectOutputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_TRGOSource);        // 选择输出触发源TRGO(主模式输出)
  6. void TIM_SelectSlaveMode(TIM_TypeDef* TIMx, uint16_t TIM_SlaveMode);        // 选择从模式
  7. void TIM_SetIC1Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);        // 配置1通道的分频器
  8. void TIM_SetIC2Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);        // 配置2通道的分频器
  9. void TIM_SetIC3Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);        // 配置3通道的分频器
  10. void TIM_SetIC4Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);        // 配置4通道的分频器
  11. void TIM_SetClockDivision(TIM_TypeDef* TIMx, uint16_t TIM_CKD);
  12. uint16_t TIM_GetCapture1(TIM_TypeDef* TIMx);        // 读取1通道的CCR
  13. uint16_t TIM_GetCapture2(TIM_TypeDef* TIMx);        // 读取2通道的CCR
  14. uint16_t TIM_GetCapture3(TIM_TypeDef* TIMx);        // 读取3通道的CCR
  15. uint16_t TIM_GetCapture4(TIM_TypeDef* TIMx);        // 读取4通道的CCR
复制代码
编码器接口函数:
  1. void TIM_EncoderInterfaceConfig(TIM_TypeDef* TIMx, uint16_t TIM_EncoderMode,
  2.                                 uint16_t TIM_IC1Polarity, uint16_t TIM_IC2Polarity);        // 编码器接口配置
复制代码
7、ADC相关函数
  1. void RCC_ADCCLKConfig(uint32_t RCC_PCLK2);        // 配置 ADC_CLK 分频器
复制代码
  1. void ADC_DeInit(ADC_TypeDef* ADCx);                                                        // 恢复缺省配置
  2. void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct);                        // 初始化 ADC
  3. void ADC_StructInit(ADC_InitTypeDef* ADC_InitStruct);                                        // ADC结构体初始化
  4. void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState);                                // 开启 ADC
  5. void ADC_DMACmd(ADC_TypeDef* ADCx, FunctionalState NewState);                                // 开启 DMA 输出信号
  6. void ADC_ITConfig(ADC_TypeDef* ADCx, uint16_t ADC_IT, FunctionalState NewState);        // 中断输出控制
  7. void ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);                // 软件触发 ADC
  8. FlagStatus ADC_GetSoftwareStartConvStatus(ADC_TypeDef* ADCx);                                // 获取软件开始转换状态(软件触发后立刻从1清零)(一般不用)
  9. void ADC_DiscModeChannelCountConfig(ADC_TypeDef* ADCx, uint8_t Number);                        // 配置每隔几个通道间断一次
  10. void ADC_DiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState);                        // 启用间断模式
  11. void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);        // ADC规则组通道配置
  12. void ADC_ExternalTrigConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);                // ADC 外部触发转换控制
  13. uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx);                                        // ADC 获取转换值
  14. uint32_t ADC_GetDualModeConversionValue(void);                                                // ADC 获取双模式转换值
  15. /* 校准相关配置 */
  16. void ADC_ResetCalibration(ADC_TypeDef* ADCx);                        // 复位校准
  17. FlagStatus ADC_GetResetCalibrationStatus(ADC_TypeDef* ADCx);        // 获取复位校准状态
  18. void ADC_StartCalibration(ADC_TypeDef* ADCx);                        // 开始校准
  19. FlagStatus ADC_GetCalibrationStatus(ADC_TypeDef* ADCx);                // 获取开始校准状态
  20. /* 注入组相关配置 */
  21. void ADC_AutoInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
  22. void ADC_InjectedDiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
  23. void ADC_ExternalTrigInjectedConvConfig(ADC_TypeDef* ADCx, uint32_t ADC_ExternalTrigInjecConv);
  24. void ADC_ExternalTrigInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
  25. void ADC_SoftwareStartInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
  26. FlagStatus ADC_GetSoftwareStartInjectedConvCmdStatus(ADC_TypeDef* ADCx);
  27. void ADC_InjectedChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);
  28. void ADC_InjectedSequencerLengthConfig(ADC_TypeDef* ADCx, uint8_t Length);
  29. void ADC_SetInjectedOffset(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel, uint16_t Offset);
  30. uint16_t ADC_GetInjectedConversionValue(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel);
  31. /* 模拟看门狗相关配置 */
  32. void ADC_AnalogWatchdogCmd(ADC_TypeDef* ADCx, uint32_t ADC_AnalogWatchdog);                                        // 是否启动模拟看门狗
  33. void ADC_AnalogWatchdogThresholdsConfig(ADC_TypeDef* ADCx, uint16_t HighThreshold, uint16_t LowThreshold);        // 配置高低阈值
  34. void ADC_AnalogWatchdogSingleChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel);                                // 配置看门通道
  35. void ADC_TempSensorVrefintCmd(FunctionalState NewState);                // ADC 温度传感器,内部电压控制
  36. FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx, uint8_t ADC_FLAG);        // 获取标志位状态
  37. void ADC_ClearFlag(ADC_TypeDef* ADCx, uint8_t ADC_FLAG);                // 清空标志位
  38. ITStatus ADC_GetITStatus(ADC_TypeDef* ADCx, uint16_t ADC_IT);                // 获取中断状态
  39. void ADC_ClearITPendingBit(ADC_TypeDef* ADCx, uint16_t ADC_IT);                // 清空中断挂起位
复制代码
8、DMA 相关函数
  1. void DMA_DeInit(DMA_Channel_TypeDef* DMAy_Channelx);                                                        // 恢复缺省配置
  2. void DMA_Init(DMA_Channel_TypeDef* DMAy_Channelx, DMA_InitTypeDef* DMA_InitStruct);                        // 初始化 DMA
  3. void DMA_StructInit(DMA_InitTypeDef* DMA_InitStruct);                                                        // DMA 结构体初始化
  4. void DMA_Cmd(DMA_Channel_TypeDef* DMAy_Channelx, FunctionalState NewState);                                // 使能 DMA
  5. void DMA_ITConfig(DMA_Channel_TypeDef* DMAy_Channelx, uint32_t DMA_IT, FunctionalState NewState);        // 中断输出使能
  6. void DMA_SetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx, uint16_t DataNumber);        // DMA 设置当前数据寄存器
  7. uint16_t DMA_GetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx);                        // DMA 获取当前数据寄存器
  8. FlagStatus DMA_GetFlagStatus(uint32_t DMAy_FLAG);        // 获取标志位状态
  9. void DMA_ClearFlag(uint32_t DMAy_FLAG);                        // 清空标志位
  10. ITStatus DMA_GetITStatus(uint32_t DMAy_IT);                // 获取中断状态
  11. void DMA_ClearITPendingBit(uint32_t DMAy_IT);                // 清空中断挂起位
复制代码
9、USART
  1. void USART_DeInit(USART_TypeDef* USARTx);                                                        // 恢复缺省配置
  2. void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct);                        // 初始化 USART
  3. void USART_StructInit(USART_InitTypeDef* USART_InitStruct);                                        // USART 结构体初始化
  4. void USART_ClockInit(USART_TypeDef* USARTx, USART_ClockInitTypeDef* USART_ClockInitStruct);        // 配置同步时钟输出
  5. void USART_ClockStructInit(USART_ClockInitTypeDef* USART_ClockInitStruct);                        // 同步时钟输出结构体初始化
  6. void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState);                                // 开启 USART
  7. void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState);        // 开启中断
  8. void USART_DMACmd(USART_TypeDef* USARTx, uint16_t USART_DMAReq, FunctionalState NewState);        // 开启USART到DMA的触发通道
  9. void USART_SendData(USART_TypeDef* USARTx, uint16_t Data);                // 发送数据
  10. uint16_t USART_ReceiveData(USART_TypeDef* USARTx);                        // 接收数据
  11. FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG);        // 获取标志位状态
  12. void USART_ClearFlag(USART_TypeDef* USARTx, uint16_t USART_FLAG);                // 清空标志位
  13. ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT);                // 获取中断状态
  14. void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT);                // 清空中断挂起位
复制代码
基础模块设计

GPIO

具体步骤

  • RCC 开启时钟
  • GPIO_Init() 初始化 GPIO
  • 使用输出或输入函数控制 GPIO
  1. GPIO_InitTypeDef GPIO_InitStructure;
  2. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  3. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;                //GPIO_Pin_15;
  4. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  5. GPIO_Init(GPIOA, &GPIO_InitStructure);
复制代码
EXTI 外部中断

1.png

具体步骤

  • RCC 开启时钟(GPIO、AFIO)
  • 配置 GPIO 为输入模式
  • 配置 AFIO,选择我们使用的一路GPIO
  • 配置 EXTI,选择边沿触发方式、触发响应方式(中断响应、事件响应)
  • 配置 NVIC,选择优先级
  1. void CountSensor_Init(void)
  2. {
  3.         /* RCC 开启时钟 */
  4.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
  5.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
  6.     /* 配置 GPIO  */
  7.     GPIO_InitTypeDef GPIO_InitStructure;
  8.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  9.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
  10.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  11.     GPIO_Init(GPIOB, &GPIO_InitStructure);
  12.     /* 配置 AFIO */
  13.     GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);
  14.     /* 配置 EXTI */
  15.     EXTI_InitTypeDef EXTI_InitStructure;
  16.     EXTI_InitStructure.EXTI_Line = EXTI_Line14;
  17.     EXTI_InitStructure.EXTI_LineCmd = ENABLE;
  18.     EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  19.     EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
  20.     EXTI_Init(&EXTI_InitStructure);
  21.     /* 配置 NVIC,中断分组 */
  22.     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  23.     /* 配置 NVIC,设置优先级 */
  24.     NVIC_InitTypeDef NVIC_InitStructure;
  25.     NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
  26.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  27.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  28.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  29.     NVIC_Init(&NVIC_InitStructure);
  30. }
  31. void EXTI15_10_IRQHandler(void)
  32. {
  33.         if (EXTI_GetITStatus(EXTI_Line14) == SET)
  34.         {
  35.                 EXTI_ClearITPendingBit(EXTI_Line14);
  36.         }
  37. }
复制代码
EXTI 与 NVIC 的时钟不需手动开启
Timer 定时中断

2.png


  • 具体步骤

    • RCC 开启时钟
    • 选择时基单元的时钟源(定时中断选择内部时钟源)
    • 配置时基单元
    • 配置输出中断控制,允许更新中断到 NVIC
    • 配置 NVIC,打开定时器中断通道,分配优先级
    • 运行控制

  1. void Timer_Init(void)
  2. {
  3.    
  4.         /* RCC 开启时钟 */
  5.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
  6.        
  7.         /* 选择时基单元的时钟源,内部时钟源 */
  8.         TIM_InternalClockConfig(TIM2);
  9.        
  10.         /* 配置时基单元 */
  11.         TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
  12.         TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
  13.         TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
  14.         TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1;
  15.         TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;
  16.         TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
  17.         TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
  18.        
  19.         TIM_ClearFlag(TIM2, TIM_FLAG_Update);
  20.         TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);                // 使能中断
  21.        
  22.         /* 配置 NVIC,中断分组 */
  23.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  24.        
  25.         /* 配置 NVIC,配置优先级 */
  26.         NVIC_InitTypeDef NVIC_InitStructure;
  27.         NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
  28.         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  29.         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
  30.         NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  31.         NVIC_Init(&NVIC_InitStructure);
  32.        
  33.         /* 启动计时器 */
  34.         TIM_Cmd(TIM2, ENABLE);
  35. }
  36. void TIM2_IRQHandler(void)
  37. {
  38.         if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
  39.         {
  40.                
  41.                 TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
  42.         }
  43. }
复制代码
PWM 输出

3.png


  • 具体步骤

    • RCC 开启时钟
    • 配置时基单元
    • 配置输出比较单元
    • 配置 GPIO
    • 运行控制,启动计数器

  1. #include "stm32f10x.h"                  // Device header
  2. void PWM_Init(void)
  3. {
  4.         /* RCC 开启时钟 */
  5.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
  6.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  7.         /* 配置 GPIO */
  8.         GPIO_InitTypeDef GPIO_InitStructure;
  9.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  10.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
  11.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  12.         GPIO_Init(GPIOA, &GPIO_InitStructure);
  13.         /* 选择时基单元的时钟源,内部时钟源 */
  14.         TIM_InternalClockConfig(TIM2);
  15.         /* 配置时基单元 */
  16.         TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
  17.         TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
  18.         TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
  19.         TIM_TimeBaseInitStructure.TIM_Period = 100 - 1;                //ARR
  20.         TIM_TimeBaseInitStructure.TIM_Prescaler = 36 - 1;                //PSC
  21.         TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
  22.         TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
  23.         /* 配置输出比较单元 */
  24.         TIM_OCInitTypeDef TIM_OCInitStructure;
  25.         TIM_OCStructInit(&TIM_OCInitStructure);
  26.         TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  27.         TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
  28.         TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  29.         TIM_OCInitStructure.TIM_Pulse = 0;                //CCR
  30.         TIM_OC3Init(TIM2, &TIM_OCInitStructure);
  31.         /* 运行控制,启动计数器 */
  32.         TIM_Cmd(TIM2, ENABLE);
  33. }
  34. // 设置占空比
  35. void PWM_SetCompare3(uint16_t Compare)
  36. {
  37.         TIM_SetCompare3(TIM2, Compare);
  38. }
  39. // 设置预分频值
  40. void PWM_SetPrescaler(uint16_t Prescaler)
  41. {
  42.         TIM_PrescalerConfig(TIM2, Prescaler, TIM_PSCReloadMode_Immediate);
  43. }
复制代码
IC 输入捕获

4.png

5.png


  • 具体步骤

    • RCC 开启时钟
    • GPIO 初始化为输入模式(上拉或浮空)
    • 配置时基单元
    • 配置输入捕获单元,包括滤波器、极性、直连通道还是交叉通道、分频器这些参数
    • 选择从模式的触发源(TI1FP1)
    • 选择触发后执行的操作(Reset操作)
    • 运行控制,启动计时器

  1. #include "stm32f10x.h"                  // Device header
  2. void IC_Init(void)
  3. {
  4.     /* RCC 开启时钟 */
  5.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
  6.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  7.        
  8.     /* GPIO 初始化为输入模式(上拉或浮空) */
  9.         GPIO_InitTypeDef GPIO_InitStructure;
  10.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  11.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
  12.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  13.         GPIO_Init(GPIOA, &GPIO_InitStructure);
  14.        
  15.     /* 选择时基单元的时钟源,内部时钟源 */
  16.         TIM_InternalClockConfig(TIM3);
  17.        
  18.     /* 配置时基单元 */
  19.         TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
  20.         TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
  21.         TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
  22.         TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1;                //ARR
  23.         TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1;                //PSC
  24.         TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
  25.         TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
  26.        
  27.     /* 配置输入捕获单元 */
  28.         TIM_ICInitTypeDef TIM_ICInitStructure;
  29.         TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
  30.         TIM_ICInitStructure.TIM_ICFilter = 0xF;
  31.         TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
  32.         TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
  33.         TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
  34.         TIM_ICInit(TIM3, &TIM_ICInitStructure);
  35.        
  36.     /* 选择从模式的触发源,选择触发后执行的操作 */
  37.         TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);
  38.         TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);
  39.        
  40.     /* 运行控制,启动计时器 */
  41.         TIM_Cmd(TIM3, ENABLE);
  42. }
  43. uint32_t IC_GetFreq(void)
  44. {
  45.         return 1000000 / (TIM_GetCapture1(TIM3) + 1);
  46. }
复制代码
PWMI 模式

6.png


  • 具体步骤

    • RCC 开启时钟
    • GPIO 初始化为输入模式(上拉或浮空)
    • 配置时基单元
    • 配置输入捕获单元
    • 选择从模式的触发源(TI1FP1)
    • 选择触发后执行的操作(Reset操作)
    • 运行控制,启动计时器

  1. #include "stm32f10x.h"                  // Device header
  2. void IC_Init(void)
  3. {
  4.         /* RCC 开启时钟 */
  5.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
  6.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  7.        
  8.     /* GPIO 初始化为输入模式(上拉或浮空) */
  9.         GPIO_InitTypeDef GPIO_InitStructure;
  10.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  11.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
  12.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  13.         GPIO_Init(GPIOA, &GPIO_InitStructure);
  14.        
  15.     /* 选择时基单元的时钟源,内部时钟源 */
  16.         TIM_InternalClockConfig(TIM3);
  17.        
  18.     /* 配置时基单元 */
  19.         TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
  20.         TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
  21.         TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
  22.         TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1;                //ARR
  23.         TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1;                //PSC
  24.         TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
  25.         TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
  26.        
  27.     /* 配置输入捕获单元 */
  28.         TIM_ICInitTypeDef TIM_ICInitStructure;
  29.         TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
  30.         TIM_ICInitStructure.TIM_ICFilter = 0xF;
  31.         TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
  32.         TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
  33.         TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
  34.         TIM_PWMIConfig(TIM3, &TIM_ICInitStructure);
  35.         /* 选择从模式的触发源,选择触发后执行的操作 */
  36.         TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);
  37.         TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);
  38.        
  39.     /* 运行控制,启动计时器 */
  40.         TIM_Cmd(TIM3, ENABLE);
  41. }
  42. uint32_t IC_GetFreq(void)
  43. {
  44.         return 1000000 / (TIM_GetCapture1(TIM3) + 1);
  45. }
  46. uint32_t IC_GetDuty(void)
  47. {
  48.         return (TIM_GetCapture2(TIM3) + 1) * 100 / (TIM_GetCapture1(TIM3) + 1);
  49. }
复制代码
编码器接口测速

7.png


  • 具体步骤

    • RCC 开启时钟
    • GPIO 初始化为输入模式
    • 配置时基单元
    • 配置输入捕获单元,包括滤波器、极性参数
    • 配置编码器接口模式
    • 运行控制,启动计时器

  1. #include "stm32f10x.h"                  // Device header
  2. void Encoder_Init(void)
  3. {
  4.         /* RCC 开启时钟 */
  5.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
  6.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  7.        
  8.     /* GPIO 初始化为输入模式 */
  9.         GPIO_InitTypeDef GPIO_InitStructure;
  10.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  11.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
  12.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  13.         GPIO_Init(GPIOA, &GPIO_InitStructure);
  14.        
  15.     /* 配置时基单元 */
  16.         TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
  17.         TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
  18.         TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;        // 没用
  19.         TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1;                //ARR
  20.         TIM_TimeBaseInitStructure.TIM_Prescaler = 1 - 1;                //PSC
  21.         TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
  22.         TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
  23.        
  24.     /* 配置输入捕获单元,包括滤波器、极性参数 */
  25.         TIM_ICInitTypeDef TIM_ICInitStructure;
  26.         TIM_ICStructInit(&TIM_ICInitStructure);
  27.         TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
  28.         TIM_ICInitStructure.TIM_ICFilter = 0xF;
  29.         TIM_ICInit(TIM3, &TIM_ICInitStructure);
  30.         TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
  31.         TIM_ICInitStructure.TIM_ICFilter = 0xF;
  32.         TIM_ICInit(TIM3, &TIM_ICInitStructure);
  33.        
  34.     /* 配置编码器接口模式 */
  35.         TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
  36.        
  37.     /* 运行控制,启动计时器 */
  38.         TIM_Cmd(TIM3, ENABLE);
  39. }
  40. int16_t Encoder_Get(void)
  41. {
  42.         int16_t Temp;
  43.         Temp = TIM_GetCounter(TIM3);
  44.         TIM_SetCounter(TIM3, 0);
  45.         return Temp;
  46. }
复制代码
ADC

8.png


  • 具体步骤

    • RCC 开启时钟(ADC和GPIO),配置 ADC_CLK 分频器
    • GPIO 配置为模拟输入模式
    • 配置多路开关
    • 配置 ADC 转换器
    • 配置看门狗(可选)
    • 开启中断,配置 NVIC(可选)
    • 开启 ADC
    • 对 ADC 进行校准(建议)

  1. #include "stm32f10x.h"                  // Device header
  2. void AD_Init(void)
  3. {
  4.     /* RCC 开启时钟 */
  5.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
  6.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  7.        
  8.     /* 配置 ADC_CLK 分频器 */
  9.         RCC_ADCCLKConfig(RCC_PCLK2_Div6);
  10.        
  11.     /* GPIO 配置为模拟输入模式 */
  12.         GPIO_InitTypeDef GPIO_InitStructure;
  13.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
  14.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
  15.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  16.         GPIO_Init(GPIOA, &GPIO_InitStructure);
  17.        
  18.     /* 配置多路开关 */
  19.         ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);
  20.        
  21.     /* 配置 ADC 转换器 */
  22.         ADC_InitTypeDef ADC_InitStructure;
  23.         ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
  24.         ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  25.         ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
  26.         ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
  27.         ADC_InitStructure.ADC_ScanConvMode = DISABLE;
  28.         ADC_InitStructure.ADC_NbrOfChannel = 1;
  29.         ADC_Init(ADC1, &ADC_InitStructure);
  30.        
  31.     /* 开启 ADC */
  32.         ADC_Cmd(ADC1, ENABLE);
  33.        
  34.     /* 对 ADC 进行校准 */
  35.         ADC_ResetCalibration(ADC1);                // 复位校准
  36.         while (ADC_GetResetCalibrationStatus(ADC1) == SET);        // 等待复位校准完成
  37.         ADC_StartCalibration(ADC1);                // 开始校准
  38.         while (ADC_GetCalibrationStatus(ADC1) == SET);                // 等待校准完成
  39. }
  40. uint16_t AD_GetValue(void)
  41. {
  42.         ADC_SoftwareStartConvCmd(ADC1, ENABLE);                        // 软件触发转换
  43.         while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);        // 等待转换完成
  44.         return ADC_GetConversionValue(ADC1);                        // 读取 ADC 转换结果
  45. }
复制代码
DMA

9.png


  • 具体步骤

    • RCC 开启时钟
    • 初始化 DMA(包括外设和存储器的各个数据、方向、传输计数器、是否需要自动重装、选择触发源、通道优先级)
    • 若为硬件触发,开启对应 DMA 输出(可选)
    • 开启中断输出,配置 NVIC(可选)
    • 开启 DMA

改变传输寄存器时需先失能,写入值后再使能
  1. #include "stm32f10x.h"                  // Device header
  2. uint16_t MyDMA_Size;
  3. void MyDMA_Init(uint32_t AddrA, uint32_t AddrB, uint16_t Size)
  4. {
  5.     MyDMA_Size = Size;
  6.        
  7.         /* RCC 开启时钟 */
  8.     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
  9.        
  10.         /* 初始化 DMA */
  11.     DMA_InitTypeDef DMA_InitStructure;
  12.         DMA_InitStructure.DMA_PeripheralBaseAddr = AddrA;                        // 外设起始地址
  13.         DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;        // 外设数据宽度
  14.         DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;                // 外设是否自增
  15.         DMA_InitStructure.DMA_MemoryBaseAddr = AddrB;;                                // 存储器起始地址
  16.         DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;;        // 存储器数据宽度
  17.         DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;;                // 存储器是否自增
  18.         DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;        // 传输方向
  19.         DMA_InitStructure.DMA_BufferSize = Size;                // 缓冲区大小,即传输寄存器
  20.         DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                // 传输模式,即是否使用自动重装
  21.         DMA_InitStructure.DMA_M2M = DMA_M2M_Enable;                // 选择是否存储器到存储器,即选择硬件触发或软件触发
  22.         DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;        // 优先级
  23.         DMA_Init(DMA1_Channel1, &DMA_InitStructure);
  24.        
  25.         /* 开启 DMA */
  26.     DMA_Cmd(DMA1_Channel1, DISABLE);
  27. }
  28. void MyDMA_Transfer(void)
  29. {
  30.         /* DMA失能、设置当前数据寄存器、DMA使能 */
  31.         DMA_Cmd(DMA1_Channel1, DISABLE);
  32.         DMA_SetCurrDataCounter(DMA1_Channel1, MyDMA_Size);
  33.         DMA_Cmd(DMA1_Channel1, ENABLE);
  34.        
  35.         /* 等待转运完成、清除转运完成标志位 */
  36.         while (DMA_GetFlagStatus(DMA1_FLAG_TC1) == RESET);
  37.         DMA_ClearFlag(DMA1_FLAG_TC1);
  38. }
复制代码
USART 串口

10.png


  • 具体步骤

    • RCC 开启时钟(USART和GPIO)
    • GPIO设置(TX配置为复用输出、RX配置为输入)
    • 配置USART
    • 开启中断、配置NVIC(可选)
    • 开启USART


  • 发送数据
初始化函数:
  1. #include "stm32f10x.h"                  // Device header
  2. #include <stdio.h>
  3. #include <stdarg.h>
  4. void Serial_Init(void)
  5. {
  6.         /* RCC 开启时钟 */
  7.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
  8.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  9.        
  10.         /* GPIO设置 */
  11.         GPIO_InitTypeDef GPIO_InitStructure;
  12.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                // 复用推挽输出
  13.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  14.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  15.         GPIO_Init(GPIOA, &GPIO_InitStructure);
  16.        
  17.         /* 配置USART */
  18.         USART_InitTypeDef USART_InitStructure;
  19.         USART_InitStructure.USART_BaudRate = 9600;                                                // 波特率
  20.         USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;                // 硬件流控制
  21.         USART_InitStructure.USART_Mode = USART_Mode_Tx;                                                // 串口模式
  22.         USART_InitStructure.USART_Parity = USART_Parity_No;                                        // 校验位
  23.         USART_InitStructure.USART_StopBits = USART_StopBits_1;                                        // 停止位
  24.         USART_InitStructure.USART_WordLength = USART_WordLength_8b;                                // 字长
  25.         USART_Init(USART1, &USART_InitStructure);
  26.        
  27.         /* 开启USART */
  28.         USART_Cmd(USART1, ENABLE);
  29. }
复制代码
相关函数封装:
  1. /**
  2.   * @brief  发送一个字节
  3.   * @param  Byte: 要发送的字节数据
  4.   * @retval None
  5.   */
  6. void Serial_SendByte(uint8_t Byte)
  7. {
  8.         USART_SendData(USART1, Byte);
  9.         while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
  10. }
  11. /**
  12.   * @brief  发送一个数组
  13.   * @param  Array: 数组的首地址,必须为 uint8_t 类型的数组
  14.   * @param  Length: 数组的长度
  15.   *   This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
  16.   * @retval None
  17.   */
  18. void Serial_SendArray(uint8_t *Array, uint16_t Length)
  19. {
  20.         uint16_t i;
  21.         for (i = 0; i < Length; i ++)
  22.         {
  23.                 Serial_SendByte(Array[i]);
  24.         }
  25. }
  26. /**
  27.   * @brief  发送字符串
  28.   * @param  String: 字符串的首地址
  29.   * @retval None
  30.   */
  31. void Serial_SendString(char *String)
  32. {
  33.         uint8_t i;
  34.         for (i = 0; String[i] != '\0'; i ++)
  35.         {
  36.                 Serial_SendByte(String[i]);
  37.         }
  38. }
  39. /**
  40.   * @brief  指数函数,即X的Y次方
  41.   * @param  X:底数
  42.   * @param  Y:指数
  43.   * @retval None
  44.   */
  45. uint32_t Serial_Pow(uint32_t X, uint32_t Y)
  46. {
  47.         uint32_t Result = 1;
  48.         while (Y --)
  49.         {
  50.                 Result *= X;        // 1 乘以X Y次
  51.         }
  52.         return Result;
  53. }
  54. /**
  55.   * @brief  发送数字
  56.   *         本质将数字手动转为字符串然后发送
  57.   * @param  Number
  58.   * @param  Length
  59.   * @retval None
  60.   */
  61. void Serial_SendNumber(uint32_t Number, uint8_t Length)
  62. {
  63.         uint8_t i;
  64.         for (i = 0; i < Length; i ++)
  65.         {
  66.                 Serial_SendByte(Number / Serial_Pow(10, Length - i - 1) % 10 + '0');        // 发送Number的每一位(高位先行)'0'->偏移
  67.         }
  68. }
  69. /**
  70.   * @brief  fputc重定向
  71.   * @param  
  72.   * @retval
  73.   */
  74. int fputc(int ch, FILE *f)
  75. {
  76.         Serial_SendByte(ch);
  77.         return ch;
  78. }
  79. /**
  80.   * @brief  模拟printf重写打印字符串函数
  81.   * @retval None
  82.   */
  83. void Serial_Printf(char *format, ...)
  84. {
  85.         char String[100];
  86.         va_list arg;
  87.         va_start(arg, format);
  88.         vsprintf(String, format, arg);
  89.         va_end(arg);
  90.         Serial_SendString(String);
  91. }
复制代码
printf 重定向方法3:
  1.         char String[100];
  2.         sprintf(String, "\r\nNum3=%d", 333);
  3.         Serial_SendString(String);
复制代码

  • 接收数据
  1. #include "stm32f10x.h"                  // Device header
  2. #include <stdio.h>
  3. #include <stdarg.h>
  4. uint8_t Serial_RxData;
  5. uint8_t Serial_RxFlag;
  6. void Serial_Init(void)
  7. {
  8.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
  9.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  10.        
  11.         GPIO_InitTypeDef GPIO_InitStructure;
  12.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;        // 上拉输入
  13.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  14.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  15.         GPIO_Init(GPIOA, &GPIO_InitStructure);
  16.        
  17.         USART_InitTypeDef USART_InitStructure;
  18.         USART_InitStructure.USART_BaudRate = 9600;
  19.         USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  20.         USART_InitStructure.USART_Mode = USART_Mode_Rx;
  21.         USART_InitStructure.USART_Parity = USART_Parity_No;
  22.         USART_InitStructure.USART_StopBits = USART_StopBits_1;
  23.         USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  24.         USART_Init(USART1, &USART_InitStructure);
  25.        
  26.         /* 开启中断 */
  27.         USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
  28.        
  29.         /* NVIC 分组 */
  30.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  31.        
  32.         /* NVIC 配置 */
  33.         NVIC_InitTypeDef NVIC_InitStructure;
  34.         NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
  35.         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  36.         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  37.         NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  38.         NVIC_Init(&NVIC_InitStructure);
  39.        
  40.         USART_Cmd(USART1, ENABLE);
  41. }
  42. /**
  43.   * @brief  获取标志位
  44.   * @param  Nonw
  45.   * @retval None
  46.   */
  47. uint8_t Serial_GetRxFlag(void)
  48. {
  49.         if (Serial_RxFlag == 1)
  50.         {
  51.                 Serial_RxFlag = 0;
  52.                 return 1;
  53.         }
  54.         return 0;
  55. }
  56. /**
  57.   * @brief  获取串口数据
  58.   * @param  None
  59.   * @retval None
  60.   */
  61. uint8_t Serial_GetRxData(void)
  62. {
  63.         return Serial_RxData;
  64. }
  65. /**
  66.   * @brief  串口1中断函数
  67.   * @param  None
  68.   * @retval None
  69.   */
  70. void USART1_IRQHandler(void)
  71. {
  72.         if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
  73.         {
  74.                 Serial_RxData = USART_ReceiveData(USART1);        // 获取数据
  75.                 Serial_RxFlag = 1;                                // 标志位置1
  76.                 USART_ClearITPendingBit(USART1, USART_IT_RXNE);        // 清空终端挂起位
  77.         }
  78. }
复制代码

  • 收发 HEX 数据包
  1. /**
  2.   * @brief  发送数据包
  3.   * @param  None
  4.   * @retval None
  5.   */
  6. void Serial_SendPacket(void)
  7. {
  8.         Serial_SendByte(0xFF);
  9.         Serial_SendArray(Serial_TxPacket, 4);
  10.         Serial_SendByte(0xFE);
  11. }
  12. /**
  13.   * @brief  中断程序中接收数据包
  14.   * @param  None
  15.   * @retval None
  16.   */
  17. void USART1_IRQHandler(void)
  18. {
  19.         static uint8_t RxState = 0;                // 当前状态
  20.         static uint8_t pRxPacket = 0;                // 接收到第几个数据
  21.         if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
  22.         {
  23.                 uint8_t RxData = USART_ReceiveData(USART1);
  24.                
  25.                 if (RxState == 0)                // 状态0:包头
  26.                 {
  27.                         if (RxData == 0xFF)
  28.                         {
  29.                                 RxState = 1;        // 进入状态1
  30.                                 pRxPacket = 0;        // 接收数据指针置零
  31.                         }
  32.                 }
  33.                 else if (RxState == 1)                                // 状态1:数据
  34.                 {
  35.                         Serial_RxPacket[pRxPacket] = RxData;        // 接收数据
  36.                         pRxPacket ++;                                // 指针后移
  37.                         if (pRxPacket >= 4)
  38.                         {
  39.                                 RxState = 2;                // 进入状态3
  40.                         }
  41.                 }
  42.                 else if (RxState == 2)                        // 状态2:包尾
  43.                 {
  44.                         if (RxData == 0xFE)
  45.                         {
  46.                                 RxState = 0;                // 重新进入状态0
  47.                                 Serial_RxFlag = 1;        // 置接收标志位为1
  48.                         }
  49.                 }
  50.                
  51.                 USART_ClearITPendingBit(USART1, USART_IT_RXNE);
  52.         }
  53. }
复制代码
STM32 CubeMX及HAL库学习

入门

在拥有固件库开发的基础上,观看 Z小旋的博客-CSDN博客,能够快速上手 HAL 库。
下面对大佬的博客进行排序,方便查找。
这里推荐: 【STM32】_Z小旋的博客-CSDN博客
【STM32】HAL库 STM32CubeMX教程一---安装教程
【STM32】HAL库 STM32CubeMX教程二---基本使用(新建工程点亮LED灯)
【STM32】HAL库 STM32CubeMX教程三---外部中断(HAL库GPIO讲解)_hal_gpio_exti_callback
【STM32】HAL库 STM32CubeMX教程四---UART串口通信详解_hal_uart_transmit
【STM32】HAL库 STM32CubeMX教程五---看门狗(独立看门狗,窗口看门狗)_stm32看门狗
【STM32】HAL库 STM32CubeMX教程六---定时器中断_hal_tim_irqhandler
【STM32】HAL库 STM32CubeMX教程七---PWM输出(呼吸灯)_stm32 hal pwm输出
【STM32】HAL库 STM32CubeMX教程八---定时器输入捕获_hal_tim_readcapturedvalue
【STM32】HAL库 STM32CubeMX教程九---ADC_stm32cubemx adc
【STM32】HAL库 STM32CubeMX教程十---DAC
【STM32】HAL库 STM32CubeMX教程十一---DMA (串口DMA发送接收)_cubemx spi dma
【STM32】HAL库 STM32CubeMX教程十二---IIC(读取AT24C02 )_cubemx iic
【STM32】HAL库 STM32CubeMX教程十三---RTC时钟_stm32 hal库的时钟
【STM32】HAL库 STM32CubeMX教程十四---SPI_cubemx spi
【STM32】HAL库 STM32CubeMX教程十五---FMC-SDRAM(一)_stm32cubemx fmc
【STM32】HAL库 STM32CubeMX教程十五---FMC-SDRAM(二)
提高

1、串口
初步写自己的具体逻辑,主要是串口,可以观看 STM32系列视频(CubeMX+MDK5+HAL库+库函数一站式学习) 进行学习。
这个视频主要是标准库和 HAL库 函数都有,面向电源题类的。
2、PID控制
编码器测速:【STM32】使用HAL库进行电机测速,原理、代码、滤波
PID速度环:【STM32】使用HAL库进行电机速度环PID控制,代码+调参
PID位置环:【STM32】使用HAL库进行电机PID位置环控制,代码+调参
3、PID调参
VOFA+调参:使用VOFA+上位机进行PID调参(附下位机代码)
VOFA+官网:VOFA+
4、江科大OLED移植
基于HAL库的stm32的OLED显示屏显示:基于HAL库的stm32的OLED显示屏显示(模拟I2C,四脚,0.96寸)
其他

大佬的笔记整理:【单片机学习笔记】上传一整年的自学电子笔记,互相交流,共同进步
电赛国一大佬的方案:2021年全国大学生电子设计大赛F题——智能送药小车,全方位解决方案+程序代码(详细注释)山东赛区国奖
STM32中的预编译

#define

1、不带参宏定义
#define,宏定义命令,它也是C语言预处理命令的一种。
所谓宏定义,就是用一个标识符来表示一个字符串,如果在后面的代码中出现了该标识符,那么就全部替换成指定的字符串。
例如
  1. #define N 100
复制代码
在编译过程中遇到 N 时,会直接替换为 100。
2、带参公定义
宏定义可以携带参数。
例如
  1. #define M(y) y*y+3*y  //宏定义
  2. int main()
  3. {
  4.     // 以下命令解释为 5*5+3*5
  5.     int a = M(5);
  6. }
复制代码
3、防止头文件重复包含
如下所示
  1. #ifndef __HEADER_One_H__ // 意思是:宏开始行,如果还没有定义 __HEADER_One_H__ 则 进入,否则退出
  2. #define __HEADER_One_H__ // 定义 __HEADER_One_H__
  3. // header1.h 头文件内容
  4. #endif // 宏结束行
复制代码
模版:
  1. #ifndef __x_H__
  2. #define __x_H__
  3. #endif // 宏结束行
复制代码
#if 与 #if defined

1、#if
#if的意思是如果宏条件符合,编译器就编译这段代码,否则,编译器就忽略这段代码而不编译,如
  1. #define  A 0  // 把A定义为0
  2. #if (A > 1)
  3.          printf("A > 1");  // 编译器没有编译该语句,该语句不生成汇编代码
  4. #elif (A == 1)
  5.          printf("A == 1"); // 编译器没有编译该语句,该语句不生成汇编代码
  6. #else
  7.          printf("A < 1");   // 编译器编译了这段代码,且生成了汇编代码,执行该语句
  8. #endif
复制代码
模版:
  1. #if x
  2. #else
  3. #endif
复制代码
  1. #if x
  2. #elif x
  3. #else
  4. #endif
复制代码
2、#if defined
  1. #if defined (x)
  2.     ...code...
  3. #endif
复制代码
这个#if defined它不管里面的 x 的逻辑是“真”还是“假”。它只管这个程序的前面的宏定义里面有没有定义 x 这个宏,如果定义了 x 这个宏,那么,编译器会编译中间的 …code…,否则会直接忽视中间的 …code… 代码。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册