当前位置: 首页 > news >正文

定时器定时中断定时器外部中断

基础背景:TIM定时中断-CSDN博客

TIM的函数

// 恢复缺省设置
void TIM_DeInit(TIM_TypeDef* TIMx);
// 时基单元初始化,第一个参数TIMx选择某个定时器,第二个参数是结构体,包含了配置时基单元的一些参数。
void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);// 把结构体变量赋一个默认值
void TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
// 使能计数器的,第一个参数是选择定时器TIMx,第二个是NewState,新的状态,使能还是失能。
void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);
// 使能中断输出信号,第一个TIMx,第二个TIM_IT,选择要配置哪个中断输出,第三个新的状态,使能还是失能。
void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);// 下面六个函数对应的是时基单元的时钟选择部分。
// 选择内部时钟,参数只有TIMx。
void TIM_InternalClockConfig(TIM_TypeDef* TIMx);
// 选择ITRx其他定时器的时钟,第一个参数是TIMx,选择要配置的定时器,第二个参数是选择要接入哪个其他的定时器。
void TIM_ITRxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);
// 选择TIMx捕获通道的时钟,第一个参数是TIMx,第二个参数选择TIx具体的某个引脚,后面两个参数是输入的极性和滤波器。
void TIM_TIxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_TIxExternalCLKSource, uint16_t TIM_ICPolarity, uint16_t ICFilter);
// 选择ETR通过外部时钟模式1输入的时钟,参数ExtTRGPrescaler,外部触发预分频器,可以对TER的外部时钟再提前做一个分频。
void TIM_ETRClockMode1Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter);
// 选择ETR通过外部时钟模式2输入的时钟。
void TIM_ETRClockMode2Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter);
// 用来单独配置ETR引脚的预分频器、极性、滤波器这些参数的。
void TIM_ETRConfig(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter);// 单独写预分频值的函数,Prescaler写的预分频值,TIM_PSCReloadMode写入的模式。
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);

定时器定时中断

线路图

代码

在每次复位时,发现值都是从1开始的,我们发现在TIM_TimeBaseInit()函数内部,最后会生成一个更新事件,来重装装载预分频器和重复计数器的值。

因为预分频器是有个缓冲寄存器的,写入的值只有在更新事件时才会真正起作用,所以为了让值立刻起作用,就在这最后,手动生成了一个更新事件。

但是由于更新事件和更新中断是同时发生的,更新中断会置更新中断标志位,当我们之后一旦初始化完了,更新中断就会立刻进入。

解决的方法:在TIM_TimeBaseInit()函数的后面,手动调用一下TIM_ClearFlag()函数。

Timer代码

#include "stm32f10x.h"                  // Device headervoid 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;TIM_TIMeBaseInitStructure.TIM_Prescaler = 720 - 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);
}//void TIM2_IRQHandler(void)
//{
//	if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
//	{
//		TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
//	}
//}

main代码

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Timer.h"uint16_t Num;int main(void)
{OLED_Init();Timer_Init();OLED_ShowString(1, 1, "Num:");while(1){OLED_ShowNum(1, 5, Num, 5);}
}void TIM2_IRQHandler(void)
{if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET){Num++;TIM_ClearITPendingBit(TIM2, TIM_IT_Update);}
}

定时器外部时钟

接线图

代码

Timer代码

#include "stm32f10x.h"                  // Device headervoid 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);// 用于配置定时器的外部时钟模式2// TIM_ExtTRGPSC_OFF 表示关闭预分频器,即不对外部时钟进行预分频。// TIM_ExtTRGPolarity_NonInverted: 这个参数用于配置外部触发信号的极性。// 0x00 表示不使用滤波器TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x00);// 初始化时基单元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);//配置TIM2定时器的中断,第二个参数表示定时器更新中断TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);// 配置NVIC的中断优先级分组NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);NVIC_InitTypeDef NVIC_InitStructure;// 设置中断通道为TIM2NVIC_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);
//	}
//}

main代码

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Timer.h"uint16_t Num;int main(void)
{OLED_Init();Timer_Init();OLED_ShowString(1, 1, "Num:");OLED_ShowString(2, 1, "CNT:");while(1){OLED_ShowNum(1, 5, Num, 5);OLED_ShowNum(2, 5, Timer_GetCounter(), 5);}
}void TIM2_IRQHandler(void)
{if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET){Num++;TIM_ClearITPendingBit(TIM2, TIM_IT_Update);}
}


http://www.mrgr.cn/news/40284.html

相关文章:

  • 【C++前缀和 数论 贪心】2245. 转角路径的乘积中最多能有几个尾随零|2036
  • 软件开发人员绩效考核方案(参考)
  • EP42 公告详情页
  • Linux 常用命令
  • DID身份是什么?
  • Python面向对象基础:属性动态添加
  • 《More Effective C++》的学习
  • 特殊的 BASE64 1
  • AJAX JSON 实例
  • 【信创,国产化】信息化系统信创改造,国产化改造方案,云建设
  • 水果质量检测数据集 腐烂检测13个类别‘ 训练集1811 验证集514 测试集258
  • 群面技巧|无领导小组讨论发言技巧|无领导小组讨论角色|无领导小组讨论提问|秋招
  • 车辆种类分类识别数据集,可以识别7种汽车类型,已经按照7:2:1比 例划分数据集,训练集1488张、验证集507张,测试集31张, 共计2026张。
  • Golang | Leetcode Golang题解之第448题找到所有数组中消失的数字
  • 【机器学习】任务六:分类算法(支持向量机(SVM)在线性可分与不可分数据中的应用与可视化分析)
  • XSS | XSS 常用语句以及绕过思路
  • Java | Leetcode Java题解之第449题序列化和反序列化二叉搜索树
  • 点特征直方图 (PFH) 描述符
  • Windows系统实现双网卡同时上内外网
  • C++入门基础知识93(实例)——实例18【猴子吃桃问题】