32单片机基础:旋转编码器计次

接线图如上图所示。

我们初始化一下PB0和PB1两个GPIO口外设中断,当然,这里只初始化一个外部中断也能完成功能的对于编码器而言,下图所示为正转的波形。如果把一相的下降沿用作触发中断,在中断时刻读取另一相的电平,正转时B就是高电平,反转是B就是低电平,这样就能区别旋转方向了。只不过这样在操作上有一些小瑕疵,比如你正转的时候,由于A相先出现下降沿,所以你刚开始动,就进中断了,而反转时是A相后出现下降沿,所以就是你转到位了,才进行中断。

所以打算A,B都触发中断,只有在B相下降沿和A相低电平时,才判断为正转,在A相下降沿和B相为低电平时,才判断为反转。这样保证正转和反转都转到位了,才执行数字加减的操作,同时可以演示两个初始化代码。

下面是代码:

Encoder.c

cpp 复制代码
#include "stm32f10x.h"                  // Device header

int16_t Encoder_Count;

void Encoder_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
	
	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);
	
	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);
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_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);

	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_0) == 0)
		{
			if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)
			{
				Encoder_Count --;
			}
		}
		EXTI_ClearITPendingBit(EXTI_Line0);
	}
}

void EXTI1_IRQHandler(void)
{
	if (EXTI_GetITStatus(EXTI_Line1) == SET)
	{
		/*如果出现数据乱跳的现象,可再次判断引脚电平,以避免抖动*/
		if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)
		{
			if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 0)
			{
				Encoder_Count ++;
			}
		}
		EXTI_ClearITPendingBit(EXTI_Line1);
	}
}

Encoder.h

cpp 复制代码
#ifndef __ENCODER_H
#define __ENCODER_H

void Encoder_Init(void);
int16_t Encoder_Get(void);

#endif

main.c

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

int16_t Num;

int main(void)
{
	OLED_Init();
	Encoder_Init();
	
	OLED_ShowString(1, 1, "Num:");
	
	while (1)
	{
		Num += Encoder_Get();
		OLED_ShowSignedNum(1, 5, Num, 5);
	}
}

OLED模块就不写了,前面博文有。

相关推荐
zxfly20131 小时前
STM32的DMA技术介绍
stm32·单片机·嵌入式硬件
CV金科5 小时前
蓝桥杯—STM32G431RBT6(IIC通信--EEPROM(AT24C02)存储器进行通信)
stm32·单片机·嵌入式硬件·算法·蓝桥杯
嵌入式详谈7 小时前
基于STM32的智能风扇控制系统设计
stm32·单片机·嵌入式硬件
小小怪大梦想8 小时前
RTC实时时钟
stm32·单片机·嵌入式硬件
水饺编程12 小时前
【英特尔IA-32架构软件开发者开发手册第3卷:系统编程指南】2001年版翻译,1-2
linux·嵌入式硬件·fpga开发
电子科技圈12 小时前
IAR全面支持国科环宇AS32X系列RISC-V车规MCU
人工智能·嵌入式硬件·mcu·编辑器
SZPU领跑13 小时前
第十二届蓝桥杯嵌入式省赛程序设计题解析(基于HAL库)(第一套)
stm32·单片机·算法·职场和发展·蓝桥杯
逢生博客13 小时前
Rust 语言开发 ESP32C3 并在 Wokwi 电子模拟器上运行(esp-hal 非标准库、LCD1602、I2C)
开发语言·后端·嵌入式硬件·rust
Tlog嵌入式15 小时前
蓝桥杯【物联网】零基础到国奖之路:十六. 扩展模块之矩阵按键
arm开发·stm32·单片机·mcu·物联网·蓝桥杯·iot
打地基的小白16 小时前
UART通信—基于江科大源码基础进行的改进和解析
单片机·嵌入式硬件·uart通信·代码详解