旋转编码器驱动-标准库和HAL库

一、标准库

Encoder.c-标准库

#include "stm32f10x.h"                  // Device header
#include "Delay.h"

int8_t Encoder_Count;

/**
  * 函    数:旋转编码器初始化
  * 参    数:无
  * 返 回 值:无
  */
void Encoder_Init(void)
{
	/* 开启时钟 */
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);	//开启GPIOB的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);		//开启外部中断所必须的AFIO时钟
	
	/* 初始化GPIOB */
	GPIO_InitTypeDef GPIO_InitStructure;			//定义GPIO初始化结构体
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;	//GPIO模式为上拉输入模式
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14 | GPIO_Pin_15;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	/* AFIO选择中断引脚 */
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource14);		//选择GPIOB引脚14
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource15);		//选择GPIOB引脚15
	
	/* 初始化外部中断EXTI */
	EXTI_InitTypeDef EXTI_InitStructure;		//定义EXTI初始化结构体
	EXTI_InitStructure.EXTI_Line = EXTI_Line14 | EXTI_Line15;	//选择配置外部中断的14、15号线
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;	//开启使能
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;		//设置为中断模式
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;	//设置为下降沿触发
	EXTI_Init(&EXTI_InitStructure);
	
	/* NVIC中断分组 */
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	/* 初始化嵌套中断控制器NVIC */
	NVIC_InitTypeDef NVIC_InitStructure;	//定义NVIC初始化结构体
	NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;	//由于配置了外部中断14、15号线,通道选择10~15号通道
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;		//开启使能
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructure);
	
}

/**
  * 函    数:旋转编码器获取增量值
  * 参    数:无
  * 返 回 值:自上此调用此函数后,旋转编码器的增量值
  */
int8_t Encoder_Get(void)
{
	int8_t Temp;
	Temp = Encoder_Count;
	Encoder_Count = 0;
	return Temp;
}

/**
  * 函    数:EXTI15_10外部中断函数
  * 参    数:无
  * 返 回 值:无
  * 注意事项:此函数为中断函数,无需调用,中断触发后自动执行
  *           函数名为预留的指定名称,可以从启动文件"startup_stm32f10x_md.s"复制
  *           请确保函数名正确,不能有任何差异,否则中断函数将不能进入
  *			  旋转编码器无消抖处理
  */
void EXTI15_10_IRQHandler(void)
{
	/* 14号线路触发中断 */
	if(EXTI_GetITStatus(EXTI_Line14) == SET)
	{
		//检测另一个引脚电平,确定编码器转向
		if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_15)==0)
		{
			Delay_ms(20);
			Encoder_Count--;
		}
		EXTI_ClearITPendingBit(EXTI_Line14);	//必须清除中断标志位
	}
	
	/* 15号线路触发中断 */
	else if(EXTI_GetITStatus(EXTI_Line15) == SET)
	{
		//检测另一个引脚电平,确定编码器转向
		if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)==0)
		{
			Delay_ms(20);
			Encoder_Count++;
		}
		EXTI_ClearITPendingBit(EXTI_Line15);	//必须清除中断标志位
	}
	
}

Encoder.h-标准库

#ifndef __ENCODER_H
#define __ENCODER_H

void Encoder_Init(void);
int8_t Encoder_Get(void);

#endif

二、HAL库

Encoder.c-HAL库

#include "main.h"                  // Device header
#include "Encoder.h"

int8_t Encoder_Count;

/**
  * 函    数:旋转编码器初始化
  * 参    数:无
  * 返 回 值:无
  */
void Encoder_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStruct = {0};
  /*Configure GPIO pin : PtPin */
  GPIO_InitStruct.Pin = GPIO_A_EXIT4_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  HAL_GPIO_Init(GPIO_A_EXIT4_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : PtPin */
  GPIO_InitStruct.Pin = GPIO_B_EXIT5_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  HAL_GPIO_Init(GPIO_B_EXIT5_GPIO_Port, &GPIO_InitStruct);
}

/**
  * 函    数:旋转编码器获取增量值
  * 参    数:无
  * 返 回 值:自上此调用此函数后,旋转编码器的增量值
  */
int8_t Encoder_Get(void)
{
	int8_t Temp;
	Temp = Encoder_Count;
	Encoder_Count = 0;
	return Temp;
}

/**
  * 函    数:EXTI15_10外部中断函数
  * 参    数:无
  * 返 回 值:无
  * 注意事项:此函数为中断函数,无需调用,中断触发后自动执行
  *           函数名为预留的指定名称,可以从启动文件"startup_stm32f10x_md.s"复制
  *           请确保函数名正确,不能有任何差异,否则中断函数将不能进入
  *			  旋转编码器无消抖处理
  */


void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	if(GPIO_Pin == GPIO_B_EXIT5_Pin)
	{
				
				if(HAL_GPIO_ReadPin(GPIO_A_EXIT4_GPIO_Port,GPIO_A_EXIT4_Pin) == GPIO_PIN_SET)
			{
				HAL_Delay(5);
				Encoder_Count--;
				HAL_Delay(10);
			}
	}
	if(GPIO_Pin == GPIO_A_EXIT4_Pin)
	{
				if(HAL_GPIO_ReadPin(GPIO_B_EXIT5_GPIO_Port,GPIO_B_EXIT5_Pin) == GPIO_PIN_SET)
			{
				HAL_Delay(5);
				Encoder_Count++;
				HAL_Delay(10);
			}
	}
	

}

Encoder.h-HAL库

#ifndef __ENCODER_H
#define __ENCODER_H

void Encoder_Init(void);
int8_t Encoder_Get(void);

#endif

三、README

注意有一些旋转编码器没有z轴开关功能

注意使用旋转编码器时,用delay消抖时,注意tick时钟的优先级要比中断引脚的优先级高

https://blog.csdn.net/qq_64931749/article/details/138274582?fromshare=blogdetail&sharetype=blogdetail&sharerId=138274582&sharerefer=PC&sharesource=weixin_73690807&sharefrom=from_link

注意:

例子

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	if(GPIO_Pin == KEY0_Pin)  //按键按下
    {
        HAL_Delay(20);
		if(HAL_GPIO_ReadPin(KEY0_GPIO_Port, KEY0_Pin) == GPIO_PIN_RESET)
		{
            HAL_GPIO_TogglePin(LED0_GPIO_Port,LED0_Pin);
            HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);
		}
    }
}

HAL_Delay函数本质也是打断程序去执行延时操作,那么,就一定要让系统滴答定时器抢占优先级高于外部中断的抢占优先级(数字越小级别越高),下面是配置优先级步骤:

先修改为抢占优先级与响应优先级各用2位配置(可以不改)

默认系统滴答定时器是最低,我们要把它改为1,然后外部中断比它低一个等级------2即可
相关推荐
番茄老夫子8 小时前
工业温湿度传感器芯片推荐
单片机·嵌入式硬件
silver6879 小时前
STM32 FreeRTOS中断管理
单片机
小鱼做毕设12 小时前
基于单片机的智能输液系统
单片机·嵌入式硬件·毕业设计·课程设计·智能输液系统
gyeolhada12 小时前
计算机组成原理(计算机系统3)--实验二:MIPS64乘法实现实验
stm32·单片机·嵌入式硬件
疯狂的豆包13 小时前
基于 STM32 连接 Mini MP3 播放器的实践探索
stm32·单片机·嵌入式硬件
wit_@14 小时前
单片机的原理及其应用:从入门到进阶的全方位指南
单片机·嵌入式硬件
兢兢业业的打野15 小时前
智能家居电机控制
单片机·嵌入式硬件
daybydayby16 小时前
Hooks扩展
单片机
不能只会打代码16 小时前
32单片机综合应用案例——基于GPS的车辆追踪器(三)(内附详细代码讲解!!!)
单片机·嵌入式硬件·32单片机
放我去玩单片机16 小时前
基于 STM32 的多功能时间管理器项目
stm32·单片机·嵌入式硬件