06:TIM定时器功能------编码器接口功能

目录

1:简历

2: 正交编码器

 3:编码器接口基本结构

 4:编码器的工作模式

5:极性反转

A:编码器接口测速

1:连接图

 2:函数介绍

3:步骤

4:代码

B:编码器接口计次

1:连接图

2:代码


1:简历

        Encoder Interface 编码器接口

        编码器接口可接收增量(正交)编码器的信号,根据编码器旋转产生的正交信号脉冲,自动控制CNT自增或自减,从而指示编码器的位置、旋转方向和旋转速度

        每个高级定时器和通用定时器都拥有1个编码器接口

        两个输入引脚借用了输入捕获的通道1和通道2

2: 正交编码器

当编码器旋转起来的时候, 会输出下面的方波信号

 3:编码器接口基本结构

        编码器接口,都是上升沿和下降沿都有效的 , 上升沿和下降沿都需要计次 ,  所以在编码器接口模式下 ,  边沿检测极性选择就不再是边沿的极性选择了 ,  而是高低电平的极性选择.

        选择上升沿的参数------就是信号直通过来,高低电平极性不反转---5:极性反转

        选择上升沿的参数-------就是信号通过一个非门过来,高低电平极性反转----5:极性反转

        

 4:编码器的工作模式

         正转的状态都向上计数,   反转的状态都向下计数----TIM_EncoderMode_TI12

        上面的2个模式--只在一个计数

5:极性反转

均不反转

 TI1反转

A:编码器接口测速

1:连接图

 2:函数介绍

在stm32f10x tim.h文件中的函数------配置定时器编码器接口

void TIM_EncoderInterfaceConfig(TIM_TypeDef* TIMx, uint16_t TIM_EncoderMode,
                                uint16_t TIM_IC1Polarity, uint16_t TIM_IC2Polarity)
 

  TIM_EncoderInterfaceConfig  TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);

参数 : 第二个参数---见上面的 4:编码器的工作模式

           第三个(IC1极性)和第四个(IC2极性)参数一样 : ----   3:编码器接口基本结构中的 边沿检测极性选择

        这里的上升沿并不代表上升沿有效 , 因为编码器接口始终都是上升沿、下降沿都有效的 , 这里的上升沿参数代表的是高低电平极性不反转-----5:极性反转

在stm32f10x tim.h文件中的函数------读取计数器CNT的值

uint16_t TIM_GetCounter(TIM_TypeDef* TIMx)

TIM_SetCounter :计数器读取到了65535清零

在stm32f10x tim.h文件中的函数------给CNT重新赋值

void TIM_SetCounter(TIM_TypeDef* TIMx, uint16_t Counter)
 

TIM_SetCounter : 第二给参数: 读取CNT后,改它赋一个新的值;  我们这里选择把他清零

在stm32f10x tim.h文件中的函数------中断标志位和标志位清零

ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT);

void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT)
 

TIM_GetITStatus: 获取中断标志位是否被置1了(检测外部中断的状态)

TIM_ClearITPendingBit清除中断挂起标志位

3:步骤

配置定时器编码器接口的步骤

1 : RCC开启时钟,(TIM外设---RCC_APB1PeriphClockCmd和GPIO外设----RCC_APB2PeriphClockCmd的时钟打开)

2 : 配置GPIO----GPIO_Init    (最后写第二步)

3 :  配置时基单元-----TIM_TimeBaseInit()

4 :  配置输入捕获(ic)----TIM_ICInit()--- IC需要配置2篇见代码

5 :   配置定时器编码器接口---TIM_EncoderInterfaceConfig()

6 : 启动定时器-----TIM_Cmd()

定时器开启步骤

1: 开启时钟 (RCC)

2: 选择时基单元的时钟 (TIM_InternalClockConfig--选择内部时钟)

3: 配置时基单元  (TIM_TimeBaseInit)

4 : 使能更新中断( TIM_ITConfig中断时钟控制)

5: NICV的配置   (见 02: STM32)

6: 启动定时器  (TIM_Cmd)

定时器开启步骤    详情见:03:TIM定时器

4:代码

#include "stm32f10x.h"                  // Device header
#include "OLED.h"
#include "Timer.h"
#include "Encoder.h"
#include "Delay.h"

void Timer_init(void){
//第一步是开启时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
//第二步,选择时基单元的时钟 (stm23上电默认使用的是内部时钟,这一行代码可以省略)
TIM_InternalClockConfig(TIM2);
//第三步,配置时基单元
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数
/*计数器溢出频率:CK_CNT_OV = CK_CNT / (ARR + 1)
					       = CK_PSC / (PSC + 1) / (ARR + 1
	定时频率=72M/(PSC+1)/(ARR+1)
	72MHZ=72000KHZ
	72000KHZ/7200=10KHZ=10000HZ
	T=1/F   T=1/10000hz=0.0001s=0.1ms
	然后以0.1ms的周期计10 000个数,所以就是1s
	
	*/
TIM_TimeBaseInitStructure.TIM_Period=10000-1;			//自动重装载寄存器ARR
TIM_TimeBaseInitStructure.TIM_Prescaler=7200-1;  //预分频器PSC
TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;//高级定时器特有的(重复寄存器)
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
	
//第四使能更新中断

TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
	
	
TIM_ClearFlag(TIM2, TIM_FLAG_Update);//手动清除更新中断标志位
	
//第五步NICV的配置
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	
	
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
NVIC_Init(&NVIC_InitStructure);
//第六步启动定时器
TIM_Cmd(TIM2,ENABLE);
}

void Encoder_Init(void)
{
	//1:配置RCC,把我们这里涉及的外设的时钟都打开(GPIO,AFIO)
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	//2:配置GPIO,选择我们的端口为输入模式  注意打开了2个中断
	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(GPIOB, &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);
	//配置输入捕获(IC)
	TIM_ICInitTypeDef TIM_ICInitStructure;
	TIM_ICStructInit(&TIM_ICInitStructure);
	TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
	TIM_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Rising;
	TIM_ICInitStructure.TIM_ICFilter = 0xF;
	TIM_ICInit(TIM3, &TIM_ICInitStructure);
	
	
	TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
	TIM_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Rising;
	TIM_ICInitStructure.TIM_ICFilter = 0xF;
	TIM_ICInit(TIM3, &TIM_ICInitStructure);
	//配置定时器编码器接口
	TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
	//启动定时器
	TIM_Cmd(TIM3, ENABLE);
}



int16_t Encoder_Get(void)
{
	int16_t Temp;
	//读取CNT的值
	Temp = TIM_GetCounter(TIM3);
	TIM_SetCounter(TIM3, 0);
	return Temp;
}



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);
		//Delay_ms(1000);
	}
}

void TIM2_IRQHandler(){
	//检查中断标志位
	if (	TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)
	{
		//清除标志位
		//Num++;
		Speed=Encoder_Get();
		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
	
	}


}

        只有TIM定时器的通道1和通道2接口可以作为 编码器接口

        通道3和通道4并不能做为编码器接口

IC需要配置2遍

B:编码器接口计次

        这个代码是通过定时器的编码器接口,来自动计次;  

        之前的代码是通过触发外部中断 , 然后在中断函数里手动进行计次-----见02:STM32--EXTI外部中断

1:连接图

2:代码

#include "stm32f10x.h"                  // Device header
#include "OLED.h"
#include "Timer.h"
#include "Encoder.h"
#include "Delay.h"


void Encoder_Init(void)
{
	//1:配置RCC,把我们这里涉及的外设的时钟都打开(GPIO,AFIO)
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	//2:配置GPIO,选择我们的端口为输入模式  
	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(GPIOB, &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);
	//配置输入捕获(IC)
	TIM_ICInitTypeDef TIM_ICInitStructure;
	TIM_ICStructInit(&TIM_ICInitStructure);
	TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
	TIM_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Rising;
	TIM_ICInitStructure.TIM_ICFilter = 0xF;
	TIM_ICInit(TIM3, &TIM_ICInitStructure);
	
	
	TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
	TIM_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Rising;
	TIM_ICInitStructure.TIM_ICFilter = 0xF;
	TIM_ICInit(TIM3, &TIM_ICInitStructure);
	//配置定时器编码器接口
	TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
	//启动定时器
	TIM_Cmd(TIM3, ENABLE);
}



int16_t Encoder_Get(void)
{
	
	return  TIM_GetCounter(TIM3);
}



int main(void)
{
	OLED_Init();
	
	Encoder_Init();
	OLED_ShowString(1, 1, "Speed:");
	
	while (1)
	{
		OLED_ShowSignedNum(1,7,Encoder_Get(),5);
		
	}
}

TIM篇章完结

猜你喜欢

转载自blog.csdn.net/m0_74739916/article/details/132500035
今日推荐