器件:EC11编码器
1 序
编码器型号为"黄海电子有限公司"的"EC11A-227";参数特性和ALPS的EC11B区别不大,EC11A性能较好;
出于图片规整考虑,本文截取ALPS的EC11B的datasheet来分析EC11A,推荐电路截取自"黄海电子"的"EC11B";
2 编码原理
EC11编码器为增量式编码器;由encoderA和encoderB两个光电传感器构成,光栅盘上的传感器位置相位差90度,通过脉冲计数;
假设光栅盘转一圈时,光源亮灭半圈;那么光电传感器就产生一个方波信号,encoderA和encoderB产生的方波相位相差90度;
[这里合成一张图,outputwave的触点图+顺时针波形图 + slidingNoise的触点抖动图+test circuit图]
2.1 旋转方向
顺时针方向:当encoderA为上升沿时,encoderB为低电平;当encoderA为下降沿时,encoderB为高电平;
当encoderB为上升沿时,encoderA为高电平;当encoderB为下降沿时,encoderA为低电平;
逆时针方向:当encoderA为上升沿时,encoderB为高电平;当encoderA为下降沿时,encoderB为低电平;
当encoderB为上升沿时,encodeA为低电平;当encoderB为下降沿时,encoderA为高电平;
总结:顺时针旋转>>往encoderA方向旋转>>所以时序图A方波先出现,B方波后出现>>现象如上;
逆时针旋转>>往encoderB方向旋转>>所以时序图B方波先出现,A方波后出现>>现象如上;
判断方向时配置encoderA或encoderB其中一个触发外部中断,另外一个搭配判断方向;
3 推荐电路
推荐电路使用了RC滤波电路,硬件过滤了触点抖动,没有用示波器抓取波形,不过软件实测确实没有触点抖动;
如果没有使用RC滤波电路,那么chattering触点抖动时间需要软件延时消除;
3.1 RC滤波电路
3.1.1 低通滤波
电路:RC串联在电路中,Vin >> R >>C >>GND;Vout接在R与C之间;
当Vin较低假设为100Hz时,电容阻抗Xc = 1/2πfC=160KΩ;所以Vin都从Vout出去;低频导通,几乎不衰减;
当Vin为截止频率1600Hz时,电容阻抗Xc = 10KΩ;Vout=0.707Vin;Vout导通根号2,衰减1-根号2;
当Vin较高为100KHz时,电容阻抗Xc = 1/2πfC=16Ω;所以Vin都从电容接地;高频几乎衰减完了;
3.1.2 高通滤波
电路:CR串联在电路中,Vin >> C >> R>>GND;Vout接在C与R之间;
导通特性刚好和低通滤波反过来;
3.1.3 截止频率
作用:决定信号是否开始衰减的分界频率;计算公式为Fcutout = 1/( 2πRC );
公式:网友的截至频率推导:Xc=1/jωC = 1/2πfC = R;f = 1/2πRC;(这里也把j给去掉了;)
角频率ω = 2πf;容抗Xc = 1/jωC ; j是虚数单位,所以Xc自带了一个单位;
在低通滤波中Vout = Vin( Xc/ (R+jXc) ) = Vin( R/(R+jR) ) = Vin(1/(1+j)); (这里电路中的Xc没有保留 j ?)
Vout = Vin( 1/(1+j) )乘以共轭复数(1-j)/(1-j),得到Vout = Vin( (1-j)/(1+1) )=Vin( (1-j)/2 );
Vout =Vin( (1-j)/2 )取模,|Vout| = |Vin| 根号2/2 ≈0.707|Vin|
Xc=1/jωC=1/2πfC (把j去掉了?)
ques:为什么在电容中,电流会领先于电压90度,先放着;
ques:为什么截至频率可以作为信号衰减的分解频率呢?大概实测出来就是这么回事把;
这怎么算呢?具体得拿本教材,老是有个j时有时没有的,搞不懂为什么这里保留,那里又没有;
4 软件编写
配置encoderA为外部中断,上升沿下降沿都触发;于是encoderA产生边沿后就会进入中断函数;
中断函数中,通过对旋转方向的判断来加声音或者减声音;中断函数退出前清个标志位;就完了;
以上就是编码器的代码流程了,还是比较简单的;那可不可以配置成encodeB为外部中断呢?当然也是可以的;
查看代码
/*** ec11旋钮 encode-A作为外部中断输入,encode-B作为方向判断; 调用ec11的初始化函数初始化完之后就可以了; 每次旋转ec11,自动触发外部中断,在中断函数中修改音量值; 每次按下ec11,那边循坏读取的引脚值变化了,就视作按下按键; ***/ #ifndef BSP_ENCODE_H_ #define BSP_ENCODE_H_ #define GPIO_ENA_CLK_ENABLE __HAL_RCC_GPIOB_CLK_ENABLE #define ENA_GPIO GPIOB #define ENA_PIN GPIO_PIN_0 #define GPIO_ENB_CLK_ENABLE __HAL_RCC_GPIOC_CLK_ENABLE #define ENB_GPIO GPIOC #define ENB_PIN GPIO_PIN_5 #define EXTI_TRQn_encoder EXTI0_IRQn #define EXTI_IRQHandler_encoder EXTI0_IRQHandler extern uint8_t flag_scrollMaxPrint; extern uint8_t flag_scrollMinPrint; void volumeMinimumPrint(void); void volumeMaximumPrint(void); void bsp_encode_Init(); #endif float* pCurrVolume = NULL; uint8_t flag_scrollMaxPrint = 0; uint8_t flag_scrollMinPrint = 0; //[0] 静音; [1-100]声音范围 void EXTI_IRQHandler_encoder(void){ float percentVol = 0; //CAE("IT:%x ",__HAL_GPIO_EXTI_GET_IT(ENA_PIN)); //如果面板锁定,旋转和按键都不执行; if(CurProduct->VideoOutput[0].key_1unlock==0){ CAE("lock."); __HAL_GPIO_EXTI_CLEAR_IT(ENA_PIN); return; } //开机时 if( (CurProduct->IsPowOn) ){ //挪动旋钮取消静音; if(CurProduct->VideoOutput[0].key_MuteFlag==TRUE){ CurProduct->VideoOutput[0].key_MuteFlag = FALSE; CAE("M"); } pCurrVolume = getChanneldBVolumeAddr(CurProduct->VideoOutput[0].key_volume0LINE1MSTR); if (HAL_GPIO_ReadPin(ENA_GPIO, ENA_PIN)){ if (HAL_GPIO_ReadPin(ENB_GPIO, ENB_PIN)){ (*pCurrVolume) = (*pCurrVolume) -1.25; CAE("+-"); } else{ (*pCurrVolume) = (*pCurrVolume) +1.25; CAE("++"); } } else{ if (HAL_GPIO_ReadPin(ENB_GPIO, ENB_PIN)){ (*pCurrVolume) = (*pCurrVolume) +1.25; CAE("-+"); } else{ (*pCurrVolume) = (*pCurrVolume) -1.25; CAE("--"); } } //旋钮最值打印; if ( ((*pCurrVolume) <1) || ((*pCurrVolume)>200) ){ *pCurrVolume = 1; flag_scrollMinPrint = 1; } else if ((*pCurrVolume) >100){ (*pCurrVolume) = 100; flag_scrollMaxPrint = 1; } CAE("*pCurrVolume %f",(*pCurrVolume)); CurProduct->SaveEEP_tick = 10; } __HAL_GPIO_EXTI_CLEAR_IT(ENA_PIN); } void bsp_encode_Init(){ CAE("bsp_encode_Init() "); GPIO_ENA_CLK_ENABLE(); GPIO_ENB_CLK_ENABLE(); //下降沿触发, 这种通过边沿触发的都默认是nopull模式吗? GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = ENA_PIN; GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(ENA_GPIO, &GPIO_InitStruct); GPIO_InitStruct.Pin = ENB_PIN; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; HAL_GPIO_Init(ENB_GPIO, &GPIO_InitStruct); // EXTI线配置 //文文这里有个exti线的配置的,但是这个没有也能跑先放着; //使能中断 HAL_NVIC_SetPriority(EXTI_TRQn_encoder, 2, 1); HAL_NVIC_EnableIRQ(EXTI_TRQn_encoder); }
5 规格特性
EC11A额定电压为5V;最大额定电流10mA;绝缘阻抗在250V DC时,为100MΩ以上;耐电压300V持续1min,绝缘良好;
EC11A旋转寿命可达旋转20000周;
编码器还提供了一个self return switch自复位按键,还原的bounce回弹时间最大2ms;
6 小结
有的现象就是这么回事,总结出来就行了,至于因果关联性,许多现象不具备因果关联性;
这个编码器的数据手册主要需要看什么呢?
前面是产品线系列product Line和尺寸dimensions;然后是各系列的电气特性,主要是使用寿命,工作温度,绝缘特性;
需要看的就是后面的波形时序,和"黄海电子"规格书的推荐电路了;
关于滤波电路的相关电分定义先放着;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?