旋转 编码器 是一种将旋转位移转换为一连串数字脉冲 信号 的旋转式 传感器 。这些脉冲用来控制角位移。读数系统通常采用差分方式,即将两个波形一样但相位差为180°的不同信号进行比较,以便提高输出信号的质量和稳定性。读数是在两个信号的差别基础上形成的,从而消除了干扰。
模块实物展示:
资料下载 链接: 资料 提取码:8889
2. 规格 参数
模块的厂家资料下载请查看百度网盘链接
工作电压:5V
工作 电流 :1MA
模块尺寸:18 x 25 mm
旋转角度: 360度
通信 协议:相位差
管脚数量:5n(2.54mm间距 排针 )
3.移植过程
我们的目标是在立创·CW32F030C8T6开发板上能够判断旋转方向、旋转次数和是否按下的功能。首先要获取资料,查看数据手册应如何实现,再移植至我们的工程。
3.1查看资料
旋转编码器是通过两个引脚的相位差,实现的旋转方向判断(以后的CLK引脚统一称呼为A相,DT引脚为B相)
当是顺时针旋转时,A相超前B相90度,即A相为下降沿时,B相为低电平;A相为上升沿时,B相为高电平。
当是逆时针旋转时,B相超前A相90度,即A相为下降沿时,B相为高电平;A相为上升沿时,B相为低电平。
而EC11按旋转的输出动作可以分为两种。
一种是转两格,A、B端输出一个完整脉冲(转一格就只是由低电平->高电平或由高电平->低电平);
一种就是转一格,A、B对C端输出一个完整脉冲。
转一格半个脉冲
转一格完整脉冲
因此我们只需 检测 A相或者B相有发生高低电平跳变时,就判断另一相状态,来决定旋转方向。根据以下真值表,可以发现:
当两相同时为上升沿或者同时为下降沿时,则为顺时针;
当两相不同时为上升沿或者不同时为下降沿时,则为逆时针;
下B相 右A相 | 上升沿 | 下降沿 |
---|---|---|
上升沿 | 顺时针 | 逆时针 |
下降沿 | 逆时针 | 顺时针 |
旋转编码器是 机械 结构的,是机械结构就避免不了在旋转或者按下时有抖动,这里采用 定时器 每隔10ms扫描一次编码器是否有动作,实现10ms内的消抖。
在中断服务函数中,根据真值表确定旋转的方向。
3.2引脚选择
该模块有5个引脚,具体引脚连接见 表 各引脚连接。
3.3移植至工程
打开自己的工程。(这里工程参考见入门手册工程模板)
移植步骤中的导入.c和.h文件与第二章的第1小节【DHT11温 湿度传感器 】相同,只是将.c和.h文件更改为ec11.c与ec11.h。这里不再过多讲述,移植完成后面修改相关代码。
在文件ec11.c中,编写如下代码。
/* * Change Logs: * DaAuthorNotes * 2024-06-19LCKFB-LPfit version */#include "ec11.h"#include "stdio.h"/****************************************************************** * 函 数 名 称:Encoder_GPIO_Init * 函 数 说 明:旋转编码器引脚初始化 * 函 数 形 参:无 * 函 数 返 回:无 * 作者:LC * 备注:使用定时器每10Ms扫描一次是否有旋转,即通过定时器进行消抖******************************************************************/void Encoder_GPIO_Init(void){GPIO_InitTypeDef GPIO_InitStruct;// GPIO初始化结构体BM_TimeBaseInitTypeDef BTIM_TimeBaseInitStruct;// 定时器初始化结构体RCC_GPIO_ENABLE();// 使能GPIO时钟BTIM_RCC_ENABLE();// 使能BTIM时钟// 禁止中断,以安全地配置NVIC__disable_irq();// 开启BTIM1中断,并关联到NVICNVIC_EnableIRQ(BSP_TIMER_IRQ);// 允许中断,恢复中断状态__enable_irq();GPIO_InitStruct.Pins =GPIO_ENCODER_SW|// GPIO引脚GPIO_ENCODER_LCK|GPIO_ENCODER_DT;GPIO_InitStruct.Mode = GPIO_MODE_INPUT_PULLUP;// 上拉输入GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;// 输出速度高GPIO_Init(PORT_GPIO, &GPIO_InitStruct);// 初始化// 配置定时器模式、周期和预分频器BTIM_TimeBaseInitStruct.BTIM_Mode = BTIM_Mode_TIMER;// 设置为定时器模式BTIM_TimeBaseInitStruct.BTIM_Period = 625 - 1;// 设置周期,使得定时器每10ms产生一次溢出中断BTIM_TimeBaseInitStruct.BTIM_Prescaler = BTIM_PRS_DIV1024; // 预分频器设置为1024,以降低时钟频// 使用上述配置初始化定时器BTIM1BTIM_TimeBaseInit(BSP_TIMER, &BTIM_TimeBaseInitStruct);// 使能BTIM1的溢出中断BTIM_ITConfig(BSP_TIMER, BTIM_IT_OV, ENABLE);// 启动定时器BTIM1BTIM_Cmd(BSP_TIMER, ENABLE);}/****************************************************************** * 函 数 名 称:Encoder_Sf * 函 数 说 明:判断旋转编码器是否有往哪一个方向旋转 * 函 数 形 参:无 * 函 数 返 回:1=正转 2=反转 * 作者:LC * 备注:哪一边正转哪一边反转不需要太在意,你说的算******************************************************************/char Encoder_Scanf(void){stat GPIO_PinState EC11_CLK_Last= GPIO_Pin_RESET; //EC11的LCK引脚上一次的状态(A相)static GPIO_PinState EC11_DT_Last = GPIO_Pin_RESET; //EC11的DT引脚上一次的状态(B相)char ScanResult = 0;//当A发生跳变时采集B当前的状态,并将B与上一次的状态进行对比。if(GET_CLK_STATE !=EC11_CLK_Last){//若A 0->1 时,B 1->0 正转;若A 1->0 时,B 0->1 正转;//若A 0->1 时,B 0->1 反转;若A 1->0 时,B 1->0 反转if(GET_CLK_STATE == 1)//EC11_A和上一次状态相比,为上升沿{//EC11_B和上一次状态相比,为下降沿if((EC11_DT_Last == 1)&&(GET_DT_STATE == 0))ScanResult = 1;//正转//EC11_B和上一次状态相比,为上升沿if((EC11_DT_Last == 0)&&(GET_DT_STATE == 1))ScanResult = 2; //反转//>>>>>>>>>>>>>>>>下面为正转一次再反转或反转一次再正转处理<<<<<<<<<<<<<<< >>>>>>>>>>>>>>>下面为正转一次再反转或反转一次再正转处理<<<<<<<<<<<<<<<
在文件ec11.h中,编写如下代码。
/* * Change Logs: * DateAuthorNotes * 2024-06-19LCKFB-LPfirst version */#ifndef _BSP_ENCODER_H_#define _BSP_ENCODER_H_#include "board.h"#define RCC_GPIO_ENABLE()__RCC_GPIOA_CLK_ENABLE()#define PORT_GPIOCW_GPIOA//SW引脚#define GPIO_ENCODER_SWGPIO_PIN_7//CLK引脚#define GPIO_ENCODER_LCKGPIO_PIN_6//DT引脚#define GPIO_ENCODER_DTGPIO_PIN_4//获取CLK引脚的状态#define GET_CLK_STATEGPIO_RePin(PORT_GPIO, GPIO_ENCODER_LCK)//获取DT引脚的状态#define GET_DT_STATEGPIO_ReadPin(PORT_GPIO, GPIO_ENCODER_DT)//获取SW引脚的状态#define GET_SW_STATEGPIO_ReadPin(PORT_GPIO, GPIO_ENCODER_SW)//定时器扫描#define BTIM_RCC_ENABLE()__RCC_BTIM_CLK_ENABLE() // 使能定时器时钟#define BSP_TIMERCW_BTIM1// 定时器#define BSP_TIMER_IRQBTIM1_IRQn// 定时器中断#define BSP_TIMER_IRQHANDLERBTIM1_IRQHandler// 定时器中断服务函数void Encoder_GPIO_Init(void);//旋转编码器初始化unsigned char Encoder_Sw_Down(void);//编码器是否按下int Encoder_Rotation_left(void);//左转服务函数int Encoder_Rotation_right(void);//右转服务函数#endif
4.移植验证
在自己工程中的main主函数中,编写如下。
/* * Change Logs: * DateAuthorNotes * 2024-06-19LCKFB-LPfirst version */#include "board.h"#include "stdio.h"#include "bsp_.h"#include "ec11.h"int32_t main(void){board_init();// 开发板初始化uart1_init(115200);// 串口1波特率115200Encoder_GPIO_Init();printf("encoder demo startrn");while(1){if( Encoder_Sw_Down() == 1 )//旋转编码器被按下{printf("Encoder downrn");}}}
移植现象:向右旋转10次,向左旋转10次,按下一次。
模块移植成功案例代码:
链接:
提取码:LCKF审核编辑 黄宇