Table of contents
3: Basic structure of encoder interface
A: Encoder interface speed measurement
1: Resume
Encoder Interface encoder interface
The encoder interface can receive signals from incremental (quadrature) encoders and automatically control the CNT to increase or decrease based on the quadrature signal pulses generated by the encoder rotation, thereby indicating the position, rotation direction and rotation speed of the encoder.
Each advanced timer and general timer has 1 encoder interface
The two input pins are borrowed from channel 1 and channel 2 of the input capture
2: Quadrature encoder
When the encoder rotates, it will output the following square wave signal
3: Basic structure of encoder interface
The encoder interface is valid for both rising and falling edges. Both rising and falling edges need to be counted. Therefore, in the encoder interface mode, the edge detection polarity selection is no longer the edge polarity selection. It is the polarity selection of high and low levels.
Select the parameters of the rising edge------the signal passes through directly, and the high and low level polarity is not reversed---5: Polarity reversal
Select the parameter of the rising edge-------the signal comes through a NOT gate, and the high and low level polarity is reversed----5: Polarity reversal
4: Encoder working mode
Forward rotation states count upwards, and reverse rotation states count downwards----TIM_EncoderMode_TI12
The 2 modes above -- only count in one
5: Polarity reversal
None are reversed
TI1 inversion
A: Encoder interface speed measurement
1: Connection diagram
2: Function introduction
The function in the stm32f10x tim.h file ------ configure the timer encoder interface
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);
Parameters : The second parameter---see 4 above: Encoder working mode
The third (IC1 polarity) and fourth (IC2 polarity) parameters are the same: ---- 3: Edge detection polarity selection in the basic structure of the encoder interface
The rising edge here does not mean that the rising edge is valid, because the encoder interface is always valid on both the rising edge and the falling edge. The rising edge parameter here represents that the high and low level polarities are not reversed -----5: polarity reversal
The function in the stm32f10x tim.h file------reads the value of the counter CNT
uint16_t TIM_GetCounter(TIM_TypeDef* TIMx)
TIM_SetCounter : The counter is cleared when 65535 is read.
The function in the stm32f10x tim.h file ------- reassigns CNT
void TIM_SetCounter(TIM_TypeDef* TIMx, uint16_t Counter)
TIM_SetCounter: The second parameter: after reading CNT, change it and assign a new value; here we choose to clear it to zero
Functions in the stm32f10x tim.h file------interrupt flag bits and flag bit clearing
ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT);
void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT)
TIM_GetITStatus : Get whether the interrupt flag bit is set to 1 ( detect the status of the external interrupt )
TIM_ClearITPendingBit : Clear the interrupt pending flag bit
3: Steps
To configure the timer encoder interface
1: RCC turns on the clock, (the clocks of TIM peripherals---RCC_APB1PeriphClockCmd and GPIO peripherals--RCC_APB2PeriphClockCmd are turned on)
2: Configure GPIO----GPIO_Init (write the second step last)
3: Configure time base unit-----TIM_TimeBaseInit()
4: Configure input capture (ic ) ----TIM_ICInit()---IC needs to be configured 2 articles see code
5: Configure the timer encoder interface---TIM_EncoderInterfaceConfig()
6: Start the timer-----TIM_Cmd()
Timer starting steps
1: Turn on the clock (RCC)
2: Select the clock of the time base unit (TIM_InternalClockConfig--select the internal clock )
3: Configure time base unit (TIM_TimeBaseInit)
4: Enable update interrupt (TIM_ITConfig interrupt clock control )
5: Configuration of NICV (see 02: STM32)
6: Start timer (TIM_Cmd)
Steps to start the timer. For details, see: 03: TIM timer.
4: Code
#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);
}
}
Only the channel 1 and channel 2 interfaces of the TIM timer can be used as encoder interfaces
Channel 3 and channel 4 cannot be used as encoder interfaces
IC needs to be configured twice
B: Encoder interface counting
This code automatically counts times through the timer's encoder interface;
The previous code was to trigger an external interrupt, and then manually count the times in the interrupt function - see 02: STM32--EXTI external interrupt
1: Connection diagram
2: Code
#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);
}
}
The TIM chapter is completed