STM 入门学习(4)定时器-1 定时中断和内外时钟源选择 含代码

TIM简介

16位计数器,预分频器,自动重装寄存器的时基单元, 65536.

类型编号总线功能
高级定时器TIM1,TIM8APB2拥有所有功能,额外有重复计数器,死区生成,互补输出,刹车输入等
通用定时器TIM2,TIM3, TIM4,TIM5APB1拥有基本功能,额外具有内外时钟源选择,输入捕获,输出比较,编码器接口,主从模式触发等功能
基本定时器TIM6,TIM7APB1拥有定时中断,主模式触发DAC功能
  • 预分频器
    • 写0 为 1分频 为输出频率=输入频率/1 =72MHz
    • 写1 为 2 分频 为输出频率=输入频率/2 =36MHz
    • 预分频为16位 最大值位65535 也就是 65536 分频

通用定时器

  • 外部时钟源
    • TIMx_ETR (PA0) ------ 输入 方波信号
      – >| 配置 极性选择,边沿检测和预分频器 |–>输入滤波 【对外部波形进行修整】

      • 分两路
        +【外部时钟模式2】 ETRF 进入控制器 选择作为时基单元
        想在ETR外部引脚提供时钟 / 对ETR时钟进行计数,把定时器当做计数器
        + 【外部时钟模式1】TRGI(TRIGGER IN)主要作为触发输入来使用的,触发输入可以触发定时器的从模式 {* 之后在说,本节当成外部时钟讨论}, 或者 当作外部时钟 使用
        1. ETR
        2. ITR 【时钟信号来自其他定时器】{从触发器的 TRGO 来的}
        在这里插入图片描述
        可以 实现 定时器的级联 功能
        3. TI1F_ED 连接 输入捕获单元的 CH1 {ED为边沿的意思 说明这一路时钟 上升沿和下降沿均有效
        4. TI1FP1 和 TI2P2获得

      时基单元: 预分频器 计数器 自动重装器

高级定时器

为了三相电机驱动

  • 死区 防止 互补输出的pwm驱动桥臂时 在开关切换的瞬间,桥臂上下同时关闭,产生死去 防止造成短暂的直通现象
  • 刹车输入 (为电机提供保障) 刹车信号 或者时钟失效 切断电源

基本结构

在这里插入图片描述

  • 计数器计数频率
    CK_CNT= CK_PSC(PSC+1)
    CK_CNT 定时器时钟
    PSC预分频
  • 计数器溢出频率
    CK_CNT_OV=CK_CNT/(ARR+1)
    =CK_PSC/(PSC+1)/(ARR+1)

影子寄存器
在更新事件的时候 更新重装寄存器

思路

第一步:RCC开启时钟
第二步:选择时基单元的时钟源
第三步:配置时基单元:预分频器,自动重装器,计数模式,等等(一个结构体)
第四步:配置输出中断控制,允许更新中断输出到NVIC
第五步:配置NVIC在NVIC打开定时器中断的通道,并分配一个优先级。
第六步:运行控制 使能一下计数器,
最后:定时器的中断函数

常用讲解

 - 恢复缺省配置
void TIM_DeInit(TIM_TypeDef* TIMx);
 - 时基单元初始化  
void TIM_TimeBaseInit(TIM_TypeDef* TIMx,/*选择某一个定时器*/ TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct/*结构体*/);
- 给结构体赋一个默认值
void TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
- 使能计数器
void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);
- 中断输出控制
void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);

步骤

  • 时钟源选择:
void TIM_InternalClockConfig(TIM_TypeDef* TIMx);
void TIM_ITRxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);
void TIM_TIxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_TIxExternalCLKSource,
                                uint16_t TIM_ICPolarity, uint16_t ICFilter);
void TIM_ETRClockMode1Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,
                             uint16_t ExtTRGFilter);
void TIM_ETRClockMode2Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, 
                             uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter);
void TIM_ETRConfig(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,
                   uint16_t ExtTRGFilter);
                   
  • 时基单元初始化
void TIM_TimeBaseInit(TIM_TypeDef* TIMx,/*选择某一个定时器*/ TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct/*结构体*/);
void TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);//给结构体赋一个默认值
  • 中断输出控制
void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);
  • NVIC
    NVIC
  • 运行控制
void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);

可以单独修改一些值

  • 单独写预分频值的
void TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler,/*写入的预分频值*/
uint16_t TIM_PSCReloadMode/*写入的模式*/);

写入的模式:选择在更新事件生效;或者:手动写入更新事件,立即生效。

  • 改变计数器的计数模式
void TIM_CounterModeConfig(TIM_TypeDef* TIMx, uint16_t TIM_CounterMode/*选择新的计数器模式*/);
  • 自动重装器预装功能装置
void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState/* 使能还是失能*/);
  • 给计数器写入一个值
void TIM_SetCounter(TIM_TypeDef* TIMx, uint16_t Counter);
  • 给自动重装器写入一个值
void TIM_SetAutoreload(TIM_TypeDef* TIMx, uint16_t Autoreload);
  • 获取当前计数器的值
uint16_t TIM_GetCounter(TIM_TypeDef* TIMx);
  • 获取当前的预分频器的值
uint16_t TIM_GetPrescaler(TIM_TypeDef* TIMx);
  • 获取标志位和清除标志位
FlagStatus TIM_GetFlagStatus(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);
void TIM_ClearFlag(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);
ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT);
void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT);

内部例程:

TIMER.c

void Timer_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
	
	TIM_InternalClockConfig(TIM2);
	
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;//选择一分频
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数
	TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1;//ARR自动重装器(一秒)
	TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;//预分频器的值(1秒)
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//重复计数器,高定才有
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
	
	TIM_ClearFlag(TIM2, TIM_FLAG_Update);//手动清除标志位,避免刚初始化进中断,例子:没有时 计数器显示从0001开始 ,正常:0000开始
	TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructure);
	
	TIM_Cmd(TIM2, ENABLE);
	}
	// 配置中断函数,为别的文件使用
	/*
void TIM2_IRQHandler(void)
{
	if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
	{
		//比如  NUM++  ,计数器加一 需要写声明 :extern   --- 跨文件的变量   或  写到主函数// 
		TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
	}
}
*/

外部时钟

TIMER.c

#include "stm32f10x.h"                  // Device header

void Timer_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU//上拉输入;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF/*选择不分频*/, TIM_ExtTRGPolarity_NonInverted/*外部触发的极性:2.不反向 高电平有效*/, 0x0F/*外部触发滤波器*/);
	
	
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period = 10 - 1;
	TIM_TimeBaseInitStructure.TIM_Prescaler = 1 - 1;
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
	
	TIM_ClearFlag(TIM2, TIM_FLAG_Update);
	TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructure);
	
	TIM_Cmd(TIM2, ENABLE);
}

uint16_t Timer_GetCounter(void)//实时看一下计数器的值  封装函数
{
	return TIM_GetCounter(TIM2);
}

/*
void TIM2_IRQHandler(void)
{
	if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
	{
		
		TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
	}
}
*/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值