loading

PINB register on ATtiny45 not working?

I've been programming a pretty simple led driver in Atmel Studio 6 with the attiny45. The idea is that hitting a push button will advance through three different modes of the LEDs, solid, strobe, and fade. When you reach the last mode hitting the button again should reset to the first mode. For some reason the PINB register doesn't seem to be working. Here is the code:



#define F_CPU 1000000

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



int main(void)
{

//  Setup PWM
TCCR0A |= (1 << COM0A1) | (1 << WGM00) | (1 << WGM01);
TCCR0B |= (1 << CS01);
DDRB |= (1 << PB0)|(0<<PB4);

PORTB = 0b00010000;   //enable internal pull up

int state = 2;  //initialize some variables
while(1)
{
  //int val = PINB3;
 
    if(PINB == 0)   //if button is pressed, increment state variable
  {
   _delay_ms(100);   //primitive debouncing...
    state = state + 1;
  }
 
 
  if(state > 2){  //if we exceed the number of modes, reset state variable
  
   state = 0;
  }else
  {
   state = state;  //probably not necessary, but has solved problems in the past.
  }

while(state == 0){   //first mode just turns on LEDs at full brightness
 
  OCR0A = 255;
}

while(state == 1){  //second mode strobes the LEDs
 
  OCR0A = 255;
  _delay_ms(35);
  OCR0A = 0;
  _delay_ms(35);
}

while(state == 2){    //Third mode fades LEDs
 
   //  Fade LED on
   for(i = 0; i < 255; i++)
   {
    //  Load new value onto OCR0A register to change duty cycle
    OCR0A = i;
    _delay_ms(5);
   }
  
   //  Fade LED off
   for(i = 255; i >= 0; i--)
   {
    OCR0A = i;
    _delay_ms(5);
   }
}

}

}

All of the independent modes work fine, and even the state variable itself is doing what it is supposed to (I know because initializing it to different values gets me the correct mode) but for some reason the PINB register is not getting any kind of response. I am enabling the internal pull up, and then the button connects the I/0 (in this case PB4) to ground which should make the state zero and satisfy the argument of the if statement, but for some reason this is not doing anything. Any ideas? thanks in advanced!

verence3 years ago

Once the program enters one of the

while(state == xxx)
// do something
}

loops, it is trapped in an endless loop. It never gets to the point where it checks for PB4 again. (unless PB4 is an interrupt source and you do the modification of the state variable in an interrupt handler routine.

Change the while conditions like this:

while(<button not pressed>)

if (state == 0)
// do state 0
else if (state == 1)
// do state 1
else if (state == 2)
// do state 2

Checking for the button press with

if (PINB == 0)

seems odd. I may be wrong, but IIRC, PINB is the whole input register of port B, i.e. 8 bit of data. A button on PB4 will only change one bit of PINB. You have to mask this single bit with

if ((PINB & 0x10)==0) // depending on how pins are counted mask may be 0x08
// or maybe your compiler has a special syntax for that like:

if (PINB.4 == 0)

And btw., the whole

else
{
state = state; //probably not necessary, but has solved problems in the past.
}

is totally unnecessary and never solved anything. If you think so just means that you didn't understand the problem you had at that time. See Cargo_cult_programming

Higgs Boson (author)  verence3 years ago

Thanks for your suggestions! I am still new to programming with Atmel studio 6, and I am trying to get the hang of it. Once when I was using MPlabX for PICs a while ago the code wasn't working until I added the state = state thing. Not sure what was going on there, but I knew at the time there was no real reason for it to work (I am still baffled by it) and I understand why.