问题描述
我正在尝试读取旋转编码器作为更大项目的一部分。我正在使用 Atmega8L 和 MPLab X 和 XC8 编译器。
我遇到的问题是编码器工作不可靠,似乎只能向上计数而不能向下计数。
由于电路的某些其他方面,编码器引脚无法连接到 atmega8 的具有中断功能的引脚。
这是我的代码,它读取编码器。
#include <xc.h>
#include "pinmapping.h"
#include "main.h"
static inputEvent lastEvent;
static int aLastState;
static int aState;
//get the last Events data for use elsewhere
inputEvent getLastInputEvent(){
return lastEvent;
}
void initEncoder(){
//get our current button state and set rotation change to 0
if((PINB & ENCODER_SW) == 0){
//also save that to our Event
lastEvent.buttonpressed = 1;
}
else{
lastEvent.buttonpressed = 0;
}
lastEvent.rotationChange = 0;
//also save the current state of the A pin for the first read
aLastState = (PINB & ENCODER_A);
if(aLastState >= 1){
aLastState = 1;
}
}
//this should run regularly eg. on a timer interrupt
void readEncoder(){
//first get the state of both pins
aState = (PINB & ENCODER_A);
int bState = (PINB & ENCODER_B);
if(aState >= 1){
aState = 1;
}
if(bState >= 1){
bState = 1;
}
//check if the button is pressed
if((PINB & ENCODER_SW) == 0){
//save that to our Event
lastEvent.buttonpressed = 1;
}
else{
lastEvent.buttonpressed = 0;
}
//check if the state has changed since last time
if(aState != aLastState){
//check if A and B have the same state -> positive rotation
if(bState != aState){
//save the rotation change to our Event
lastEvent.rotationChange = 1;
}
else{
lastEvent.rotationChange = -1;
}
//save the current state of the A pin for next time
aLastState = aState;
}
else{
//if no rotation change happend,save that to our Event
lastEvent.rotationChange = 0;
}
}
按钮按下工作正常,但旋转变化永远不会是 -1,而是始终为 1 或 0。
ENCODER_SW、ENCODER_A 和 ENCODER_B 是位掩码,在对应于正确 IO 引脚的位上全为 0 和单个 1。
在main中,首先调用initEncoder(在IO-setup之后),然后在无限循环中调用一个函数,该函数依次调用readEncoder()和getLastInputEvent(),然后在返回到主要的。
我还尝试过大约每毫秒在计时器中断上运行 readEncoder() 函数。然而,这导致它根本不起作用。
有什么问题?为什么它不起作用?
编辑:在我做了一些更改后更新了代码。
我使用的是带按钮的 ALPS EC12E。
rotationChange 用于增加/减少打印到 LCD 的数字。
编辑 2:我现在认为,这是一个时间问题,因为我尝试运行基本相同的代码,只是在 Arduino 上没有其他任何东西,并将值打印到串行控制台,它基本上工作得很好。
我检查了其他操作并意识到在我当前的代码中 readEncoder() 函数大约每 98 毫秒运行一次。
当我每 1 或 2 毫秒在定时器中断上运行该函数时,它根本不起作用。我什至不再对按钮按下作出反应,这是我完全不明白的事情。 事实上,定时器似乎根本没有运行,或者至少中断服务程序从未执行过。 (我尝试在设置中打开 LED 并在 isr 中将其关闭,但它无限期地保持点亮状态。)
所以我想现在有一个新问题...
这是定时器初始化:
ASSR = 0x00; //make sure we are not in asynchronous mode
OCR2 = 3; //Output compare register
TCNT2 = 0; //Reset counter to 0
TCCR2 = 0b00001111; //Timer 2 CTC mode,clkio/1024
这是在 initDecoder() 内部完成的。 OCIE2 位已在主设置中较早设置,从而启用定时器 2 中断。
isr 不仅仅是这样的:
void __interrupt (TIMER2_COMP_vect_num) timer2_isr(){
//Just read the encoder
readEncoder();
}
中断标志在执行 isr 时被硬件清除。
TIMER2_COMP_vect_num 也绝对正确,因为 MPLab 可以识别它,我什至可以查看它的定义。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)