ATMEGA168 Timer 1 Output Compare B problem

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

I have a problem with Timer 1 and output compare register B.

I initialize the timer register with this code:

    clr    reg17                            ; set high byte of output compare b to zero
    ldi    reg18,        timer_inc            ; set low byte of output compare b to 50
    sts    ocr1bh,        reg17                ; set timer1 ocb hi
    sts    ocr1bl,        reg18                ; set timer1 ocb lo
Thie works perfectly. After initialization I enable interrupts and start the timer clocking off the 4 MHZ clock.

The interrupt occurs when the timer1 reaches 0x0032.

During the output compare interrupt, in the routine, I want to increase the output compare value to 100

I do this:

    ldi    reg17,      0x00
    ldi    reg18,      0x64
    sts    ocr1bh,        reg17                ; set timer1 ocb hi
    sts    ocr1bl,        reg18                ; set timer1 ocb lo

I run the code in the simulator in Studio, version 7, on a Windows 10 computer.

I watch the timer1 values and registers in the simulator Timer 1 window.

After this code executes, OCR1Bh,l is still showing as 0x0032. It will not update to the new value of 0x0064.

I do the high byte first, as you're supposed to.

The actual board execution behaves like the output compare value isn't changing too. I see no assembler errors when building the code.

It's as though you're only allowed to program the output compare register once, but I know that's not right.

 

What the heck am I missing???

 

Wally Gibbons

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

I set up this simple demo. The PD6 line changes about 62us after the PD5 line changes.

/*
 * Demo_Cnt1.c
 *
 * Created: 10/24/2020 11:54:32 AM
 * Author : CmdrZin
 *
 * Change PD6 50 counts after PD5 changes.
 */ 

#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdbool.h>

typedef enum { S_PD5_TOGGLE, S_PD6_TOGGLE } STATE_CONTROL;

volatile STATE_CONTROL state = S_PD5_TOGGLE;

bool flag_pd5 = false;
bool flag_pd6 = false;

int main(void)
{
	// Initialize Timer1 to interrupt on Compare B match.
	// Default TCCR1A is Normal non-PWM, WGM = 0000 (Mode 0)
	TCCR1B = (1<<CS10);		// clk/1
	// Default TCCR1C. Not used.
	// OCR1A not used
	OCR1B = 0x0032;		// 50 as in code.
	TIMSK1 = (1<<OCIE1B);	// Interrupt on Compare B match.
	// TIFR1 handled in hardware.
	
	// Set up I/O lines as outputs
	DDRD = (1<<PORTD5) | (1<<PORTD6);
	
	sei();		// enable global interrupts
	
    /* Replace with your application code */
    while (1) 
    {
    }
}

// Timer1 Compare B match
ISR(TIMER1_COMPB_vect)
{
	switch(state) {
		case S_PD5_TOGGLE:
			if(flag_pd5) {
				PORTD |= (1<<PORTD5);
				flag_pd5 = false;
			} else {
				PORTD &= ~(1<<PORTD5);
				flag_pd5 = true;
			}
			// Update OCR1B to 0x0064 (100)
			OCR1B = 0x0064;
			// Next state
			state = S_PD6_TOGGLE;
			break;

		case S_PD6_TOGGLE:
			if(flag_pd6) {
				PORTD |= (1<<PORTD6);
				flag_pd6 = false;
			} else {
				PORTD &= ~(1<<PORTD6);
				flag_pd6 = true;
			}
			// Update OCR1B to 0x0032 (50)
			OCR1B = 0x0032;
			// Next state
			state = S_PD5_TOGGLE;
			break;
			
		default:
			state = S_PD5_TOGGLE;
			break;
	}	
}

and a look at the .lss file shows the assembly code.

			// Update OCR1B to 0x0064 (100)
			OCR1B = 0x0064;
  e4:	84 e6       	ldi	r24, 0x64	; 100
  e6:	90 e0       	ldi	r25, 0x00	; 0
  e8:	90 93 8b 00 	sts	0x008B, r25	; 0x80008b <__DATA_REGION_ORIGIN__+0x2b>
  ec:	80 93 8a 00 	sts	0x008A, r24	; 0x80008a <__DATA_REGION_ORIGIN__+0x2a>

which loads high then low, the same as yours. So the issue is somewhere else in your code.

"If you find yourself in an even battle, you didn't plan very well."
http://pc.gameactive.org

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

Post a complete program -- we cannot see the timer setup, loop, etc. 
Tell what tool you are using to get your result.  Tell what you expect.

 

What does the datasheet say about when OCR gets updated in the timer mode that you have chosen?

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Actually, folks, I delved deeper into the compare registers for timer one. When I first write to the OCR1B the timer isn't running.

When I attempt the second write to the compare register the timer is actually running and I'm trying to do the write in the interrupt routine called by the compare match.

AND, since WGM is 11, the output compare register is double buffered, and doesn't update until the top value is reached. (Or, the compare value in OCR1A, in my case).

I've modified my code to use the double buffering feature and it's working fine now. The simulation behaves like it should and the timer operation on my hardware is as I expect.

I'm getting a nice PWM waveform out of the output pin toggled by the OCR1B compare.

 

Thanks for the responses.

 

I'm calling it problem solved, I just needed to do more digging!!

 

Wally Gibbons

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

Still, next time tell AVR model and post a complete program.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

wally.gibbons@gmail.com wrote:
I'm calling it problem solved

In which case, please mark the solution - see Tip #5 in my signature, below, for instructions:

 

(also note Tip #1 for how to properly post source code)

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...