Atmel微处理器和旋转编码器控制7段显示速度

时间:2014-12-16 13:25:15

标签: c atmel microprocessors atmelstudio

我正在尝试使用Atmel(ATmega328P Xplained mini)微处理器控制7段显示器的速度,从0到9。我的问题是,每当我运行程序时,显示器的计数越来越快,直到你能看到一个" 8"有时似乎我可以通过旋转编码器CCW保持速度下降,有时候没有效果。因为我不是那种在编程方面经验丰富的人,尤其不是这些东西,我希望有人能够并且愿意提供帮助。

这是我的代码:

#include <avr/io.h>

void Display (uint8_t x)
{
    static uint8_t tabel[] =
    {0b11000000,0b11111001,0b10100100,0b10110000,0b10011001,0b10010010,0b10000010,0b11111000,0b10000000,0b10010000};
    PORTD = tabel[x];
}

int GetInput (void)
{
    uint8_t x = PINC&1;
    uint8_t y = (PINC>>1)&1;
    if (x == 0 && y == 0) {return 0; }
    else if (x == 1 && y == 0) {return 1;}
    else if (x == 0 && y == 1) {return 2;}
    else {return 3;}
}

int main(void)
{
    DDRD = 0xFF;  // set PortD as an output
    DDRC = 0x00;  // set PortC as an input
    PORTB = 0x03; // Activate Pull-up resistors

    float d = 9000;
    int tick = 0;
    int i = 0;
    int input, state = 0; // initial state
    int oldInput = 0;

    while (1)
    {   
        input = GetInput();
        if (oldInput == 0 && input == 1)
        {
            d = (d * 1.1);
            //slower
        }else if (oldInput == 0 && input == 2)
        {
            d = (d * 0.9);
            //faster
        }else if (oldInput == 1 && input == 0)
        {
            d = (d * 0.9);
            //faster
        }else if (oldInput == 1 && input == 3)
        {
            d = (d * 1.1);
            //slower
        }else if (oldInput == 2 && input == 0)
        {
            d = (d * 1.1);
            //slower
        }else if (oldInput == 2 && input == 3)
        {
            d = (d * 0.9);
            //faster
        }else if (oldInput == 3 && input == 1)
        {
            d = (d * 0.9);
            //faster
        }else if (oldInput == 3 && input == 2)
        {
            d = (d * 1.1);
            //slower
        }
        oldInput = input;

        switch (state)
        {
            case 0: //ini
                Display(0);
                state = 1;
                break;

            case 1: //count
                if (i == 9)
                {
                    i = 0;
                    Display(i);
                }
                else
                {
                    i++;
                    Display(i);
                }
                state = 2;
                break;

            case 2: // delay
                if (tick < d)
                {
                    state = 2;
                    tick++;
                }
                else
                {
                    state = 1;
                    tick = 0;
                }
                break;

            case 3: //reset / destroy
                break;
        }
    }
}

2 个答案:

答案 0 :(得分:1)

首先尝试更改GetInput函数以返回更有用的值。请注意,PINC的位0和位1已经组合在一起形成您正在重构的整数。

int GetInput (void)
{
    // array to convert grey scale bit patterns to direction indicators.
    // Rows indexed by lastValue, columns indexed by thisValue, and the
    // content is -1 for CCW, +1 for CW, 0 for no motion.  Note that 0 is
    // also used for an invalid transition (2 bits changed at once), but a
    // different value could be used for fault detection.
    static const int tableGreyToDirection[4][4] =
    {
        0 , -1, 1 , 0 ,                        // lastValue==0
        1 , 0 , 0 , -1,                        // lastValue==1
        -1, 0 , 0 , 1 ,                        // lastValue==2
        0 , 1 , -1, 0                          // lastValue==3
    };

    static uint8_t lastValue = 0;             // A valid default starting value
    uint8_t thisValue = (PINC & 0b00000011);  // Use the bottom two bits as a value from 0..3
    int result = tableGreyToDirection[lastValue][thisValue];
    lastValue = thisValue;
    return result;
}

然后,您可以大大简化循环中的测试。

while (1)
{
    // Check the direction of the encoder: -1 = CCW, +1 = CW, anything else = no motion.
    input = GetInput();
    if(0 < input)
    {
        // Motion is CW, so increment the delay (within reasonable bounds).
        if(8900 > d) d += 100;
    }
    else if(0 > input)
    {
        // Motion is CCW, so decrement the delay (within reasonable bounds).
        if(100 < d) d -= 100;
    }

    // Keep the rest as it is...
}

建议将d更改为uint16_t并将其整理一下。进一步的提示包括使用#define为常量提供可读名称。例如。在我可以使用的指示表中:

#define ENCODER_CW 1
#define ENCODER_CCW -1
#define ENCODER_NEITHER 0

...

static const int tableGreyToDirection[4][4] =
{
    ENCODER_NEITHER, ENCODER_CCW, ENCODER_CW, ENCODER_NEITHER,  // lastValue==0
    ...

我相信你可以自己填写。

答案 1 :(得分:0)

我检查了你的SW,但我立刻找不到大问题。 你最好查看以下部分。

  1. 如果您没有触摸编码器,但速度越来越快 :您是否有权检查编码器输入端口是否从端口输入噪声。
  2. 如果两个输入端口稳定,请检查您的值是否稳定 :旧输入和新输入值应相同 :更改值时,按日志检查或输出切换未使用的端口。你可以调试自己的代码。
  3. 你最好添加金额滴答值而不是直接乘以防止d值变为0。
  4. 您的CPU必须以检测主循环中端口状态更改的速度运行。 - 我认为如果这个代码完全是你的系统就有可能。