PORTB's LEDs controlling via input PINA in avr

833 Views Asked by At

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

} }

2

There are 2 best solutions below

1
On BEST ANSWER

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; 
    }
}

4
On

When you are trying to control outputs according to another port inputs, you can simply do something like

PORTB = PINA;

Of course, if you don't need the full port you can always mask the bits you need from the entire port. Also, this is not the way to do it if you don't have the same pin numbers paired in both ports (i.e.: if the pin 3 of one port controls the behavior of the pint 6 of the other, for example) This way you can avoid a lot of ugly and complex logic

If you want to continue in the path you are going, try removing the "else" from the "else if"s, they are not needed and as far as I can see, the conditions are mutually exclusive