旋转编码器驱动-标准库和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即可
相关推荐
国科安芯13 小时前
航天器多路并联大功率电源系统设计与ASP4644均流特性分析
单片机·嵌入式硬件·fpga开发·安全性测试
茯苓gao15 小时前
嵌入式开发笔记:CANopen相关移位运算与通信协议术语详解
网络·嵌入式硬件·学习·信息与通信
梁朝辉18 小时前
STM32H750VBT6中ADCINP与INN什么区别
stm32·单片机·嵌入式硬件
省四收割者19 小时前
一文详解信号完整性(1)
python·嵌入式硬件·数学建模·信息与通信·信号处理·智能硬件
崇山峻岭之间20 小时前
单片机无感FOC驱动之ADC
单片机·嵌入式硬件
Ligocious20 小时前
1.点亮一颗小小的LED
单片机·嵌入式硬件
KaifuZeng1 天前
通信与接口协议面试八、CAN通信
单片机·嵌入式硬件·面试·通信与接口协议
智源单片机设计1 天前
基于单片机的直流电机双闭环调速系统设计
单片机·嵌入式硬件
kebidaixu1 天前
两轮车换电 BMS 的模拟前端中颖 SH367306 AFE 芯片详解
stm32
kebidaixu1 天前
两轮车换电 BMS 的模拟前端中颖 SH367306 AFE 芯片调试实录:四个关键问题与解决方案
stm32