STM32旋转编码计次

1.工程模块

2.旋转编码器模块

复制代码
#include "stm32f10x.h"  

int16_t ENCODER_Count;

//用于记录编码器累计的"步数"(或称"计数值"),使用 int16_t 表示可正可负,支持正反转计数。

void ENCODER_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

//使能 GPIOB 和复用功能时钟(AFIO),因为要用到 EXTI 中断。
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);

//设置为上拉输入是为了在没有信号时保持高电平,防止浮空干扰。
	
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource0);
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource1);

//将 EXTI0 映射到 PB0,EXTI1 映射到 PB1。
	
	EXTI_InitTypeDef EXTI_InitStructure;						
	EXTI_InitStructure.EXTI_Line = EXTI_Line0|EXTI_Line1;					
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;					
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;			
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;		
	EXTI_Init(&EXTI_InitStructure);

//使能 EXTI0 和 EXTI1 中断,触发方式为下降沿触发(即从高变低时触发中断)。这种设计可以减少中断次数(只在一边沿触发),但需配合相位判断方向。

	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

//设置中断优先级分组为 2 位抢占 + 2 位子优先级。

	NVIC_InitTypeDef NVIC_InitStructure;						
	NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;		
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;				
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;	
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;			
	NVIC_Init(&NVIC_InitStructure);
	
//两个中断都使能,优先级相同(抢占优先级都是 1)

	NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;		
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;				
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;	
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;			
	NVIC_Init(&NVIC_InitStructure);
}


int16_t ENCODER_Get(void)
{
	int16_t Temp;
	Temp = ENCODER_Count;
	ENCODER_Count=0;
	return Temp;
}
/*
返回当前累计的编码器变化量,并 清零计数器;
适用于需要周期性读取"增量"的场景(如速度控制、位置增量反馈)。
*/
void EXTI0_IRQHandler(void)
{
	if(EXTI_GetITStatus(EXTI_Line0)==SET)
	{
		if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)==0)
		{
			ENCODER_Count --;
		}
		EXTI_ClearITPendingBit(EXTI_Line0);
	}
}

/*
当 A 相(PB0)出现下降沿时进入中断;
此时读取 B 相(PB1)电平:
若 B 相为低 → 说明是 逆时针旋转 → 计数减 1;
若 B 相为高 → 顺时针,不处理(因为只在下降沿触发,另一方向会在 EXTI1 中处理)。
*/

void EXTI1_IRQHandler(void)
{
	if(EXTI_GetITStatus(EXTI_Line1)==SET)
	{
		if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0)==0)
		{
			ENCODER_Count ++;
		}
		EXTI_ClearITPendingBit(EXTI_Line1);
	}
}
/*
当 B 相(PB1)出现下降沿时进入中断;
读取 A 相(PB0)电平:
若 A 相为低 → 说明是 顺时针旋转 → 计数加 1;
否则为逆时针,已在 EXTI0 中处理。
*/

本段代码是用于 STM32F10x 系列微控制器增量式旋转编码器(Quadrature Encoder)接口驱动程序 ,通过 外部中断(EXTI)方式 实现对编码器脉冲的计数。

3.主函数

复制代码
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "ENCODER.h"

int16_t Num;

int main(void)
{
	OLED_Init();
	OLED_ShowString(1,1,"Num:");
	while(1)
	{
		Num +=ENCODER_Get();
		OLED_ShowSignedNum(1,5,Num,5);
	}
}
相关推荐
Dr.kangder1 小时前
嵌入式面试总结(十五)——异常处理
单片机·面试·职场和发展·系统架构·嵌入式
zlinear数据采集卡3 小时前
D223上位机C#开发实战:从帧解析到波形显示的完整实现
开发语言·arm开发·嵌入式硬件·fpga开发·开源·c#
ACP广源盛139246256733 小时前
蚂蚁百灵 Ling‑3.0‑flash 开源 + 昇腾 0‑Day 原生适配@ACP#GSV9001E 在国产算力矩阵中的机会与落地场景
大数据·人工智能·分布式·单片机·嵌入式硬件
Rocktech_ruixun5 小时前
机器人端侧大模型部署对主板有哪些要求?瑞迅主控板分级方案对比
人工智能·嵌入式硬件·机器人
振南的单片机世界6 小时前
SysTick硬核拆解:既是HAL_Delay的“心跳”,也是RTOS的“节拍器”
arm开发·stm32·单片机·嵌入式硬件
Lzh编程小栈6 小时前
【嵌入式底层】SPI超透彻详解:通信原理、四线结构、四种模式、寄存器底层 + 面试全集
c语言·stm32·单片机·面试·职场和发展
Rocktech_ruixun6 小时前
机器人数据采集能力取决于什么?瑞迅科技RK3588/3576核心板方案深度解析
人工智能·嵌入式硬件·机器人
水果里面有苹果6 小时前
28-DRV8825PWPR步进电机驱动器
单片机
恒锐丰科技韩生7 小时前
率能 SS6625E|3.0~20V 单通道 H 桥直流电机驱动 SOP8 电子锁玩具机器人分享
嵌入式硬件·硬件工程
zlinear数据采集卡7 小时前
D223 ADC数据处理流水线:从原始采样值到工程单位的完整转换链
开发语言·arm开发·嵌入式硬件·fpga开发·开源·c#