TIM定时中断
TIM简介
定时器的类型
基本定时器
通用定时器
高级定时器
定时中断的基本结构
通用计时器的时序
可以参考STM32参考文档的14通用定时器(TIMx) 部分。
预分频器时序
计数器时序
计数器无预装时序(无缓冲寄存器)
计数器有预装时序(有缓存寄存器)
RCC时钟树
STM32中用来产生和配置时钟,并且把配置好的时钟发送到各个外设的系统。
三种不同的时钟源可被用来驱动系统时钟(SYSCLK):
● HSI振荡器时钟
● HSE振荡器时钟
● PLL时钟
这些设备有以下2种二级时钟源:
● 40kHz低速内部RC,可以用于驱动独立看门狗和通过程序选择驱动RTC。RTC用于从停机/
待机模式下自动唤醒系统。
● 32.768kHz低速外部晶体也可用来通过程序选择驱动RTC(RTCCLK)。
当不被使用时,任一个时钟源都可被独立地启动或关闭,由此优化系统功耗。
1.当HSI被用于作为PLL时钟的输入时,系统时钟能得到的最大频率是64MHz。
2.对于内部和外部时钟源的特性,请参考相应产品数据手册中“电气特性”章节。
用户可通过多个预分频器配置AHB、高速APB(APB2)和低速APB(APB1)域的频率。AHB和
APB2域的最大频率是72MHz。APB1域的最大允许频率是36MHz。SDIO接口的时钟频率固定
为HCLK/2。
RCC通过AHB时钟(HCLK)8分频后作为Cortex系统定时器(SysTick)的外部时钟。通过对SysTick
控制与状态寄存器的设置,可选择上述时钟或Cortex(HCLK)时钟作为SysTick时钟。ADC时钟
由高速APB2时钟经2、4、6或8分频后获得。
定时器时钟频率分配由硬件按以下2种情况自动设置:
- 如果相应的APB预分频系数是1,定时器的时钟频率与所在APB总线频率一致。
- 否则,定时器的时钟频率被设为与其相连的APB总线频率的2倍。
具体可参考STM32参考手册6.3 RCC寄存器描述部分
定时器定时中断
第一步:新建工程
第二步:连接线路
第三步:编写程序
实验现象:OLED显示屏上显示“Num:”,每秒自动加一。
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:");
while(1)
{
OLED_ShowNum (1,5,Num,5);
// OLED_ShowNum (2,5,TIM_GetCounter (TIM2),5);
//获取TIMx计数器的值:TIM_GetCounter
}
}
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
{
Num ++;
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
}
Timer.c文件
#include "stm32f10x.h" // Device header
//extern uint16_t Num;
void Timer_Init(void )
{
RCC_APB1PeriphClockCmd (RCC_APB1Periph_TIM2 ,ENABLE );
//TIM2是APB1总线的外设
//配置TIMx内部时钟
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 = 7200 - 1;//指定用于分频TIM时钟的预分频器值。
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//指定重复计数器值
//根据TIM_TimeBaseInitStruct中指定的参数,初始化TIMx时间基准单元外设。
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
//清除TIMx的挂起标志位。
TIM_ClearFlag(TIM2, TIM_FLAG_Update);
//使能或失能指定的TIM中断
TIM_ITConfig(TIM2 ,TIM_IT_Update ,ENABLE);
//NVIC
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外设
TIM_Cmd(TIM2, ENABLE);
}
//中断函数
/*
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
{
Num ++;
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
}
*/
Timer.h文件
#ifndef __TIMER_H
#define __TIMER_H
void Timer_Init(void);
#endif
定时器外部时钟
第一步:新建工程
第二步:连接线路
第三步:编写程序
实验现象:对射式红外传感器遮挡后移开,CNT加一,CNT加到9后,再加一,CNT清零,Num的值为一。
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);
// OLED_ShowNum (2,5,TIM_GetCounter (TIM2),5);
//获取TIMx计数器的值:TIM_GetCounter
}
}
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
{
Num ++;
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
}
Timer.c文件
#include "stm32f10x.h" // Device header
//extern uint16_t Num;
void Timer_Init(void )
{
RCC_APB1PeriphClockCmd (RCC_APB1Periph_TIM2 ,ENABLE );
//TIM2是APB1总线的外设
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_ETRClockMode2Config(TIM2,TIM_ExtTRGPSC_OFF,TIM_ExtTRGPolarity_NonInverted,0x0F);
//指定要配置的定时器实例,这里是TIM2
//TIM_ExtTRGPSC_OFF:表示禁用定时器的外部时钟源
//TIM_ExtTRGPolarity_NonInverted:表示定时器的输出极性为非反相。
//0x00:表示定时器的分频值,这里设置为0。
//配置时基单元
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时钟的预分频器值。
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//指定重复计数器值
//根据TIM_TimeBaseInitStruct中指定的参数,初始化TIMx时间基准单元外设。
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
//清除TIMx的挂起标志位。
TIM_ClearFlag(TIM2, TIM_FLAG_Update);
//使能或失能指定的TIM中断
TIM_ITConfig(TIM2 ,TIM_IT_Update ,ENABLE);
//NVIC
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外设
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)
{
Num ++;
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
}
*/
Timer.h文件
#ifndef __TIMER_H
#define __TIMER_H
void Timer_Init(void);
uint16_t Timer_GetCounter(void);
#endif
TIM输出比较
输出比较简介
PWM简介
输出比较通道(通用)
输出比较通道(高级)
仅做了解
输出比较模式
PWM基本结构
PWM参数计算
舵机
舵机简介
硬件电路
直流电机
直流电机及驱动简介
硬件电路
PWM驱动LED呼吸灯
第一步:新建工程
第二步:连接线路
第三步:编写程序
实验现象:PA0端口上的LED呈现呼吸灯的效果。
main.c文件
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "PWM.h"
uint8_t i;
int main (void)
{
OLED_Init ();
PWM_Init ();
while(1)
{
for (i=0;i<=100;i++)
{
PWM_SetCompare1 (i);
Delay_ms(10);
}
for (i=0;i<=100;i++)
{
PWM_SetCompare1 (100-i);
Delay_ms(10);
}
}
}
PWM.c文件
#include "stm32f10x.h" // Device header
void PWM_Init(void )
{
RCC_APB1PeriphClockCmd (RCC_APB1Periph_TIM2 ,ENABLE );
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
// RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
// GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2, ENABLE);
// GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP ;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //GPIO_Pinn_15
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz ;
GPIO_Init(GPIOA ,&GPIO_InitStructure );
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 = 100 - 1; //ARR
TIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1; //PSC
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCStructInit(&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 0; //CCR
TIM_OC1Init(TIM2 ,&TIM_OCInitStructure);
TIM_Cmd(TIM2, ENABLE);
}
void PWM_SetCompare1(uint16_t Compare)
{
TIM_SetCompare1(TIM2 ,Compare );
}
PWM.h文件
#ifndef __PWM_H
#define __PWM_H
void PWM_Init(void);
void PWM_SetCompare1(uint16_t Compare);
#endif
PWM驱动舵机
第一步:新建工程
第二步:连接线路
第三步:编写程序
实验现象:按下按键,舵机输出轴的角度变化,OLED显示当前的角度。
main.c文件
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "Servo.h"
#include "Key.h"
uint8_t KeyNum;
float Angle;
int main (void)
{
OLED_Init ();
Servo_Init ();
Key_Init();
OLED_ShowString (1,1,"Angle:");
while(1)
{
KeyNum =Key_GetNum ();
if (KeyNum == 1)
{
Angle +=30;
if (Angle >180)
{
Angle =0;
}
}
Servo_SetAngle(Angle );
OLED_ShowNum (1,7,Angle ,3);
}
}
Servo.c文件
#include "stm32f10x.h" // Device header
#include "PWM.h"
void Servo_Init(void )
{
PWM_Init ();
}
void Servo_SetAngle(float Angle)
{
PWM_SetCompare2 (Angle /180*2000 + 500);
}
Servo.h文件
#ifndef __SERVO_H
#define __SERVO_H
void Servo_Init(void );
void Servo_SetAngle(float Angle);
#endif
PWM驱动直流电机
第一步:新建工程
第二步:连接线路
第三步:编写程序
实验现象:按下按键,电机转动,再按一下按键,速度增加,增加到最大,再按下按键,点击反向全速选择,之后速度减少;OLED显示当前的速度值。
main.c文件
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "Motor.h"
#include "Key.h"
uint8_t KeyNum;
int8_t Speed;
int main (void)
{
OLED_Init ();
Motor_Init();
Key_Init();
OLED_ShowString (1,1,"Speed:");
while(1)
{
KeyNum = Key_GetNum();
if (KeyNum == 1)
{
Speed +=20;
if (Speed >100)
{
Speed=-100;
}
}
Motor_SetSpeed(Speed);
OLED_ShowSignedNum (1,7,Speed ,3);
}
}
Motor.c文件
#include "stm32f10x.h" // Device header
#include "PWM.h"
void Motor_Init(void )
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz ;
GPIO_Init(GPIOA ,&GPIO_InitStructure );
PWM_Init ();
}
void Motor_SetSpeed(int8_t Speed)
{
if (Speed >=0)
{
GPIO_SetBits(GPIOA ,GPIO_Pin_4);
GPIO_ResetBits(GPIOA ,GPIO_Pin_5);
PWM_SetCompare3(Speed );
}
else
{
GPIO_ResetBits(GPIOA ,GPIO_Pin_4);
GPIO_SetBits(GPIOA ,GPIO_Pin_5);
PWM_SetCompare3(-Speed );
}
}
Motor.h文件
#ifndef __MOTOR_H
#define __MOTOR_H
void Motor_Init(void);
void Motor_SetSpeed(int8_t Speed);
#endif
TIM输入捕获
输入捕获简介
频率测量
输入捕获通道
主从触发模式
输入捕获基本结构
PWMI结构
输入捕获模式测频率
第一步:新建工程
第二步:连接线路
第三步:编写程序
实验现象:OLED屏幕上显示“Freq:01000Hz”。
main.c文件
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "PWM.h"
#include "IC.h"
int main (void)
{
OLED_Init();
PWM_Init();
IC_Init();
OLED_ShowString(1, 1, "Freq:00000Hz");
PWM_SetPrescaler(720 - 1); //Freq = 72M / (PSC + 1) / 100
PWM_SetCompare1(50); //Duty = CCR / 100
while (1)
{
OLED_ShowNum(1, 6, IC_GetFreq(), 5);
}
}
PWM.c文件
#include "stm32f10x.h" // Device header
void PWM_Init(void )
{
RCC_APB1PeriphClockCmd (RCC_APB1Periph_TIM2 ,ENABLE );
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP ;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz ;
GPIO_Init(GPIOA ,&GPIO_InitStructure );
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 = 100 - 1; //ARR
TIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1; //PSC
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCStructInit(&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 0; //CCR
TIM_OC1Init(TIM2 ,&TIM_OCInitStructure);
TIM_Cmd(TIM2, ENABLE);
}
void PWM_SetCompare1(uint16_t Compare)
{
TIM_SetCompare1(TIM2 ,Compare );
}
void PWM_SetPrescaler(uint16_t Prescaler)
{
//配置 TIMx 预分频器
TIM_PrescalerConfig(TIM2 ,Prescaler ,TIM_PSCReloadMode_Immediate);
}
PWM.h文件
#ifndef __PWM_H
#define __PWM_H
void PWM_Init(void);
void PWM_SetCompare1(uint16_t Compare);
void PWM_SetPrescaler(uint16_t Prescaler);
#endif
IC.c文件
#include "stm32f10x.h" // Device header
void IC_Init(void )
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
TIM_InternalClockConfig(TIM3);
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1; //ARR
TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1; //PSC
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
TIM_ICInitTypeDef TIM_ICInitStructure;
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;//设置TIM IC通道为TIM_Channel_1,即选择TIM3定时器的通道1
TIM_ICInitStructure.TIM_ICFilter = 0xF;//设置TIM IC的输入捕获过滤器为0xF,这意味着当输入信号的上升沿或下降沿被检测到时,TIM IC将产生中断
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;//设置TIM IC的中断极性为上升沿触发,这意味着当输入信号的上升沿被检测到时,TIM IC将产生中断
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;//设置TIM IC的输入捕获预分频器为1,这意味着输入信号的上升沿或下降沿每过1个TIM时钟周期,TIM IC就会产生一次中断
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;//设置TIM IC的输入捕获选择为直接TI模式,这意味着TIM IC将在每个输入通道上独立地产生中断
//初始化TIM3定时器的TIM IC
TIM_ICInit(TIM3, &TIM_ICInitStructure);
//选择TIM3定时器的通道1作为输入触发源,并设置触发源的预分频值为1
TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);
//将TIM3定时器设置为从模式,并使能定时器
TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);
//使能TIM3定时器的时钟
TIM_Cmd(TIM3, ENABLE);
}
uint32_t IC_GetFreq(void)
{
return 1000000 / (TIM_GetCapture1(TIM3) + 1);
}
IC.h文件
#ifndef __IC_H
#define __IC_H
void IC_Init(void);
uint32_t IC_GetFreq(void);
#endif
PWMI模式(PWM输入模式)测频率和占空比
第一步:新建工程
第二步:连接线路
第三步:编写程序
实验现象:OLED屏幕第一行显示“Freq:01000Hz”,第二行显示“Duty:50%”。
main.c文件
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "PWM.h"
#include "IC.h"
int main (void)
{
OLED_Init();
PWM_Init();
IC_Init();
OLED_ShowString(1, 1, "Freq:00000Hz");
OLED_ShowString(2, 1, "Duty:00%");
PWM_SetPrescaler(720 - 1); //Freq = 72M / (PSC + 1) / 100
PWM_SetCompare1(50); //Duty = CCR / 100
while (1)
{
OLED_ShowNum(1, 6, IC_GetFreq(), 5);
OLED_ShowNum(2, 6, IC_GetDuty(), 2);
}
}
IC.c文件
#include "stm32f10x.h" // Device header
void IC_Init(void )
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
TIM_InternalClockConfig(TIM3);
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1; //ARR
TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1; //PSC
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
TIM_ICInitTypeDef TIM_ICInitStructure;
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;//设置TIM IC通道为TIM_Channel_1,即选择TIM3定时器的通道1
TIM_ICInitStructure.TIM_ICFilter = 0xF;//设置TIM IC的输入捕获过滤器为0xF,这意味着当输入信号的上升沿或下降沿被检测到时,TIM IC将产生中断
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;//设置TIM IC的中断极性为上升沿触发,这意味着当输入信号的上升沿被检测到时,TIM IC将产生中断
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;//设置TIM IC的输入捕获预分频器为1,这意味着输入信号的上升沿或下降沿每过1个TIM时钟周期,TIM IC就会产生一次中断
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;//设置TIM IC的输入捕获选择为直接TI模式,这意味着TIM IC将在每个输入通道上独立地产生中断
//初始化TIM3定时器的TIM IC
/*
TIM_ICInit(TIM3, &TIM_ICInitStructure);
TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;//设置TIM IC通道为TIM_Channel_2,即选择TIM3定时器的通道2
TIM_ICInitStructure.TIM_ICFilter = 0xF;//设置TIM IC的输入捕获过滤器为0xF,这意味着当输入信号的上升沿或下降沿被检测到时,TIM IC将产生中断
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;//设置TIM IC的中断极性为下降沿触发,这意味着当输入信号的下降沿被检测到时,TIM IC将产生中断
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;//设置TIM IC的输入捕获预分频器为1,这意味着输入信号的上升沿或下降沿每过1个TIM时钟周期,TIM IC就会产生一次中断
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_IndirectTI;//设置TIM IC的输入捕获选择为交叉TI模式
//初始化TIM3定时器的TIM IC
TIM_ICInit(TIM3, &TIM_ICInitStructure);
*/
TIM_PWMIConfig(TIM3 ,&TIM_ICInitStructure );
//选择TIM3定时器的通道1作为输入触发源,并设置触发源的预分频值为1
TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);
//将TIM3定时器设置为从模式,并使能定时器
TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);
//使能TIM3定时器的时钟
TIM_Cmd(TIM3, ENABLE);
}
uint32_t IC_GetFreq(void)
{
return 1000000 / (TIM_GetCapture1(TIM3) + 1);
}
uint32_t IC_GetDuty(void)
{
return (TIM_GetCapture2(TIM3)+1)*100 / (TIM_GetCapture1(TIM3)+1);
}
IC.h文件
#ifndef __IC_H
#define __IC_H
void IC_Init(void);
uint32_t IC_GetFreq(void);
uint32_t IC_GetDuty(void);
#endif
TIM编码器接口
编码器接口简介
正交编码器
编码器接口基本结构
工作模式
实例(均不反相)
实例(TI1反相)
编码器接口测速
第一步:新建工程
第二步:连接线路
第三步:编写程序
实验现象:自动对编码器进行计次,从而得到旋转编码器的速度。向右慢速旋转旋转编码器,OLED显示屏上显示的数值为正,计次比较小;向右快速旋转,计次就会增大;向左旋转,计次数值为负。
main.c文件
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "Timer.h"
#include "Encoder.h"
int16_t Speed;
int main (void)
{
OLED_Init ();
Timer_Init ();
Encoder_Init ();
OLED_ShowString (1,1,"Speed:");
while(1)
{
OLED_ShowSignedNum (1,7,Speed ,5);
}
}
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
{
Speed = Encoder_Get ();
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
}
Encoder.c文件
#include "stm32f10x.h" // Device header
void Encoder_Init(void )
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1; //ARR
TIM_TimeBaseInitStructure.TIM_Prescaler = 1 - 1; //PSC
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
TIM_ICInitTypeDef TIM_ICInitStructure;
TIM_ICStructInit (&TIM_ICInitStructure );
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
TIM_ICInitStructure.TIM_ICFilter = 0xF;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInit(TIM3, &TIM_ICInitStructure);
TIM_ICStructInit (&TIM_ICInitStructure );
TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
TIM_ICInitStructure.TIM_ICFilter = 0xF;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInit(TIM3, &TIM_ICInitStructure);
//配置 TIMx 编码器接口。
TIM_EncoderInterfaceConfig(TIM3 ,TIM_EncoderMode_TI12 ,TIM_ICPolarity_Rising ,TIM_ICPolarity_Rising );
/*
用来配置TIM3定时器的编码器接口的。
TIM_EncoderMode_TI12:这是编码器的模式,表示使用TI12模式。在这种模式下,编码器接口会在每个输入捕获事件发生时更新一个计数器,
这个计数器的值会被用来对定时器的溢出时间进行“取模”运算,从而产生一个PWM占空比的值。
TIM_ICPolarity_Rising:这是输入捕获极性,表示当输入信号的上升沿或下降沿被检测到时,TIM IC将产生中断。
TIM_ICPolarity_Rising:这是输入捕获极性,表示当输入信号的上升沿或下降沿被检测到时,TIM IC将产生中断。
*/
TIM_Cmd (TIM3 ,ENABLE );
}
int16_t Encoder_Get(void )
{
int16_t Temp;
Temp = TIM_GetCounter (TIM3 );
TIM_SetCounter (TIM3 ,0);
return Temp ;
}
Encoder.h文件
#ifndef __ENCODER_H
#define __ENCODER_H
void Encoder_Init(void );
int16_t Encoder_Get(void );
#endif