PWM in ATmega48

Go To Last Post
7 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

I'm new to this forum, to ATmega (or microcontrollers in general) and to C, so be patient with me... :wink:

My project is to control a led on a STK500 with PWM using a ATmega48. The idea is to have the intensity of the led increase and decrease by pushing switches 3 & 4. See code below. Starting point was code from Joerg Wunsch, which increased/decreased the led automatically, by having the pwm change direction when overflowing. This worked fine before, so my pwm settings should be correct. However, with the code below the led on PB1 just switches on and stays at max intensity.

Does anyone has a clue of what is wrong in the code below?

Thanks,
Leon

#include 
#include 
#include 

#define TIMER1_TOP 1023	/* 10-bit PWM */
#define TIMER1_PWM_INIT _BV(WGM10) | _BV(WGM11) | _BV(COM1A1)
#define TIMER1_CLOCKSOURCE _BV(CS10) /* full clock */

enum { UP, DOWN, ZERO};
static uint16_t pwm;        
static uint8_t direction;

ioinit (void)                   
{
    /* Timer 1 is 10-bit PWM */
    TCCR1A = TIMER1_PWM_INIT;
   	TCCR1B |= TIMER1_CLOCKSOURCE;
   	
    /* Run any device-dependent timer 1 setup hook if present.   */
#if defined(TIMER1_SETUP_HOOK)
    TIMER1_SETUP_HOOK();
#endif

    /* Set PWM value to 0. */
    OCR1A 	= 0;

    /* Enable PB1 as output. */
    DDRB 	= 14;
	PORTB 	= 14; 
	
    /* Enable Port D as input. */
	DDRD	= 0x00;                  

    PORTD	= 0xff;                  /* activate internal pull-up*/


    /* Enable timer 1 overflow interrupt. */
    TIMSK1 	= _BV (TOIE1);
    direction 	= ZERO;
    sei ();
}

ISR (TIMER1_OVF_vect)           
{
		switch (direction)         
	    {
	        case UP:
	            if (++pwm >= TIMER1_TOP)
    	            --pwm;
    	        break;
	        case DOWN:
	            if (--pwm <= 0)
    	            ++pwm;
    	        break;
	    }
	OCR1A = pwm;                  
}

int
main (void)
{
    uint8_t   led; 

    uint8_t   keys;
	
    ioinit ();
	
    while(1)
    {    
		keys = ~PIND;
		if ( keys == 4 )
		{
			direction 	= UP;
			PORTB 		= ~4;
		}
		else if ( keys == 8 )
		{	
			direction 	= DOWN;
			PORTB 		= ~8;
		}
		else
		{	
			direction 	= ZERO;
			PORTB 		= 14;
		}	
 	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

FAQ#1

make direction 'volatile'.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Clawson,

Thx! That was it. Stupid, should have RTFFAQ :-)

Leon

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Clawson,

To which FAQ are you referring? The only faq i can find on this site is the faq concerning the forum itself.

Leon

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

1. Clawson has a 5-item FAQ as his footer.
2. There is a FAQ in the avr-libc documentation (which is the run-time lib that comes with the avr-gcc compiler the OP uses).

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As Johan says, the mini FAQ in the footer of my posts was in part inspired by the large FAQ in the GCC user manual:

http://www.nongnu.org/avr-libc/u...

See item 1 there. In fact read the whole FAQ - loads of useful info and when you have finished that page go on and read the entire manual - all good stuff!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
http://www.nongnu.org/avr-libc/u...
See item 1 there. In fact read the whole FAQ

Thx, good link&advice!