赞
踩
因为定时器和中断系统的电路都在STM32内部,定时中断是为我们程序设计提供服务的,芯片外部只需要插一个OLED显示数据。
本设计采用模块化编程,在配置好的工程基础上在System文件夹中加上Timer.c、Timer.h两部分。
在Timer.c首先进行函数的初始化。
初始化定时器大致思路
1. 第⼀步,RCC开启时钟 ,定时器的基准时钟和整个外设的工作时钟就会同时打开。 2. 第⼆步,选择时基单元的时钟源 (内部时钟源) 3. 第三步,配置时基单元 4. 第四步,配置输出中断控制,允许更新中断输出到NVIC 5. 第五步,配置NVIC,在NVIC中打开定时器中断的通道,并分配⼀个优先级 6. 第六步,运⾏控制 7. 第七步,使能计数器,计数器使能后,计数器开始计数,当计数器更新时,触发中断
8. 第八部,定时器中断函数,中断函数每隔一段时间就能自动执行一次
恢复缺省配置函数
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);
选择ITRx其他定时器的时钟函数
void TIM_ITRxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);
选择TIx捕获通道的时钟函数
- void TIM_TIxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_TIxExternalCLKSource,
- uint16_t TIM_ICPolarity, uint16_t ICFilter);
TIMx--选择要配置的定时器
TIM_TIxExternalCLKSource--选择TIx具体的某个引脚
TIM_ICPolarity--输入极性
ICFilter--滤波器
选择ETR通过外部时钟模式1输⼊的时钟函数
- void TIM_ETRClockMode1Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,
- uint16_t ExtTRGFilter);
参数2:预分频器 参数3:输⼊的极性 参数4:滤波器
选择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);
单独写预分频值函数
void TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler,uint16_t TIM_PSCReloadMode);
TIMx--选择要配置的定时器
Prescaler--要写入的预分频值
TIM_PSCReloadMode--写入模式,在更新事件⽣效,或者在写⼊后,⼿动产⽣⼀个更新事件,让这个值 立刻生效。
改变计数器的计数模式函数
void TIM_CounterModeConfig(TIM_TypeDef* TIMx, uint16_t TIM_CounterMode);
⾃动重装器预装功能配置函数 TIM_ARRPreloadConfig设置为DISABLE 和ENABLE的问题,他的作⽤只是允许或禁⽌在定 时器⼯作时向ARR的缓冲器中写⼊新值,以便在更新事件发⽣时载⼊覆盖以前的值。
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);
Timer.h
- #ifndef __TIMER_H
- #define __TIMER_H
-
- void Timer_Init(void);
-
- #endif
Timer.c
- #include "stm32f10x.h" // Device header
-
- void Timer_Init(void)
- {
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//开启TIM2时钟
-
- TIM_InternalClockConfig(TIM2);//使用内部时钟
- //配置时基单元
- TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//定义时基单元结构体
- TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;//设置1分频,也就是不分频
- TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//设置向上计数
- TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1;//ARR自动重装值(CK_PSC/(PSC+1)/(ARR+1))
- TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;//PSC预分频器的值,PSC不分频
- TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//重复计数器的值,高级定时器特有
- TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);//写入参数
-
- TIM_ClearFlag(TIM2, TIM_FLAG_Update);//清除更新标志位,避免刚初始化完就进中断。
- TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);//中断输出
- //配置NVIC
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断优先级分组
-
- NVIC_InitTypeDef NVIC_InitStructure;//NVIC结构体
- 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);//开启定时器
- }
-
- //定时器2中断函数
- /*
- void TIM2_IRQHandler(void)
- {
- if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)//判断是否中断溢出
- {
-
- TIM_ClearITPendingBit(TIM2, TIM_IT_Update);//清除中断标志位
- }
- }
- */
- //将中断函数提到使用的地方
main.c
- #include "stm32f10x.h" // Device header
- #include "Delay.h"
- #include "OLED.h"
- #include "Timer.h"
-
- uint16_t Num;//定义16位全局变量Num
-
- int main(void)
- {
- OLED_Init();
- Timer_Init();//初始化定时器
-
- OLED_ShowString(1, 1, "Num:");
-
- while (1)
- {
- OLED_ShowNum(1, 5, Num, 5);
- }
- }
- //定时器2中断函数
- void TIM2_IRQHandler(void)
- {
- if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
- {
- Num ++;//每秒Num自动++
- TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
- }
- }
接一个对射式红外传感器,DO数字输出接到PA0引脚(TIM2的ETR引脚,在此引脚输入外部时钟)
本设计采用模块化编程,在配置好的工程基础上在System文件夹中加上Timer.c、Timer.h两部分。
每次遮挡射式红外传感器CNT+1,加到9后,自动清零,同时申请中断,Num++
Timer.h
- #ifndef __TIMER_H
- #define __TIMER_H
-
- void Timer_Init(void);
- uint16_t Timer_GetCounter(void);
-
- #endif
Timer.c
- #include "stm32f10x.h" // Device header
-
- void Timer_Init(void)
- {
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//开启TIM2时钟
- //配置GPIO
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//开启GPIOA的时钟
-
- 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, 0x0F);//使用外部时钟
- //配置时基单元
- TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//定义时基单元结构体
- TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;//设置1分频,也就是不分频
- TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//设置向上计数
- TIM_TimeBaseInitStructure.TIM_Period = 10;//从0计到9
- TIM_TimeBaseInitStructure.TIM_Prescaler = 1;//PSC预分频器的值,PSC不分频
- TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//重复计数器的值,高级定时器特有
- TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);//写入参数
-
- TIM_ClearFlag(TIM2, TIM_FLAG_Update);//清除更新标志位
- TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);//中断输出
- //配置NVIC
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断优先级分组
-
- NVIC_InitTypeDef NVIC_InitStructure;//NVIC结构体
- 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);//开启定时器
- }
- //CNT计数器值
- uint16_t Timer_GetCounter(void)
- {
- return TIM_GetCounter(TIM2);
- }
- //定时器2中断函数
- /*
- void TIM2_IRQHandler(void)
- {
- if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)//判断是否中断溢出
- {
-
- TIM_ClearITPendingBit(TIM2, TIM_IT_Update);//清除中断标志位
- }
- }
- */
- //将中断函数提到使用的地方
main.c
- #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);
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。