二、STM32F103C8T6-定时器
STM32F103C8T6 定时器概述
STM32F103C8T6 作为一款广泛使用的微控制器,内置多个定时器,能够支持多种计时和控制功能,如精确延时、脉冲宽度调制(PWM)、捕获比较(Capture/Compare)、输入捕获 和 输出比较 等。这些功能在电机控制、信号测量、周期性事件触发等应用中非常常用。
STM32F103C8T6 的定时器分类
一、高级定时器(TIM1):高级定时器不仅具有基本的定时和计数功能,还支持高级功能,如死区控制(dead-time generation)、互补输出、刹车功能和自动重装载预加载(ARR preload),这些功能使其特别适合用于复杂的电机控制和电源管理应用。
- 提供增强的功能,特别适合 PWM 控制、电机控制。
- 支持多通道 PWM 输出,具有丰富的捕获/比较功能。
高级定时器互补输出:互补输出是通过定时器的多个输出通道生成一对相反的 PWM 信号,即一个信号为高电平时,另一个信号为低电平。互补输出常用于控制 全桥电路 或 半桥电路,从而驱动 MOSFET 或 IGBT 等开关器件。
互补输出的基本原理:
主通道(主输出):高级定时器生成的 PWM 信号,用于驱动负载或开关。
互补通道(互补输出):与主通道相反的信号(即互补信号),用于驱动相反极性的开关器件,确保系统中不会同时导通同一条导通路径的两个开关,避免短路。
死区时间(Dead Time):为了避免主通道和互补通道的开关在某一瞬间同时导通(造成短路),可以引入死区时间。死区时间是指主通道关闭后,互补通道延迟一定时间才开始导通,反之亦然。这是电机控制和开关电源中非常关键的一项保护功能。

互补输出控制电机正反转例子图:(H桥)

扩展:IGBT与MOSFET对比:

二、通用定时器
在 STM32F103C8T6 微控制器中,通用定时器提供了丰富的功能,适合于基本计时、输入捕获、输出比较、PWM 输出等多种应用。STM32F103C8T6 配备了多个通用定时器,包括 TIM2、TIM3、TIM4。
- TIM2:32 位通用定时器,支持基本定时、中断、捕获/比较、PWM 输出等功能。
- TIM3、TIM4:16 位通用定时器,支持类似功能,主要区别在于计数器的位宽较小。

应用实例:
1、定时器中断
使用定时器2(TIM2),每隔1秒产生一次中断,时钟频率为72MHZ
void TIM2_Init(void)
{
// 开启 TIM2 时钟
__HAL_RCC_TIM2_CLK_ENABLE();
TIM_HandleTypeDef TimHandle = {0};
TimHandle.Instance = TIM2;
// 预分频器配置,计数频率为 10 kHz
TimHandle.Init.Prescaler = 7200 - 1; // 72 MHz / 7200 = 10 kHz
// 自动重装载值,1 秒定时
TimHandle.Init.Period = 10000 - 1; // 10 kHz / 10000 = 1 秒
TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
HAL_TIM_Base_Init(&TimHandle);
// 启用定时器中断
HAL_TIM_Base_Start_IT(&TimHandle);
}
// 定时器中断回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM2)
{
// 每 1 秒触发一次中断
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); // 切换 GPIO 状态
}
}
代码中,TIM2 配置为每秒产生一次中断,计数频率为 10 kHz,周期为 1 秒。每次中断发生时,GPIO 引脚状态发生翻转。
定时器中断回调函数:用于处理定时器产生的中断事件。STM32 使用 HAL 库时,定时器中断发生后,HAL_TIM_PeriodElapsedCallback() 函数会被自动调用,这是一个通用的定时器中断回调函数,负责处理定时器的计时溢出或更新事件。
(参数 htim:传入的 TIM_HandleTypeDef 结构体用于标识是哪一个定时器产生了中断)
2、使用TIM3生成PWM信号
假设我们使用TIM3生成一个1KHZ的PWM信号,占空比50%
void TIM3_PWM_Init(void)
{
// 开启 TIM3 时钟
__HAL_RCC_TIM3_CLK_ENABLE();
TIM_HandleTypeDef TimHandle = {0};
TIM_OC_InitTypeDef sConfigOC = {0}; //输出比较的结构体,任务句柄
// 基本时基配置
TimHandle.Instance = TIM3;
TimHandle.Init.Prescaler = 72 - 1; // 预分频器,计数频率 1 MHz
TimHandle.Init.Period = 1000 - 1; // 自动重装载值,1 kHz PWM 频率
TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
HAL_TIM_PWM_Init(&TimHandle); // 初始化 PWM
// 配置 PWM 输出通道
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 500; // 50% 占空比
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
HAL_TIM_PWM_ConfigChannel(&TimHandle, &sConfigOC, TIM_CHANNEL_1);
// 启动 PWM 输出
HAL_TIM_PWM_Start(&TimHandle, TIM_CHANNEL_1);
}
3、使用 TIM4 捕获输入信号
假设我们使用 TIM4 捕获输入信号的上升沿,并测量输入信号的频率。
void TIM4_InputCapture_Init(void)
{
// 开启 TIM4 时钟
__HAL_RCC_TIM4_CLK_ENABLE();
TIM_HandleTypeDef TimHandle = {0};
TIM_IC_InitTypeDef sConfigIC = {0};
// 基本时基配置
TimHandle.Instance = TIM4;
TimHandle.Init.Prescaler = 72 - 1; // 计数频率为 1 MHz
TimHandle.Init.Period = 0xFFFF; // 最大计数值
TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
HAL_TIM_IC_Init(&TimHandle);
// 输入捕获配置
sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING; //上升沿捕获
sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
sConfigIC.ICFilter = 0;
HAL_TIM_IC_ConfigChannel(&TimHandle, &sConfigIC, TIM_CHANNEL_1);
// 启动输入捕获
HAL_TIM_IC_Start_IT(&TimHandle, TIM_CHANNEL_1);
}
输入捕获,计算输入信号周期
#include "stm32f1xx_hal.h"
// 定义全局变量
uint32_t capture1 = 0;
uint32_t capture2 = 0;
uint32_t difference = 0;
uint32_t frequency = 0;
// 初始化 TIM3 的输入捕获功能
void TIM3_InputCapture_Init(void)
{
__HAL_RCC_TIM3_CLK_ENABLE();
TIM_HandleTypeDef TimHandle = {0};
TIM_IC_InitTypeDef sConfigIC = {0};
TimHandle.Instance = TIM3;
TimHandle.Init.Prescaler = 72 - 1; // 1 MHz 计数频率
TimHandle.Init.Period = 0xFFFF;
TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
HAL_TIM_IC_Init(&TimHandle);
sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
sConfigIC.ICFilter = 0;
HAL_TIM_IC_ConfigChannel(&TimHandle, &sConfigIC, TIM_CHANNEL_1);
HAL_TIM_IC_Start_IT(&TimHandle, TIM_CHANNEL_1);
}
// 定时器输入捕获回调函数
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM3 && htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
{
if (capture1 == 0)
{
capture1 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
}
else
{
capture2 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
if (capture2 > capture1)
{
difference = capture2 - capture1;
}
else
{
difference = (0xFFFF - capture1) + capture2 + 1;
}
frequency = 1000000 / difference;
capture1 = 0;
}
}
}
void TIM3_NVIC_Config(void)
{
HAL_NVIC_SetPriority(TIM3_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM3_IRQn);
}
// 主函数
int main(void)
{
HAL_Init();
TIM3_InputCapture_Init();
TIM3_NVIC_Config();
while(1)
{
// 可以在此处监控 frequency 变量
}
}
二、STM32F103C8T6-定时器的更多相关文章
- 【Visual C++】游戏编程学习笔记之二:定时器的使用
本系列文章由@二货梦想家张程所写,转载请注明出处. 本文章链接:http://blog.csdn.net/terence1212/article/details/44195831 作者:ZeeCode ...
- 从零开始学 Web 之 BOM(二)定时器
大家好,这里是「 从零开始学 Web 系列教程 」,并在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公众号:Web前端之巅 博客园:ht ...
- STM32 定时器详细篇(基于HAL库)
l 16位的向上.向下.向上/向下(中心对齐)计数模式,支持自动重装载 l 16位的预分频器 l 每个定时器都有多个独立通道,每个通道可用于 * 输入捕获 * 输出比较 * PWM输出 * ...
- jmeter(七)定时器
知识来源有点复杂,其他测试工作者的博客,百度百科,搜集的电子文档,个人理解等等,限于水平和理解能力,可能有些内容有错误的地方... jmeter提供了很多元件,帮助我们更好的完成各种场景的性能测试,其 ...
- JavaScript定时器原理分析
.header { cursor: pointer } p { margin: 3px 6px } th { background: lightblue; width: 20% } table { t ...
- μC/OS-Ⅲ系统的时间管理函数和定时器
一.时间管理函数 μC/OS-Ⅲ系统提供一些列时间管理服务函数: 1.OSTimeDly():任务延时n个时钟节拍. 2.OSTimeDlyHMSM():任务延时指定的时间,采用“时:分:秒:毫秒”方 ...
- Cocos2d-x 3.2 学习笔记(十六)保卫萝卜 游戏主循环与定时器
保卫萝卜~想法一直存在于想法,实战才是硬道理!有想法就去实现,眼高手低都是空谈. 一.游戏主循环GameSchedule 主循环是游戏处理逻辑,控制游戏进度的地方,处理好主循环是很重要的 ...
- Unix_Linux系统定时器的应用(案例)
2014-05-05 Created By BaoXinjian
- cocos2dx中的定时器及其分类
cocos2dx中的定时器分三大类: 1.帧循环定时器 2.一次性定时器 3.自定义定时器 一.帧循环定时器,顾名思义,每一帧都会执行一次,用于实时性要求比较高的场合,如碰撞检测 void sched ...
- Stm32 定时器 定时时间设置及PWM频率 占空比的设置总结
一.定时器的时钟: 当SYSCLK等于72M,APB1等于36M APB2等于72M时,定时器的时钟为72M.注意图中这句话:如果APB1/APB2预分频器=1则频率不变,否则频率x2.如果此时,AP ...
随机推荐
- JSP的文件上传和下载
文件的上传和下载 文件的上传和下载,是非常常见的功能.很多的系统中,或者软件中都经常使用文件的上传和下载. 比如:微信头像,就使用了上传. 邮箱中也有附件的上传和下载功能. 文件的上传介绍 1.要有一 ...
- 牛逼!Vue3.5的useTemplateRef让ref操作DOM更加丝滑
前言 vue3中想要访问DOM和子组件可以使用ref进行模版引用,但是这个ref有一些让人迷惑的地方.比如定义的ref变量到底是一个响应式数据还是DOM元素?还有template中ref属性的值明明是 ...
- ASP.NET Core – Razor Syntax
前言 Full stack 的问题就是经常需要一阵子离开一个环境. 比如我跑去写 Angular 几个月. 回来写 Razor, 肯定是卡卡的. 尤其是一些比较不常用到的语法. 所以有一个很好的笔记就 ...
- BOOST库 将源码作交叉编译 书籍下载
好记性不如烂笔头,BOOST库的移植,我也记录一下. 1. BOOST库 版本1.66.0 下载地址, 附书籍C++ BOOST库开发指南: https://download.csdn.net/dow ...
- linux(centos7)中安装7z
linux(centos7)中安装7z 一. 先安装wget yum -y install wget 二. 下载7z的压缩包 wget https://sourceforge.net/projects ...
- KASAN 中kasan_multi_shot 的作用
kasan_multi_shot 是 Linux 内核配置选项之一,与 Kernel Address Sanitizer (KASAN) 相关.KASAN 是一种内核内存错误检测工具,能够检测内核代码 ...
- 2021年第十一届数据技术嘉年华(DTC)资料分享
数据技术嘉年华(DTC)是由由中国DBA联盟(ACDU)和墨天轮社区联合主办的数据技术领域的盛会,至今已成功举办11届,吸引和聚集了众多数据领域学术精英.领袖人物.技术专家.从业者和技术爱好者,于此进 ...
- 数据库周刊57丨Oracle 2021年度安全警报;MySQL 8.0.23发布;MySQL索引优化导致的死锁案例;巨杉数据库跨引擎事务实践;MongoDB企业级能力解析;OceanBase OBCP 实验指导手册……
摘要:墨天轮数据库周刊第57期发布啦,每周1次推送本周数据库相关热门资讯.精选文章.干货文档. 热门资讯 1.Oracle 2021年度安全警报: Critical Patch Update 发布8个 ...
- js中判断数据类型的方法有哪些
判断数据类型可以使用 typeof 但是typeof 判断数组和函数时返回的都是Object 不能具体判断,这时使用 instanceof 可以判断对象是否是另一个函数创造的 : 用法: typeof ...
- python 生成requirements 文件
python 要生成 requirements文件 有两种情况 具有独立的虚拟环境 全局环境 具有独立的虚拟环境 pip freeze > requirements.txt 全局环境 安装 pi ...