旋转编码器简介
旋转编码器:用来测量位置、速度或旋转方向的装置,当其旋转轴旋转时,其输出端可以输出与旋转速度和方向对应的方波信号,读取方波信号的频率和相位信息即可得知旋转轴的速度和方向
类型:机械触点式/霍尔传感器式/光栅式
硬件电路
接线图:
代码配置
这里的中断配置与上一章的对射式红外传感器配置一样,只需要改一下引脚,以及通道配置,这里配置了两个引脚,所以需要配置两个中断通道(NVIC),写两个中断函数。
void Encoder_init(void)
{
//------------------------定义结构体变量-----------------------------------
GPIO_InitTypeDef GPIO_InitStructure; //定义GPIO结构体变量
EXTI_InitTypeDef EXTI_InitStructure; //定义EXTI结构体变量
NVIC_InitTypeDef NVIC_InitStructure; //定义NVIC结构体变量
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//开启GPIO的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //开启AFIO的时钟
//---------------------GPIO配置--------------------------------------
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初始化
//---------------------GPIO配置--------------------------------------
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource0);//将中断线与GPIO引脚连接
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource1);//将中断线与GPIO引脚连接
//---------------------EXTI配置--------------------------------------
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);
//---------------------EXTI配置--------------------------------------
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断分组,这里放到模块函数里了,一般情况放在主函数第一行(如上一章按键中断)
//---------------------NVIC配置--------------------------------------
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);
//---------------------NVIC配置--------------------------------------
}
中断函数:
中断函数编程:在中断函数里,不要执行耗时过长的代码,中断函数要简短快速最好不要用delay函数,因为中断时处理突发事情的,如果为了突发的事情在中断函数呆着出不来了,主程序就会收到严重的阻塞
int16_t Encoder_Count;
//返回数据
int16_t Encoder_Get(void)
{
return Encoder_Count;
}
//中断函数
void EXTI0_IRQHandler(void)
{
//判断中断是否触发
if(EXTI_GetITStatus(EXTI_Line0) == SET)
{
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_0) == 0)
{
Encoder_Count++;
}
//清除标志位
EXTI_ClearITPendingBit(EXTI_Line1);
}
}
主函数:
#include "Encoder.h"
int main(void)
{
LED_Init();
OLED_Init();
Encoder_init();
OLED_ShowString(1, 3, "Num:");
while(1)
{
OLED_ShowSignedNum(1, 6, Encoder_Get(), 5);
}
}