Search code examples
avratmega32

PORTB's LEDs controlling via input PINA in avr


I'm trying to write a code in Atmel so I can control atmega32 PORTB's pins via switches connected to PINA, it works but there is only one problem, if one switch is left high and an another switch turns high the led connected(relates) to the second pin doesn't change, where did i go wrong?

#include <avr/io.h>
#include <util/delay.h>
#define F_CPU 1000000UL                         //Setting the CPU frequency to 1MHz
toggle(void){                               //Creating a toggle function to call it within the main function
    unsigned char input = 0x00;                 //Creating an 8-bit variable so we can save the input port
    int t = 1;                              //Loop variable
    while(PINA != 0x00){
    t = t + 1;
    _delay_ms(1);
    if(t == 100) break;
    }
    while(t != 100){
        if((PINA != 0x00) && (input !=PINA))
        {
            input = PINA;
            PORTB = PORTB^input;
            t = t + 1;
            _delay_ms(1);
        }
        else if(input == PINA)
        {
            t = t + 1;
            _delay_ms(1);
        }
        else if(PINA == 0x00){
            t = t + 1;
            _delay_ms(1);
            input = PINA;
        }
    }
}

int main(void)
{
DDRA = 0x00;                                //Setting PORTA as input
DDRB = 0xFF;                                //Setting PORTB as output
DDRC = 0xFF;                                //Setting PORTC as output
DDRD = 0x02;                                //Setting PORTD.2 as output
PORTB= 0x00;                                //Setting PORTB's output to zero
PORTC= 0x00;                                //Setting PORTC's output to zero
PORTD= 0x02;                                //Setting PORTD.2's output to one
while (1) 
{
PORTD= 0x02;                                //Turning on the PORTD LED
toggle();                                   //Toggling the PORTB's LEDs
PORTD= 0x00;                                //Turning off the PORTD LED
toggle();                                   //Toggling the PORTB's LEDs

} }


Solution

  • Analyze your code

    look at this section

    while(PINA != 0x00){
        t = t + 1;
        _delay_ms(1);
        if(t == 100) break;
        }
    while(t != 100){
        //your algorithm body processed here
    }
    

    if one of switches (which connected to PORTA) is left high then the first while loop condition PINA != 0x00 is always true the loop finish only when t==100, then, when you go to the second while Loop it will not excite because the condition t != 100 is already false

    in other words your toggle() function will not process any data until you release all switches

    solution

    I have made a simple code for what you try to do

    int main(void)
    {
        DDRA = 0x00;                                //Setting PORTA as input
        DDRB = 0xFF;                                //Setting PORTB as output
        DDRC = 0xFF;                                //Setting PORTC as output
        DDRD = 0x02;                                //Setting PORTD.2 as output
        PORTB= 0x00;                                //Setting PORTB's output to zero
        PORTC= 0x00;                                //Setting PORTC's output to zero
        PORTD= 0x02;                                //Setting PORTD.2's output to one
        
        unsigned char currentInput=PINA;            
        unsigned char previousInput=PINA;
        unsigned char changedBitsMusk = 0;
        while (1)
        {
            currentInput = PINA; //update current reading
            
            changedBitsMusk = currentInput ^ previousInput; // calculate what is changed from previous reading 
            if (changedBitsMusk)        // if there is change happen
            {
                if (currentInput&changedBitsMusk) // only process the data if change is HIgh (i.e only when button is pressed)
                {
                    PORTB^=changedBitsMusk; // toggle the corresponding pins
                }
            }
            previousInput = currentInput; 
        }
    }