Cannot clear Compare Output on ATMEGA324PA

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

I'm using Timer2 on the ATMega324PA with an external 32.768kHz crystal on TOSC1/TOSC2. Timer2 is running in CTC mode, and I'd like to create an output pulse on either OC2A or OC2B. I have set the compare output mode to "Set OC2A on compare match". I'd like to clear the OC2A a bit later in my software, without affecting the running timer in any way. I have tried to use FOC2A to do that, by setting the compare output mode to "Clear OC2A on Compare match", writing 1 to FOC2A, and then changing the outputmode back to it's original value ("Set OC2A on compare match") so that the output is set again on the next timer2 match. This doesn't work, however, because OC2A is set once and stays set forever. Any ideas how the  OC2A/OC2B output can be cleared?

 

 

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

That is indeed tricky.  Once you "connect" the pin to the timer you lose normal control.

 

At the expense of a few cycles (and perhaps a race depending on how close "some time later" is) you can disconnect the pin from the timer, clear the pin, then reconnect for next time.  But you said

...without affecting the running timer in any way.

What I suggested won't change the timer's counting, but is strictly an "any way" I guess--why the requirement so strict?

 

If the "some time later" is fixed, then you could use a PWM mode.

 

Or, don't connect the pin to the timer but have a compare-match interrupt that does the work.

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.

Last Edited: Thu. Mar 12, 2015 - 01:43 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for your answer.

 

At the expense of a few cycles (and perhaps a race depending on how close "some time later" is) you can disconnect the pin from the timer, clear the pin, then reconnect for next time. 

Do you mean I should set COM2A1/COM2A0 to 0/0 for "Normal port operation", set the port bin to low level, and then set COM2A1/0 back to "Set on compare match"?

 

What I suggested won't change the timer's counting, but is strictly an "any way" I guess--why the requirement so strict?

I'm using Timer2 as RTC, I just want to make sure that there are no cycles lost, for example by reprogramming Timer2.

 

If the "some time later" is fixed, then you could use a PWM mode.

That's a good idea, I'll check if I can live with the time intervals that PWM modes can provide.

 

 

 

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

Do you mean I should set COM2A1/COM2A0 to 0/0 for "Normal port operation", set the port bin to low level, and then set COM2A1/0 back to "Set on compare match"?

 

Yes.  As "Set on compare match" is typically both bits set, indeed it may well introduce RMW  on TCCR2A. 
IN/ANDI/OUT then the CBI for the port bit then IN/ORI/OUT.  I suppose it could be CBI/CBI CBI SBI/SBI.  Now, again it depends on how long your "bit later" is, and whether there is a race for the next compare match.

 

That's a good idea, I'll check if I can live with the time intervals that PWM modes can provide.

 

???  I guess I assumed that the watch crystal was used for one-second operation.  But you've never given me a hint of what "bit later" means.

 

 

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

At the expense of a few cycles (and perhaps a race depending on how close "some time later" is) you can disconnect the pin from the timer, clear the pin, then reconnect for next time.

This won't work. As soon as you go back to having the timer control the pin, it will be set to whatever the timer thinks it should be.

I have tried to use FOC2A to do that, by setting the compare output mode to "Clear OC2A on Compare match", writing 1 to FOC2A, and then changing the outputmode back to it's original value ("Set OC2A on compare match") so that the output is set again on the next timer2 match.

I believe that this should have worked.

Regards,
Steve A.

The Board helps those that help themselves.

Last Edited: Thu. Mar 12, 2015 - 04:27 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This won't work. As soon as you go back to having the timer control the pin, it will be set to whatever the timer thinks it should be.

At first  blush, I don't agree.  (I remember a thread some months back when this was hashed out.)  But I guess it could work that way.  So the timer needs to be stopped?  Doesn't sound right.  Remember that we are not in a PWM mode.

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

At first  blush, I don't agree.

At second blush, I do agree.  (It still doesn't quite make sense to me, but...)

 

I took a Mega1280 app on the bench, that has my LCD backlight on OC5A and timer5 otherwise unused.  Set up free-running, and set OC5A on compare match.  Tried a couple different combinations of manipulating the COM bits, with results as Steve A. predicted.

 

However, I found (at least?) two methods:

 

TCCR5A &=~((1<<COM5A1) | (1<<COM5A0));	// COM bits off
//LCD_BACKLIGHT_OFF();
TCCR5A |= (1<<COM5A1);					// COM bits to Clear on match
TCCR5C = (1<<FOC5A);					// Force match
// for my sanity delay_ms(250);
TCCR5A |= ((1<<COM5A1) | (1<<COM5A0));	// COM bits to Set on match

Note that it wasn't needed to set the port pin low with this method (PL3).

 

The second way is to set up the timer for "toggle on compare match".  For testing, I qualified it with the OC5A being on.  One FOC needed...sounds ideal for OP unless the "bit of time" gets close to a full period; then the qualification might be useful.

 

if (PINL & (1<<3))
	{
	TCCR5C = (1<<FOC5A);					// Force match
	}

 

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

So the timer needs to be stopped?  Doesn't sound right.

It has nothing to do with the timer being stopped or not. It has to do with the fact that the timer overrides normal port operation, so it doesn't give a hoot about how you change setting of other things controlling that pin.

However, I found (at least?) two methods:

The first is what I recall from other threads should work. I suspect that when the OP tried something similar that something was wrong with the code, not the principle.

Regards,
Steve A.

The Board helps those that help themselves.

Last Edited: Thu. Mar 12, 2015 - 07:41 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The first is what I recall from other threads should work. I suspect that when the OP tried something similar that something was wrong with the code, not the principle.

Assuming it is indeed a slow timer with e.g. 1 second period, various combinations of compare-match interrupts could be used.

 

-- If the "bit of time" is indeed fixed, then use a Fast PWM and be done.

-- Toggle can be used if you don't get out of sync.

-- One can use toggle, (or change Set/Clear COM settings,) and use a leapfrog approach with OCR2A.

-- One could abandon the COM bits, set arbitrary pin in compare match A ISR and set compare match B to the "bit of time" in the future, clearning the arbitrary pin in the ISR.

 

"How can I clear thee?  Let me count the ways..."

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

It has nothing to do with the timer being stopped or not. It has to do with the fact that the timer overrides normal port operation, so it doesn't give a hoot about how you change setting of other things controlling that pin.

I guess that my thinking was when you set COM bits to 

 

0 0 Normal port operation, OCnA/OCnB/OCnC disconnected
 

that the timer would not keep any "memory" of what it used to do, or what it did in the past.  Wrong assumption, apparently.  The datasheet isn't clear one way or the other.  While there is a breakout of the Waveform Generator block it doesn't show any latches or such.

 

 

ely the OCFnx Flag can be cleared by software by writing a logical one to its I/O bit location. The Waveform Generator uses the match signal to
generate an output according to operating mode set by the Waveform Generation mode
( WGMn3:0) bits and Compare Output mode (COMnx1:0) bits.

 

It would seem to me that with this latching/memory, one  could have unpleasant surprises when changing modes.  E.g. timer set up and running in a certain mode with whatever combination of WGM/COM/... is appropriate.  Now the app clears all the timer registers including TIFR, and then does a re-setup in a different combination of WGM/COM.  With this latching/memory, could one then get a spurious action on the OC pins?

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

I tried the same method like your example with "force output compare", and it didn't work. The output compare is always high level.

After some experimenting, I found the reason:

My timer is clocked from a crystal on TOSC1/2. After removing the line

 

   ASSR = (1<<AS2);

 

from my code, the OC output was working as expected, but used the internal clock. This doesn't solve my problem, however, because I need the TOSC1/2 crystal as clock source.

 

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

That doesn't make much sense to me.  The timer should operate the same regardless of the clock source, right?

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.

Last Edited: Fri. Mar 13, 2015 - 04:41 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch wrote:

That doesn't make much sense to me.  The timer should operate the same regardless of the clock source, right?

That's what I thought too. Right now, I found something very interesting about the async operation of Timer/counter2 ATmega164A_PA-324A_PA-644A_PA-1284_P_datasheet.pdf, 17.9 (page 148):

When writing to one of the registers TCNT2, OCR2x, or TCCR2x, the value is transferred to a temporary register, and latched after two positive edges on TOSC1. The user should not write a new value before the contents of the temporary register have been transferred to its destination.

That means I can't do any immediate changes on the OC outputs in async mode.

 

 

 

Last Edited: Fri. Mar 13, 2015 - 07:28 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Did you try my second "toggle" method?  That is only one register write, which should "take".

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

theusch wrote:

Did you try my second "toggle" method?  That is only one register write, which should "take".

Yes, this works, but there is a delay of two TOSC cycles until OC changes (~60us with a 32.768kHz crystal).

In sync mode, the OC output changes immediately.

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

You have never expounded on what "a bit later" means.  You are now implying that the pulse width is important.  Is it?  Then use PWM.
 

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

theusch wrote:

You have never expounded on what "a bit later" means.  You are now implying that the pulse width is important.  Is it?  Then use PWM.
 

 

My RTC interrupt is 64 times a second (=every 15.6msec). "A bit later" is roughly 200-500usec after OC goes high. Then, some measurements are made (with OC still high!). After this, the OC should be set to Low as soon as possible. The "High" time is not critical, it just shouldn't be too long because this activates a pullup, and consumes battery power. Ideally, there should be only one Interrupt for each period to keep the cpu in sleep mode as much as possible. I haven't yet tried that, but I think it should be possible to use OCRA to switch to high level without cpu intervention, and OCRB to trigger a interrupt ~200-500usec later.

                           __________
OC ________________________!        !__
                                  ^

                                  measurement, turn Port/OC low afterwards.