【单片机】STM32单片机读取旋转编码器,TIM定时器编码器模式捕获,程序

这篇具有很好参考价值的文章主要介绍了【单片机】STM32单片机读取旋转编码器,TIM定时器编码器模式捕获,程序。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

旋转编码器介绍

旋转编码器简单来说,就是会输出2个PWM,依据相位可以知道旋转方向,依据脉冲个数可以知道旋转的角度。一般旋转一圈有一个固定数值的脉冲个数。
旋转编码器广泛用于电机、或者角度传感器,STM32的定时器可以直接接入这两个波形获取到信息。

stm32旋转编码器,单片机,单片机,stm32,旋转编码器程序,定时器解码
前两个引脚(接地和Vcc)用于为编码器供电,我这里采用3.3V的供电。除了以顺时针方向和逆时针方向旋转旋钮外,编码器还有一个开关(低电平有效),按下内部的旋钮可以按下该开关。来自此开关的信号通过引脚3(Switch)获得。最后它有两个输出引脚。

stm32旋转编码器,单片机,单片机,stm32,旋转编码器程序,定时器解码

主程序逻辑直接检测

主程序中不要加延时,否则可能检测不到下降沿。

//旋转编码器
//CLK–PA0
//DT—PA1
//SW—PA2

3.3V供电。


#include "sys.h"
#include "usart.h"

//旋转编码器
//CLK--PA0
//DT---PA1
//SW---PA2
#define CLK_in  PAin(0)
#define DT_in   PAin(1)
#define SW_in  PAin(2)

u32 encoder_cnt = 100000;//旋转脉冲计数
u8 direction = 0;//旋转方向 1正传

u8 dt_high_flag = 0;

void rotary_encoder_Init(void) {
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);                          /* 使能时钟 */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;            /* 设置成上拉输入 */
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;         //IO口速度为50MHz
    GPIO_Init(GPIOA, &GPIO_InitStructure);                     //根据设定参数初始化PC13
}


int main(void) {
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);               /* 设置NVIC中断分组2:2位抢占优先级,2位响应优先级 */
    delay_init();                                                   /* 延时函数初始化 */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
    GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);      /* 关闭jtag,使能SWD,可以用SWD模式调试 */
    delay_ms(500);                                                /* 等待稳定 */
    uart_init(115200);

    rotary_encoder_Init();

    while (1) {
        if (SW_in == 0) {
            delay_ms(10);
            if (SW_in == 0) {
                printf("SW_in=0\r\n");
                while (SW_in == 0);
            }
        }

        //DT_in是下降沿的时候,如果CLK_in是高电平,那么就是正转,如果CLK_in是低电平,那么就是反转
        if (DT_in == 1 && dt_high_flag == 0) {
            dt_high_flag = 1;
        }
        if (DT_in == 0 && dt_high_flag == 1) {
            dt_high_flag = 0;
            if (CLK_in == 1) {
                direction = 0;
            } else {
                direction = 1;
            }
            if (direction == 1) {
                encoder_cnt++;
            } else {
                encoder_cnt--;
            }
            printf("direction=%d\r\n", (int) direction);
            printf("encoder_cnt=%d\r\n", encoder_cnt);
        }
				

    }
}



顺时针转一圈可以得到一些结果,这个旋钮有明显的触感。顺时针转一个刻度就加1,逆时针转一个刻度就减1。

direction=1
encoder_cnt=100001
direction=1
encoder_cnt=100002
direction=1
encoder_cnt=100003
direction=1
encoder_cnt=100004
direction=1
encoder_cnt=100005
direction=1
encoder_cnt=100006
direction=1
encoder_cnt=100007
direction=1
encoder_cnt=100008
direction=1
encoder_cnt=100009
direction=0
encoder_cnt=100008
direction=1
encoder_cnt=100009
direction=1
encoder_cnt=100010
direction=1
encoder_cnt=100011
direction=1
encoder_cnt=100012
direction=1
encoder_cnt=100013
direction=1
encoder_cnt=100014
direction=1
encoder_cnt=100015
direction=1
encoder_cnt=100016
direction=1
encoder_cnt=100017
direction=1
encoder_cnt=100018
direction=1
encoder_cnt=100019
direction=1
encoder_cnt=100020

用外部中断检测下降沿

将DT输入设置为外部中断 ,下降沿触发,明显好用多了。


#include "sys.h"
#include "usart.h"

//旋转编码器
//CLK--PA0
//DT---PA1
//SW---PA2
#define CLK_in  PAin(0)
#define DT_in   PAin(1)
#define SW_in  PAin(2)

u32 encoder_cnt = 100000;//旋转脉冲计数
u8 direction = 0;//旋转方向 1正传

u8 dt_high_flag = 0;


void rotary_encoder_Init(void) {
    EXTI_InitTypeDef EXTI_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
		GPIO_InitTypeDef GPIO_InitStructure;
	
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);                           /* 使能时钟 */
    GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);                       /* 关闭JTAG功能 */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);                          /* 使能时钟 */

    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;            /* 设置成上拉输入 */
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;         //IO口速度为50MHz
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    //将DT_in PAin(1)设置为外部中断,下降沿触发
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource1);
    EXTI_InitStructure.EXTI_Line = EXTI_Line1;                /* 外部中断线1 */
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;       /* 设置为中断请求 */
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;   /* 下降沿触发 */
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;                 /* 使能中断 */
    EXTI_Init(&EXTI_InitStructure);                           /* 配置 */

    NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;          /* 外部中断1 */
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;   /* 抢占优先级2 */
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;          /* 子优先级2 */
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                /* 使能中断 */
    NVIC_Init(&NVIC_InitStructure);                                /* 配置 */

}
void EXTI1_IRQHandler(void) {
    if (CLK_in == 1) {
        direction = 0;
    } else {
        direction = 1;
    }
    if (direction == 1) {
        encoder_cnt++;
    } else {
        encoder_cnt--;
    }
    printf("direction=%d\r\n", (int) direction);
    printf("encoder_cnt=%d\r\n", encoder_cnt);
    EXTI_ClearITPendingBit(EXTI_Line1);                         /* 清除LINE1上的中断标志位 */
}


int main(void) {
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);               /* 设置NVIC中断分组2:2位抢占优先级,2位响应优先级 */
    delay_init();                                                   /* 延时函数初始化 */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
    GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);      /* 关闭jtag,使能SWD,可以用SWD模式调试 */
    delay_ms(500);                                                /* 等待稳定 */
    uart_init(115200);

    rotary_encoder_Init();

    while (1) {
        if (SW_in == 0) {
            delay_ms(10);
            if (SW_in == 0) {
                printf("SW_in=0\r\n");
                while (SW_in == 0);
            }
        }

    }
}



当然需要记得添加库文件:
stm32旋转编码器,单片机,单片机,stm32,旋转编码器程序,定时器解码

定时器直接解码旋转编码器

下图是定时器相关引脚:

stm32旋转编码器,单片机,单片机,stm32,旋转编码器程序,定时器解码

STM32中文参考手册V10.pdf

普通定时器TIM2~TIM5都有这样的功能:
stm32旋转编码器,单片机,单片机,stm32,旋转编码器程序,定时器解码

stm32旋转编码器,单片机,单片机,stm32,旋转编码器程序,定时器解码

stm32旋转编码器,单片机,单片机,stm32,旋转编码器程序,定时器解码

stm32旋转编码器,单片机,单片机,stm32,旋转编码器程序,定时器解码

stm32旋转编码器,单片机,单片机,stm32,旋转编码器程序,定时器解码

定时器的编码器模式

这张图是很重要的,如果我们这样配置:

TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI1, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//使用编码器模式1

TIM_EncoderMode_TI1就是编码模式,TIM_ICPolarity_Rising和TIM_ICPolarity_Rising就是信号捕获边沿选择。

这张图告诉我们,编码器接收到AB相位是要同步的时候才会计数,有毛刺编码器是不会计数的。

而且还告诉我们,编码器顺时针旋转,逆时针旋转,我们的计数器是会对应增加或者减小的。

stm32旋转编码器,单片机,单片机,stm32,旋转编码器程序,定时器解码

TIM2定时器编码器程序

stm32旋转编码器,单片机,单片机,stm32,旋转编码器程序,定时器解码

#include "sys.h"
#include "usart.h"

//旋转编码器
//CLK--PA0
//DT---PA1
#define CLK_in  PAin(0)
#define DT_in   PAin(1)

/**************************************************************************
函数功能:把TIM2初始化为编码器接口模式
**************************************************************************/
void Encoder_Init_TIM2(u16 arr, u16 psc) {
    GPIO_InitTypeDef GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_ICInitTypeDef TIM_ICInitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//使能TIM4时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;       //选择你要设置的IO口
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;       //设置传输速率
    GPIO_Init(GPIOA, &GPIO_InitStructure);          /* 初始化GPIO */

    TIM_TimeBaseStructure.TIM_Period = arr;   //自动装载值
    TIM_TimeBaseStructure.TIM_Prescaler = psc; //分频系数
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //设置向上计数模式
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

    TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; //通道1
    TIM_ICInitStructure.TIM_ICFilter = 0x03;  //滤波
    TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_BothEdge;
    TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //分频系数
    TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;//PA0直接映射到TI1
    TIM_ICInit(TIM2, &TIM_ICInitStructure);

    TIM_ICInitStructure.TIM_Channel = TIM_Channel_2; //通道1
    TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;//PA1直接映射到TI2
    TIM_ICInit(TIM2, &TIM_ICInitStructure);

    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;//中断通道
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;//抢占优先级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;        //子优先级
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;            //IRQ通道使能
    NVIC_Init(&NVIC_InitStructure);
		
		TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI1, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//使用编码器模式1
		//TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//使用编码器模式3
    TIM_ICStructInit(&TIM_ICInitStructure); //将结构体中的内容缺省输入
    TIM_ICInitStructure.TIM_ICFilter = 10;
    TIM_ICInit(TIM2, &TIM_ICInitStructure);
    TIM_ClearFlag(TIM2, TIM_FLAG_Update);//清除TIM的更新标志位
    TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);//运行更新中断

    TIM_SetCounter(TIM2, 10000);//初始化计数器初值

    TIM_Cmd(TIM2, ENABLE); //使能定时器

}


// 计数超过arr就会产生溢出中断
// 也可以把NVIC_Init(&NVIC_InitStructure);注释掉就不要开启中断
void TIM2_IRQHandler(void) {
    if (TIM2->SR & 0X0001)//溢出中断
    {
        printf("interrupt\r\n");
    }
    TIM2->SR &= ~(1 << 0);//清除中断标志位
}


short Read_Encoder(u8 TIMX) {
    unsigned Encoder_TIM;
    switch (TIMX) {
        case 2:
            Encoder_TIM = (short) TIM2->CNT;
            TIM2->CNT = 0;
            break;
        case 3:
            Encoder_TIM = (short) TIM3->CNT;
            TIM3->CNT = 0;
            break;
        case 4:
            Encoder_TIM = (short) TIM4->CNT;
            break;
        default:
            Encoder_TIM = 0;
    }
    return Encoder_TIM;
}


int main(void) {
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);               /* 设置NVIC中断分组2:2位抢占优先级,2位响应优先级 */
    delay_init();                                                   /* 延时函数初始化 */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
    GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);      /* 关闭jtag,使能SWD,可以用SWD模式调试 */
    delay_ms(500);                                                /* 等待稳定 */
    uart_init(115200);

    Encoder_Init_TIM2(0xffff, 0); //初始化TIM2为编码器接口模式

    while (1) {
        printf("%d \r\n", (int) TIM_GetCounter(TIM2));

    }
}	



旋转编码器就可以看到计数器的变化了:
stm32旋转编码器,单片机,单片机,stm32,旋转编码器程序,定时器解码

TIM3定时器编码器程序

类似地写程序即可。

stm32旋转编码器,单片机,单片机,stm32,旋转编码器程序,定时器解码

#include "sys.h"
#include "usart.h"

//旋转编码器
//CLK--PA6
//DT---PA7
#define CLK_in  PAin(6)
#define DT_in   PAin(7)

/**************************************************************************
函数功能:把TIM3初始化为编码器接口模式
**************************************************************************/
void Encoder_Init_TIM3(u16 arr, u16 psc) {
    GPIO_InitTypeDef GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_ICInitTypeDef TIM_ICInitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);//使能TIM4时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;       //选择你要设置的IO口
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;       //设置传输速率
    GPIO_Init(GPIOA, &GPIO_InitStructure);          /* 初始化GPIO */

    TIM_TimeBaseStructure.TIM_Period = arr;   //自动装载值
    TIM_TimeBaseStructure.TIM_Prescaler = psc; //分频系数
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //设置向上计数模式
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

    TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; //通道1
    TIM_ICInitStructure.TIM_ICFilter = 0x03;  //滤波
    TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_BothEdge;
    TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //分频系数
    TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;//PA6直接映射到TI1
    TIM_ICInit(TIM3, &TIM_ICInitStructure);

    TIM_ICInitStructure.TIM_Channel = TIM_Channel_2; //通道1
    TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;//PA7直接映射到TI2
    TIM_ICInit(TIM3, &TIM_ICInitStructure);

    NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;//中断通道
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;//抢占优先级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;        //子优先级
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;            //IRQ通道使能
    NVIC_Init(&NVIC_InitStructure);

    TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI1, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//使用编码器模式1
    //TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//使用编码器模式3
    TIM_ICStructInit(&TIM_ICInitStructure); //将结构体中的内容缺省输入
    TIM_ICInitStructure.TIM_ICFilter = 10;
    TIM_ICInit(TIM3, &TIM_ICInitStructure);
    TIM_ClearFlag(TIM3, TIM_FLAG_Update);//清除TIM的更新标志位
    TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);//运行更新中断

    TIM_SetCounter(TIM3, 10000);//初始化计数器初值

    TIM_Cmd(TIM3, ENABLE); //使能定时器

}



// 计数超过arr就会产生溢出中断
// 也可以把NVIC_Init(&NVIC_InitStructure);注释掉就不要开启中断
void TIM3_IRQHandler(void) {
    if (TIM3->SR & 0X0001)//溢出中断
    {
        printf("interrupt\r\n");
    }
    TIM3->SR &= ~(1 << 0);//清除中断标志位
}


short Read_Encoder(u8 TIMX) {
    unsigned Encoder_TIM;
    switch (TIMX) {
        case 2:
            Encoder_TIM = (short) TIM2->CNT;
            TIM2->CNT = 0;
            break;
        case 3:
            Encoder_TIM = (short) TIM3->CNT;
            TIM3->CNT = 0;
            break;
        case 4:
            Encoder_TIM = (short) TIM4->CNT;
            break;
        default:
            Encoder_TIM = 0;
    }
    return Encoder_TIM;
}


int main(void) {
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);               /* 设置NVIC中断分组2:2位抢占优先级,2位响应优先级 */
    delay_init();                                                   /* 延时函数初始化 */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
    GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);      /* 关闭jtag,使能SWD,可以用SWD模式调试 */
    delay_ms(500);                                                /* 等待稳定 */
    uart_init(115200);

    Encoder_Init_TIM3(0xffff, 0); //初始化TIM2为编码器接口模式

    while (1) {
        printf("%d \r\n", (int) TIM_GetCounter(TIM3));

    }
}



TIM4定时器编码器程序

类似地写程序即可。
stm32旋转编码器,单片机,单片机,stm32,旋转编码器程序,定时器解码文章来源地址https://www.toymoban.com/news/detail-644350.html

#include "sys.h"
#include "usart.h"

//旋转编码器
//CLK--PB6
//DT---PB7
#define CLK_in  PBin(6)
#define DT_in   PBin(7)

/**************************************************************************
函数功能:把TIM4初始化为编码器接口模式
**************************************************************************/
void Encoder_Init_TIM4(u16 arr, u16 psc) {
    GPIO_InitTypeDef GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_ICInitTypeDef TIM_ICInitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);//使能TIM4时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;       //选择你要设置的IO口
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;       //设置传输速率
    GPIO_Init(GPIOB, &GPIO_InitStructure);          /* 初始化GPIO */

    TIM_TimeBaseStructure.TIM_Period = arr;   //自动装载值
    TIM_TimeBaseStructure.TIM_Prescaler = psc; //分频系数
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //设置向上计数模式
    TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);

    TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; //通道1
    TIM_ICInitStructure.TIM_ICFilter = 0x03;  //滤波
    TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_BothEdge;
    TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; //分频系数
    TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;//PA6直接映射到TI1
    TIM_ICInit(TIM4, &TIM_ICInitStructure);

    TIM_ICInitStructure.TIM_Channel = TIM_Channel_2; //通道1
    TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;//PA7直接映射到TI2
    TIM_ICInit(TIM4, &TIM_ICInitStructure);

    NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;//中断通道
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;//抢占优先级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;        //子优先级
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;            //IRQ通道使能
    NVIC_Init(&NVIC_InitStructure);

    TIM_EncoderInterfaceConfig(TIM4, TIM_EncoderMode_TI1, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//使用编码器模式1
    //TIM_EncoderInterfaceConfig(TIM4, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//使用编码器模式3
    TIM_ICStructInit(&TIM_ICInitStructure); //将结构体中的内容缺省输入
    TIM_ICInitStructure.TIM_ICFilter = 10;
    TIM_ICInit(TIM4, &TIM_ICInitStructure);
    TIM_ClearFlag(TIM4, TIM_FLAG_Update);//清除TIM的更新标志位
    TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);//运行更新中断

    TIM_SetCounter(TIM4, 10000);//初始化计数器初值

    TIM_Cmd(TIM4, ENABLE); //使能定时器

}



// 计数超过arr就会产生溢出中断
// 也可以把NVIC_Init(&NVIC_InitStructure);注释掉就不要开启中断
void TIM4_IRQHandler(void) {
    if (TIM4->SR & 0X0001)//溢出中断
    {
        printf("interrupt\r\n");
    }
    TIM4->SR &= ~(1 << 0);//清除中断标志位
}




int main(void) {
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);               /* 设置NVIC中断分组2:2位抢占优先级,2位响应优先级 */
    delay_init();                                                   /* 延时函数初始化 */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
    GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);      /* 关闭jtag,使能SWD,可以用SWD模式调试 */
    delay_ms(500);                                                /* 等待稳定 */
    uart_init(115200);

    Encoder_Init_TIM4(0xffff, 0); //初始化TIM2为编码器接口模式

    while (1) {
        printf("%d \r\n", (int) TIM_GetCounter(TIM4));

    }
}



到了这里,关于【单片机】STM32单片机读取旋转编码器,TIM定时器编码器模式捕获,程序的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • (STM32)PWM输出控制电机旋转并且使用编码器读取脉冲数

    目录  前言 一、pwm输出让电机转  1.电机的接线说明 2.驱动的接线说明 3.pwm输出代码  pwm.c pwm.h 4.输出pwm控制电机旋转 二、配置定时器编码器模式 1.定时器编码器模式 编码器原理 编码器相关的概念 2.编码器模式——代码部分 3.获取脉冲数 三、定时读取编码器读取的脉冲数

    2024年02月03日
    浏览(58)
  • 【32单片机学习】(3)霍尔编码器减速直流电机控制及测速

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 前言 1.实验现象 2.实验接线及原理图 接线图 原理图  电机接线图 3.代码部分 1.主函数  main.c 2.按键部分   key.c  key.h pwm代码   pwm.c  pwm.h 电机驱动   motor.c   motor.h  OLED显示 oled.c oled.h  编码器

    2024年02月11日
    浏览(57)
  • 使用STM32CubeProgrammer工具读取单片机Flash数据读取

    本文主要介绍,如何使用STM32CubeProgrammer工具读取和写入单片机Flash内部的数据,方便调试使用。 2.1 连接Stlink和单片机,点击“connect”进行连接 2.2 读取固定长度的数据 根据程序的大小,设置需要读取的字节数,如下图所示。点击“read”将单片机Flash中的数据读取到STM32Cube

    2024年02月12日
    浏览(43)
  • STM32 EC11 旋转编码器

    代码在最后,复制可直接食用 以及我的电路图 在研究EC11的时序之前首先要了解一点,EC11按旋转的输出动作可以分为两种。一种是转两格,A、B对C端输出一个完整脉冲(转一格就只是由低电平-高电平或由高电平-低电平);另一种就是转一格,A、B对C端输出一个完整脉冲。

    2024年02月02日
    浏览(40)
  • 【单片机】DS2431,STM32,EEPROM读取与写入

    芯片介绍: https://qq742971636.blog.csdn.net/article/details/132164189 DS2431内部有128个字节的数据,这篇博客可以对这128个字节的数据进行读写,而有的人想要改写芯片ROM,这是芯片的唯一地址,请看这里 https://blog.csdn.net/x1131230123/article/details/135667146 接线 串口结果: 部分代码: 代码:

    2024年02月13日
    浏览(45)
  • STM32移植LVGL+旋转编码器接口对接

    写在前面:本菜鸟结合了许多大佬的文章,成功实现了基于LVGL的GUI设计,小开心~浅浅记录一下!~ 本文以单片机STM32F103VET6为核心,利用ST7796芯片驱动分辨率为480*320的LCD液晶屏模块,移植LVGL,对接显示接口,对接外部接口——旋转编码器,完成以上两步,就可以实现LVGL的显

    2024年02月10日
    浏览(46)
  • STM32-微项目07-旋转编码器计数及测速

    一、微项目实现目标: 检测旋转编码器模式下,检测旋转编码器的转动计数值及转速。并且区分转向,一侧转动增加cout,转速值为正,一侧转动减少count,转速值为负;   二、微项目硬件配置需求: 1,stm32F103C8T6核心板一块 2,0.96寸OLED显示,用于显示计数 3,旋转编码器,

    2024年02月08日
    浏览(39)
  • 【STM32】HAL库自学记录-旋转编码器的使用

    通过本文可学会两种实现判断旋转编码器正转反转的方法,可根据自己的应用场景来选择使用哪种方法。 1、芯片:STM32F103RCT6 2、STM32CubeMx软件 3、IDE: MDK-Keil软件 4、旋转编码器模块 5、XCOM V1.4串口软件 图中C端为GND。 方向 :A相和B相相差一个相位,一般来说是90°。A相信号在

    2024年02月11日
    浏览(52)
  • 关于stm32旋转编码器计次乱跳问题(消抖)

    旋转编码器A口接GPIOB0,B口接GPIOB1。设置中断类型为上升下降沿均触发。 输出是用0.96寸oled输出 A脚设置为上升下降沿均会进中断,下降上升一个变换周期,判断这个周期的A脚,B脚的始末状态,来判断正反转一次。 A口输出的波形用来中断,B口输出的波形用来判断正转还是反转

    2024年02月16日
    浏览(39)
  • 【STM32】STM32学习笔记-对射式红外传感器计次 旋转编码器计次(12)

    相关头文件: misc.h 1.1 NVIC_PriorityGroupConfig函数 1.2 NVIC_PriorityGroup类型 1.3 NVIC_Init函数 1.4 NVIC_InitTypeDef类型 NVIC_IRQChannel取值 成员NVIC_IRQChannelPreemptionPriority可赋的值:最大取值15,具体有上面设置的优先级组中规定的位数决定 成员NVIC_IRQChannelSubPriority可赋的值:最大取值15,具体有

    2024年01月15日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包