使用 atmega8

问题描述

我正在尝试读取旋转编码器作为更大项目的一部分。我正在使用 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 (将#修改为@)