Search code examples
cavratmel

AVR C : 8 Bit Counter using button


I have circuit setup, that turns the led on every time a button is pressed and it counts up from 0 to 255, so in binary 0000 0000 to 1111 1111. My switch is configured to PB2 which is D9 on the board.

I facing a problem, as you can see from my coud I am using 8 pins, 6 from D register and 2 from B register. When I increment PORTB and at some point it become 0b00000100, then its the same value as then input pin which is pb2 so in my infinite loop even though I am not pressing the button for PINB, it gets turned on. I tried resetting the values of PORTB to 0 but still it won't turn off.

I need a mechanism so when I increment PORTB it doesn't effect my input pin which is PB2.

Please any help is appreciate, I tried posting the video but its too big.

#include <avr/io.h>
#define F_CPU 16000000UL
#include <util/delay.h>

/*
    Board digital I/O pin to atmega328 registers for LEDS
    | d2  | d3  | d4  | d5  | d6  | d7  | d8  | d9  |
    | pd2 | pd3 | pd4 | pd5 | pd6 | pd7 | pb0 | pd1 |

    Input Button
    | d9  |
    | pb2 |


*/


int main(void) {

    int x;

    DDRD = 0b11111100; 
    PORTD = 0b00000000;

    DDRB = 0b00000011; 
    PORTB = 0b00000100;

    while(1) {

        if((PINB & 0b00000100) == 0) {

            if(x < 63) {

                PORTD = PORTD + 0b00000100;
                x++;

            } else if (x == 63) {

                x=0;
                PORTD = 0b00000000;
                PORTB = PORTB + 0b00000001;

                //problem here, when PORTB is incremented to 0b00000100 then the switch turns on automatically
                if((PORTB & 0b00000100) == 0b00000100) {
                    PORTB = 0b00000000;
                    PORTD = 0b00000000;
                }

            } 

            _delay_ms(80);


        }

    }

    return 0;
}

Solution

  • The easy answer is to avoid using PORTB as a variable. Rather, use x, and shift the value in x appropriately to display it.

    #include <avr/io.h>
    #define F_CPU 16000000UL
    #include <util/delay.h>
    
    /*
    Board digital I/O pin to atmega328 registers for LEDS
    | d2  | d3  | d4  | d5  | d6  | d7  | d8  | d9  |
    | pd2 | pd3 | pd4 | pd5 | pd6 | pd7 | pb0 | pd1 |
    
    Input Button
    | d9  |
    | pb2 |
    */
    
    
    int main(void) {
    
        uint8_t x = 0;
    
        DDRD = 0b11111100; 
        PORTD = 0b00000000;
    
        DDRB = 0b00000011; 
        PORTB = 0b00000100;
    
        while(1) {
    
            if((PINB & 0b00000100) == 0) {
    
                ++x;
    
                PORTD = x << 2;
                PORTB = (PORTB & 0b11111100) | ((x >> 6) & 0b00000011);
            } 
    
            _delay_ms(80);
        }
        return 0;
    }