STM32定时器四大功能之定时器编码接口

1什么是编码器接口?

编码器接口接受编码器的正交信号,根据编码器产生的正交信号脉冲控制CNT的自增和自减,从而指示编码器的旋转方向和旋转速度。

每个高级定时器和通用定时器都有一个编码器接口,同时正交编码器产生的正交信号分为正转和反转,通过两个GPIO口产生的正交信号来决定是正转还是反转。

2.编码器接口基本结构

CNT的自增还是自减受编码器控制,输入捕获的前两个通道通过GPIO口连接编码器的A相和B相,再通过滤波器和边沿极性选择,产生TI1FP1和TI2FP2信号通向编码器接口,同时编码器接口根据编码器的旋转方向控制CNT的计数方向,编码器正转,CNT自增,编码器翻转,CNT自减。编码器接口相当于使用了一个带有方向选择的外部时钟。

 3.通用定时器基本框图

如下图所示,我们可以看到TIMx_CH1和TIMx_CH2输入捕获的前两个通道,产生TI1FP1和TI2FP2信号通向编码器接口。

 4.编码器模块Encoder代码编写

(1).开启RCC时钟,包括GPIO和定时器3的时钟。

    //1.开启时钟TIM3的时钟线是APB1
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
    //2.开启GPIOA时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);

(2).配置GPIO,把PA6和PA7引脚配置成输入模式(PA6为TIM3_CH1通道,PA7为TIM3_CH2通道)

    GPIO_InitTypeDef GPIO_Inistructure;
	GPIO_Inistructure.GPIO_Mode= GPIO_Mode_IPU;//PWM输入设置为上拉输入
	GPIO_Inistructure.GPIO_Pin= GPIO_Pin_6 | GPIO_Pin_7;
	GPIO_Inistructure.GPIO_Speed=  GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_Inistructure);//读取结构体的参数

(3).时基单元初始化。配置预分频器,预分频器选择不分频,ARR自动重装值给最大,只配置CNT即可。

   	//3.时基单元初始化
     TIM_TimeBaseInitTypeDef  TIM_timBaseInitStructure;
	 TIM_timBaseInitStructure.TIM_ClockDivision= TIM_CKD_DIV1;//一分频
	 TIM_timBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;//向上计数
	 TIM_timBaseInitStructure.TIM_Period=65536-1;//ARR
	 TIM_timBaseInitStructure.TIM_Prescaler=1-1;//PSC 选择不分频
	 TIM_timBaseInitStructure.TIM_RepetitionCounter=0;//重复计数器是高级定时器才有的
	 TIM_TimeBaseInit(TIM3,&TIM_timBaseInitStructure);

(4).配置输入捕获单元(包含滤波器和边沿极性选择)

 //4.配置输入捕获单元通道一和通道2
	TIM_ICInitTypeDef TIM_ICInitStructure;
	TIM_ICStructInit(&TIM_ICInitStructure);//结构体初始化
	TIM_ICInitStructure.TIM_Channel=TIM_Channel_1;//定时器3的通道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;//定时器3的通道2
	TIM_ICInitStructure.TIM_ICFilter=0xF;//滤波器
	TIM_ICInitStructure.TIM_ICPolarity= TIM_ICPolarity_Rising;//边沿检测极性选择上升沿触发,代表输入波形极性不翻转
    TIM_ICInit(TIM3,&TIM_ICInitStructure);

 5.配置编码器接口,A/B相均计数,A/B波形输入选择Rising,极性不反转

//5配置编码器接口,A/B相均计数,A/B波形输入选择Rising,极性不反转
	TIM_EncoderInterfaceConfig(TIM3,TIM_EncoderMode_TI12,TIM_ICPolarity_Rising,TIM_ICPolarity_Rising);

 6. 启动定时器

	//6.启动定时器
	TIM_Cmd(TIM3,ENABLE);

7.得到CNT的值


//得到CNT的值
int16_t  Encoder_Get(void)
{
     int16_t temp;
	 temp=TIM_GetCounter(TIM3);//得到CNT的值
	 TIM_SetCounter(TIM3,0);//将CNT清0
	return temp;
}

5.用TIM2中断函数计数

目的:调用TIM2中断函数,每产生一个更新事件,记一次数,即测速。在TIM2产生的中断函数中,实现对TIM3编码器产生的正交信号进行计数。
在main.c函数中实现TIM2中断函数的调用,在中断函数中实现计数的功能

注:中断函数的更新事件的标志位,在程序进行完之后要对中断标志位进行清除。

#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();		//定时器2初始化
	Encoder_Init();		//编码器初始化
	
	/*显示静态字符串*/
	OLED_ShowString(1, 1, "Speed:");	
	
	while (1)
	{
		OLED_ShowSignedNum(1, 7, Speed, 5);	//不断刷新显示编码器测得的最新速度
	}
}


 //  函    数:TIM2中断函数
void TIM2_IRQHandler(void)
{
	if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)		//判断是否是TIM2的更新事件触发的中断
	{
		Speed = Encoder_Get();								//每隔固定时间段读取一次编码器计数增量值,即为速度值
		TIM_ClearITPendingBit(TIM2, TIM_IT_Update);			//清除TIM2更新事件的中断标志位
															//中断标志位必须清除
															//否则中断将连续不断地触发,导致主程序卡死
	}
}

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值