如果vs Case。如果奇怪地增加

时间:2015-10-06 17:23:21

标签: c embedded

我正在学习嵌入式编程,并将LED板和按钮板连接到同一个PORT。

在chk_button函数下注释掉if语句,激活时某些按钮会将num预期增量+ 1加到num变量中.IE:按下按钮1将增加num。当前案例陈述适用于规范。

我理解案例陈述,当有效编译成查找表,因此占用空间更小,运行速度更快,但我不确定为什么我得到了我的错误。

我也对我的代码中的任何其他批评持开放态度。

//  HARDWARE SETUP:
//  PORTA is connected to the segments of the LED display. and to the pushbuttons.
//  PORTA.0 corresponds to segment a, PORTA.1 corresponds to segement b, etc.
//  PORTB bits 4-6 go to a,b,c inputs of the 74HC138.
//  PORTB bit 7 goes to the PWM transistor base.

#include <avr/io.h>
#include <util/delay.h>

#define F_CPU 16000000
#define DIGIT_ONE  0x00
#define DIGIT_TWO  0x10
#define DIGIT_COLON 0x20
#define DIGIT_THREE  0x30
#define DIGIT_FOUR 0x40

//******************************************************************************
//                           debounce_switches
//Checks the state of the button number passed to it. It shifts in ones till
//the button is pushed. Function returns a 1 only once per debounced button
//push so a debounce and toggle function can be implemented at the same time.
//Adapted to check all buttons from Ganssel's "Guide to Debouncing"
//Expects active low pushbuttons on PINA port.  Debounce time is determined by
//external loop delay times 12.
//Saves status of button (i) into a state array.
//******************************************************************************
int8_t debounce_switches(uint16_t *state, uint8_t i) {
  state[i] = (state[i] << 1) | (! bit_is_clear(PINA, i)) | 0xE000;
  if (state[i] == 0xF000) return 1;
  return 0;
}
//******************************************************************************
//                          chk_buttons
//Checks the buttons. Calls debounce_switches in a loop passing both the state array
//and the current switch being checked.
//If debounce_switches returns a 1 for a switch, case statements determine which switch
//was activated, and increments count by the appropriate value.
//******************************************************************************
void chk_buttons(uint16_t *state, uint16_t *num)
{
    uint8_t itr;
    for( itr=0; itr<8; itr++)
    {
        if( debounce_switches(state, itr))
        {
            switch(itr)
            {
                case 0:
                    *num += 1;
                    break;
                case 1:
                    *num += 2;
                    break;
                case 2:
                    *num += 4;
                    break;
                case 3:
                    *num += 8;
                    break;
                case 4:
                    *num += 16;
                    break;
                case 5:
                    *num += 32;
                    break;
                case 6:
                    *num += 64;
                    break;
                case 7:
                    *num +=128;
                    break;
            }
        /*
            if (itr == 0)     *num += 1;
            else if(itr == 1) *num += 2;
            else if(itr == 2) *num += 4;
            else if(itr == 3) *num += 8;
            else if(itr == 4) *num += 16;
            else if(itr == 5) *num += 32;
            else if(itr == 6) *num += 64;
            else if(itr == 7) *num += 128;
        */
        }


    }
}

//******************************************************************************
//                         itoseven
// Accepts a number from 0 -9 Returns a hex value to display on the seven segment..
//******************************************************************************
uint8_t itoseven(uint8_t num)
{
    uint8_t segnum;
    switch(num)
    {
        case 0:
                 segnum = ~0x3F;
                 return segnum;
        case 1:
               segnum = ~0x06;
               return segnum;
        case 2:
               segnum = ~0x5B;
               return segnum;
        case 3:
               segnum = ~0x4F;
               return segnum;
        case 4:
               segnum = ~0x66;
               return segnum;
        case 5:
               segnum = ~0x6D;
               return segnum;
        case 6:
               segnum = ~0x7D;
               return segnum;
        case 7:
               segnum = ~0x07;
               return segnum;
        case 8:
               segnum = ~0x7F;
               return segnum;
        case 9:
             segnum = ~0x6F;
             return segnum;
    }
}

//***********************************************************************************
//                                   segment_sum
//takes a 16-bit binary input value and displays the result to the LED board.
//***********************************************************************************
void segsum(uint16_t num) {
    uint8_t ones;
    uint8_t tens;
    uint8_t hundreds;
    uint8_t thousands;
  //break up decimal sum into 4 digit-segments
    ones = num % 10;
    tens = (num/10)%10;
    hundreds = (num/100)%10;
    thousands = (num/1000)%10;
  //determine how many digits there are
    if(num < 10)
    {
        PORTB = DIGIT_ONE;
        PORTA = itoseven(num);
    }
    else if(num > 9 && num <100)
    {
        PORTB = DIGIT_ONE;
        PORTA = itoseven(ones);
        _delay_ms(2);
        PORTB = DIGIT_TWO;
        PORTA = itoseven(tens);
    }
    else if(num > 99 && num < 1000)
    {
        PORTB = DIGIT_ONE;
        PORTA = itoseven(ones);
        _delay_ms(2);
        PORTB = DIGIT_TWO;
        PORTA = itoseven(tens);
        _delay_ms(2);
        PORTB = DIGIT_THREE;
        PORTA = itoseven(hundreds);
    }
    else if (num >999)
    {
        PORTB = DIGIT_ONE;
        PORTA = itoseven(ones);
        _delay_ms(2);
        PORTB = DIGIT_TWO;
        PORTA = itoseven(tens);
        _delay_ms(2);
        PORTB = DIGIT_THREE;
        PORTA = itoseven(hundreds);
        _delay_ms(2);
        PORTB = DIGIT_FOUR;
        PORTA = itoseven(thousands);
    }
}

uint8_t main()
{
    DDRB = 0xF0; //set port bits 4-7 B as outputs
    uint16_t num = 0;
    uint16_t state[8];
    //initialize array values for debouncing
    for(int i=0; i<8; i++)
    {
        state[i]= 0;
    }
    while(1)
    {
        //make PORTA an input port with pullups
        DDRA = 0x00;
        PORTA = 0xFF;
        //enable tristate buffer for pushbutton switches
        PORTB = 0x70;
        //check the buttons. Increment by appropriate value if switch is active.
        chk_buttons(&state, &num);
        //rollover at 1023
        if(num > 1023)
            num = 1;
        //switch PORTA to output
        DDRA = 0xFF;
        //Send num to display
        segsum(num);
        _delay_ms(2);
    }
    return 0;
}

1 个答案:

答案 0 :(得分:1)

我已更新这些功能以删除开关,因为根本不需要它们。注意第一个使用算法代替开关,第二个使用一个易于在将来调整的表。此外,断言/错误检查您的输入,当事情横向发展时,您将成为一个更快乐的露营者。

void chk_buttons(uint16_t *state, uint16_t *num)
{
    // Assert bad state and num here.  

    uint8_t itr;
    for( itr=0; itr<8; itr++)
    {
        if( debounce_switches(state, itr))
        {
            *num += 1 << itr; // Could also use |= as that is what we are doing.
        }
    }
}

uint8_t itoseven(uint8_t num)
{
    // assert num <= 9

    const uint8_t kLookup[10] = 
    {~0x3f, ~0x06, ~0x5B, ~0x4F, ~0x66, 
     ~0x6D, ~0x7D, ~0x07, ~0x7F, ~0x6F};

    return kLookup[num];
}

对于最后一个功能,如果从4位数字开始检查并向后工作到单个数字,它将成为一个非常简单的循环来进行复杂的数字计算。只需将你的面具从10,000分为10.我会稍后发布该代码,因为我有时间。

更新

这是我编写的内容,用于演示这个想法。您需要为自己的功能修改它,因为它现在只输出ASCII。它不能用于负数(就像你的代码一样),但是如果检查/ ABS /前置一个减号字符就很容易添加。

int main(void)
{
    int num = 9876;

    // Starting at the 5th digit.  You could use 1000 instead if 
    // there were only 4 digits or less ever.
    int digitMask = 10000;
    char output[16];
    int index = 0;

    // Handle 0 case.
    if(num== 0)
    {
        output[index++] = '0';
    }
    else
    {
        // Skip leading 0's
        while((num / digitMask) == 0)
        {
            digitMask /= 10;
        }

        // While there may be digits to process...
        while(digitMask)
        {
            // Grab MS Digit and mod it away from total.
            int digit = num / digitMask;
            num %= digitMask;

            // Convert to ASCII (you would use your own function)
            output[index++] = digit + '0';

            // Update mask - note we could use a for/loop here just as easily.
            digitMask /= 10;
        }
    }

    // Terminate string and print it.
    output[index] = 0;
    printf("%s", output);

    return 0;
}