rayoli

主要外设:

  • TIM:Timer 定时器

TIM中的基本电路

定时器

计数器的基本功能

  • 复位:计数器值=初值、产生一个输出脉冲、产生更新事件(UEV)脉冲、更新中断标志UIF=1
  • 计数:计数器值递增或递减
  • 设置方向:递增或递减

计数器的使用:输入脉冲(N个)→计数器→输出脉冲(1个)

  • 输入脉冲的第一个边沿时刻:计数器进行复位
  • 输入脉冲的非首个边沿时刻:检查计数器是否等于终值
    • 若相等(溢出),对计数器进行复位
    • 若不等(计数),对计数器进行计数
  • 所以N=|终值-初值|+1

计数器的数据:初值、计数器值、终值

  • 计数器值:在计数器中,位宽决定计数范围(16bit计数器为0~65535)
  • STM32以0为初值或终值
  • 另一个值(终值或初值):所以计数器还需要一个额外的寄存器

计数器的定时(分频)功能:

  • 若输入为频率fp的时钟信号
  • 则输出为频率f的时钟信号f=fp*(1/N),N作为分频系数

时基单元

输入→预分频寄存器PSC及影子寄存器、预分频计数器→自动重载寄存器ARR及影子寄存器、核心计数器、计数器寄存器CNT→产生上溢、下溢
→产生UEV事件→[产生更新中断UIF、DMA中断]

  • PSC和ARR都有一个影子寄存器:真正起作用的寄存器、不能直接用代码修改
  • 代码修改PSC和ARR时
    • 直接修改影子寄存器的值(无缓冲)
    • 等到UEV事件时,统一修改影子寄存器的值(缓冲)

时钟源

输入信号→时钟源选择→时基单元

  • 内部时钟
  • 引脚TIM_CH(外部输入):外部时钟模式1
  • 引脚TIM_ETR(外部输入):外部时钟模式2
  • 内部触发信号ITR:内部其他定时器

外部时钟模式2:
引脚TIM_ETR→GPIO AFR→GPIO输入电路→边沿选择SMCR(ETP)→分频器SMCR(ETPS)→滤波器SMCR(ETF)→时钟源选择SMCR(ECE、SMS)→时基单元

引脚TIM_CH→输入捕获单元→捕获/比较寄存器→中断/DMA
捕获/比较寄存器→输出比较单元→引脚TIM_CH

定时器分类

  • 内核定时器(CortexM):SysTick系统节拍定时器
  • 外设定时器(STM32):TIM基本、通用、高级定时器、看门狗定时器、实时时钟RTC、低功耗定时器

TIM_Base时基单元:内部时钟模式

主要功能:用内部时钟,定时触发事件/中断

数据通路
内部时钟APB timer→时钟源选择SMCR(ECE、SMS)→时基单元→中断→NVIC→CPU

时基单元TIM_Base:输入脉冲(N1*N2个)→预分频模块计数模块→输出脉冲(1个)

  • 预分频模块:预分频计数器+预分频寄存器
  • 计数模块:核心计数器+自动重载寄存器+计数器寄存器

预分频模块

  • 预分频计数器:主要用于分频,计数值为0→PSC,分频系数为N1=PSC+1
  • 预分频寄存器:预分频系数PSC(计数终值)

计数模块

  • 核心计数器:可用于分频或计数
  • 自动重载寄存器:设置自动重载系数ACC(计数初值或终值)
  • 计数器寄存器:记录当前计数值CNT

计数模式:针对核心计数器

  • 递增计数:0→ARR(上溢)
  • 递减计数:ARR→0(下溢)
  • 中心对齐计数:0→ARR-1(上溢)、ARR→0(下溢)

时基单元的定时功能

  • 输入时钟信号:APB的定时器时钟TIM_CLK
  • 输入时钟信号fp,经过预分频模块和计数模块的两次分频,最终产生特定周期T(频率为f)的时钟信号
  • f=1/T=fp*(1/N1)*(1/N2)T*fp=N1*N2=(PSC+1)*(ACC+1)PSC=N1-1,ACC=N2-1

硬件设计

  • TIM10挂接在APB2总线上,定时器时钟TIM2_CLK为100MHz
  • 若产生10ms定时中断:10ms*100MHz=10000*1000
  • 即PSC=10000-1、ARR=1000-1

CubeMX的配置

  1. 引脚分配:无
  2. 外设配置:
  • Timers-TIM10 →模式→ 勾选Activated
  • Timers-TIM10 →参数设置(时基单元设置)→ PSC预分频器=10000-1、ARR自动重载寄存器=100-1、计数器模式=递增up、内部时钟分频器=不分频、auto-reload preload=disable
  • System Core-NVIC-NVIC中断表 →TIM1 update interrupt and TIM10 global interrupt→ 勾选使能、并设置抢占优先级和子优先级

用户代码

//USER CODE2:外设启动
__HAL_TIM_CLEAR_IT(&htim10, TIM_IT_UPDATE);//清除定时器初始化过程中的中断标志、避免定时器一启动就进入中断
HAL_TIM_Base_Start_IT(&htim10); // 启动定时器中断、启动定时器

//USER CODE4:定义中断回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
    if(htim->Instance==TIM10){//判断更新中断来源
        
    }
}

TIM_Base时基单元:ETR外部时钟模式2

主要功能:对外部输入脉冲进行计数

数据通路:
TIM_ETR引脚→GPIO输入电路→GPIO的AFR→预分频PSC=0(影子寄存器)→核心计数器CNT

时基单元的外部脉冲计数功能

  • 输入脉冲信号:捕获/比较通道CH、外部触发引脚ETR
  • PSC通常置0
  • ACC通常置为特别大的值(防止计数结束前发生溢出)
  • 读取CNT中的计数值

硬件设计

PA0复用为TIM2_ETR,用来接收外部的脉冲信号

CubeMX的配置

  1. 引脚分配:
  • 在外设配置时,可自动将PA0复用为TIM2_ETR
  1. 外设配置:
  • Timers-TIM2 → 模式 →时钟源=ETR2
  • Timers-TIM2 → 参数设置(时基单元设置)→ PSC预分频器=0、ARR自动重载寄存器=0xFFFFFFFF、计数器模式=向上、内部时钟分频器=不分频、auto-reload preload=disable
  • Timers-TIM2 → 参数设置(时钟源)→ 时钟滤波=0、时钟极性=不反向、时钟分频=不分频

用户代码

HAL_TIM_Base_Start(&htim2);//启动定时器
uint32_t Result = __HAL_TIM_GET_COUNTER(&htim2); // 读取外部脉冲计数值

TIM_OC输出比较单元

时基单元TIM_Base为内部时钟模式:CNT从初值→CCR→终值循环变化
捕获/比较寄存器CCR→输出控制→引脚TIM_CH(输出比较通道)

TIM_CH的输出比较模式分类:

  • PWM1:[初值→CCR)时输出有效电平、[CCR→终值]时输出无效电平(PWM2相反)(脉冲宽度调制波形)
  • ACTIVE:CNT=CCR(匹配)时输出有效电平、不匹配时输出无效电平(INACTIVE相反)(单脉冲模式)
  • TOGGLE:CNT=CCR(匹配)时输出电平翻转
  • TIMING:CNT=CCR(匹配)时无通道输出(冻结模式)
  • FORCED_ACTIVE:强制输出有效电平
  • FORCED_INACTIV:强制输出无效电平

TIM_CH输出有效电平的极性:高电平有效、低电平有效

脉冲宽度调制Pulse Width Modulation:对模拟信号电平进行数字编码的方法,应用于灯光亮度调节、功率控制、电机控制等领域

  • 周期Period:一个完整PWM波形所持续时间(时基单元提供)
  • 占空比Duty:(高电平持续时间Ton/PWM周期)x100%(输出比较单元提供)

硬件设计

PA5复用为TIM2_CH1,产生周期为1ms,占空比为47.5%的PWM信号

  • TIM2挂接在APB2总线上,定时器时钟TIM2_CLK为100MHz
  • PWM的周期为200ms:1ms*100MHz=100*1000设PSC=100-1、ARR=1000-1、向上计数
  • 占空比为47.5%,若使用PWM1、输出极性为高电平有效、则CCR为475

CubeMX的配置

  1. 引脚分配:
  • Pinout View:搜索PA5 设置为TIM2_CH1
  1. 外设配置:
  • Timers-TIM2 →模式→ 时钟源=内部时钟源、Channel1=PWM通用CH1
  • Timers-TIM2 →参数设置(时基单元设置)→ PSC预分频器=100-1、ARR自动重载寄存器=1000-1、计数器模式=向上、内部时钟分频器=不分频、auto-reload preload=disable
  • Timers-TIM2 →参数设置(PWM输出通道设置)→ 模式=PWM mode1、脉冲(CCR)=475、通道极性=高电平有效、输出比较预装载=使能(PWM波形循环)、快速模式:禁用

用户代码

//USER CODE2:外设启动
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);

//USBR CODE3:后台程序(无限循环)
//呼吸灯:PWM的不同占空比时,在人眼的视觉暂留效果,导致LED看起来“不同亮度”
//扫描频率需大于50Hz(周期20ms),以避免闪烁
__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_1,Duty);//步进20%的占空比
HAL_Delay(100);

TIM_IC输入捕获单元

主要功能:测量信号的参数,比如周期和频率

  • 被测信号的周期 = 两次上升沿CNT的差值 x ( PSC + 1 ) / 时基单元周期

引脚TIM_CH(输入捕获通道)→输入滤波→边沿检测→当前通道直接输入方式、其他通道的间接输入方式→预分频器→捕获/比较寄存器CCR

  • 当TIM_CH的上升沿或下降沿时,将CNT的值写入到CCR中

硬件设计

PA0复用为TIM2_CH1,输入捕获
PA6复用为TIM3_CH1,比较输出PWM,即被测信号源(100KHz占空比50%的方波)

CubeMX的配置

  1. 引脚分配:
  • Pinout View:搜索PA0 设置为TIM2_CH1
  1. 外设配置:
  • Timers-TIM2 →模式→ 时钟源=内部时钟源、Channel1=输入捕获 直接模式
  • Timers-TIM2 →参数设置(时基单元设置)→ PSC预分频器=0、ARR自动重载寄存器=0xFFFFFFFF、计数器模式=向上、内部时钟分频器=不分频、auto-reload preload=disable
  • Timers-TIM2 →参数设置(输入捕获通道1设置)→ 极性选择=上升沿、输入捕获通道IC选择=直接输入模式、预分频器分频比=不分频、输入滤波=0

用户代码

uint32_t Diff = 0 ; // 存放捕获差值
uint8_t MeasureFlag = 0 ; // 测量完成标志:0表示未完成,1表示完成
uint8_t CapIndex = 0 ; // 捕获指示:0表示没有开始捕获,1表示完成一次捕获
uint32_t CapVal1 = 0 ; // 存放第一次捕获值
uint32_t CapVal2 = 0 ; // 存放第二次捕获值

//USER CODE2:外设启动
HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1); // 启动定时器2通道1的输入捕获功能

//USBR CODE3:后台程序(无限循环)
if( MeasureFlag == 1){ // 判断测量标志是否置位
    Diff =CapVal2 >= CapVal1?(CapVal2 - CapVal1):(0xFFFFFFFF + 1 - CapVal1 + CapVal2);    // 计算差值
    printf ("Period is: %.4f ms\r\n",(double)Diff/100000); // 计算信号周期
    MeasureFlag = 0; // 清除测量完成标志
    HAL_Delay(1000);
    HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1); // 启动下一次捕获
}
//USER CODE4:定义中断回调函数
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim){
    if(htim->Instance==TIM2){//判断发生捕获中断的定时器
        if(htim->Channel==HAL_TIM_ACTIVE_CHANNEL_1){//判断发生捕获中断的通道
          if(CapIndex == 0){ //存放第一次捕获时CCR的值
            CapVal1=HAL_TIM_ReadCapturedValue(&htim2, TIM_CHANNEL_1);
            CapIndex=1;
          }else if(CapIndex == 1){//存放第二次捕获时CCR的值
            CapVal2=HAL_TIM_ReadCapturedValue(&htim2, TIM_CHANNEL_1);
            HAL_TIM_IC_Stop_IT(&htim2,  TIM_CHANNEL_1); // 停止捕获
            CapIndex=0;     //重置捕获标志
            MeasureFlag=1;//测量完成的结束标志
          }
        }
    }
}

分类:

技术点:

相关文章: