Timer1 and interrupt every second ?

Go To Last Post
58 posts / 0 new

Pages

Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Guys,

I tried to get the interrupt function running every second,

Here's my timer1 configuration, what do I miss here ?

TCCR1A = (1<<WGM12);
	TCCR1B = (1<<CS12|1<<CS11|1<<CS10);
	TIFR = (1<<TOV1);            //Clear pending TOV1 interrupt
	OCR1A = 15625-1;
	MCUCR = 0x00;
	EICRA = 0x00; //extended ext ints
	EIMSK = 0x00;
	TIMSK = 1<<OCIE1A;

ISR(TIMER1_COMPA_vect)
{
	seconds++;
	
	if(seconds == 60)
	{
		seconds = 0;
		minutes++;
	}
	if(minutes == 60)
	{
		minutes = 0;
		hours++;
	}
	if(hours > 23)
	hours = 0;
}

Thanks

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

Quote:

Here's my timer1 configuration, what do I miss here ?

1) Telling us which AVR model is involved.
2) Telling us the clock speed of said AVR.
3) Telling us how you verified that the AVR is indeed running at said speed.
4) Telling us what you expect to happen.
5) Telling us what >>does<< happen.
6) Telling us how you are testing.

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

Quote:

what do I miss here ?

What makes you think there is anything missing/wrong? Tell us how you tested it, what you were expecting to see, what you actually saw.

BTW tip for the future: if you want others to play the game then post complete/compilable test programs so others can try them and see what results they get.

Just guessing but if things aren't happening at the speed you expect then likely the 15625 there was calculated based on some assumption of what F_CPU is. Maybe that assumption was wrong?

EDIT: tip not top

Last Edited: Sun. Jun 15, 2014 - 02:47 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

what do I miss here ?

7) Posting a >>complete<< test 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

Well, I can see the obvious problem.

Hint. Read your data sheet. e.g. CS12

David.

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

david.prentice wrote:
Well, I can see the obvious problem.

Hint. Read your data sheet. e.g. CS12

David.

Like this ?

TCCR1B = (1<<CS12|0<<CS11|1<<CS10);
	TIFR = (1<<TOV1);            //Clear pending TOV1 interrupt
	OCR1A = 15625-1;
	MCUCR = 0x00;
	EICRA = 0x00; //extended ext ints
	EIMSK = 0x00;
	TIMSK = 1<<OCIE1A;
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I used timer0 and it worked ok, but too fast for 1 second :


TCCR0=(1<<CS00)|(1<<CS01)|(1<<CS02); // Use mINIMUM prescaller: = 1:1024
TIFR = (1<<TOV0); //Clear pending TOV0 interrupt
TCNT0=0x4E; // Start counter from 0x4E, overflow at 10 mSec
//multitask with timer0 setting begin
MCUCR = 0x00;
EICRA = 0x00; //extended ext ints
EIMSK = 0x00;
TIMSK|=(1<<OCIE0);

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

I got it working on 1 second for this setting, but it's different with calculation...it's 1:256...suppose to be 1:1024 prescaller...

I don't understand...my clock is 16MHz, just wondering why ??

TCCR1B = (1<<CS12|0<<CS11|0<<CS10);
TIFR = (1<<TOV1); //Clear pending TOV1 interrupt

OCR1A = 15625;
MCUCR = 0x00;
EICRA = 0x00; //extended ext ints
EIMSK = 0x00;
TIMSK = 1<<OCIE1A;

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

#define F_CPU 16000000UL  // 16 MHz

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

Just setting a define to 16000000 does not necessarily mean the CPU *is* running at that speed!

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

How can I know, it's exactly 16MHz then ?

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

Did you actually answer >>any<< of my questions?

I did not post them to take time out of my Father's Day. If you would have heeded them, >>then<< we can help you to diagnose the symptoms. And in fact, if you go through them one-by-one, the solution will probably become apparent.

[So, by your logic, if you set FCPU to 1234567 then your AVR runs at 1.234MHz? And if you set it to 321 then it runs at 321Hz?]

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 put 16MHz crystal for it and CLK0:3 = 1111 so it's 16MHz, I follow

frequency of your timer interrupt will be equal to the following:

microcontroller clock frequency/(prescaler)×(compare match register value+1)

and for 1 Hz,
It's supposed to be
1 = 16 Mhz /(1024*15625),
but if I used 1024 and prescaler and 15625 as OCR1A value, it's not 1Hz,

I don't know why, the code I used now (almost 1Hz) but it's not following the calculation:

TCCR1B = (1<<CS12|0<<CS11|0<<CS10);
TIFR = (1<<TOV1); //Clear pending TOV1 interrupt
OCR1A = 5000;
MCUCR = 0x00;
EICRA = 0x00; //extended ext ints
EIMSK = 0x00;
TIMSK = 1<<OCIE1A

it's 16 MHz / (256*5000), 12 Hz....but it's not giving me 12 Hz, it's giving me almost 1 Hz...

Any clues ?
Thanks

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

Good morning. Div8 fuse? Again, you have the means at your disposal to measure and resolve this yourself. How many times have i suggested the simulator? You also have a logic analyser to give an accurate measurement.

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

Good morning,
The fuse, which one is Div8 ?
[img]http://i129.photobucket.com/albums/p231/picture_77/fusebit5_zpsf599f5ef....

Thanks

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

What did the simulator say?

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

on simulator I got :
[img]http://i129.photobucket.com/albums/p231/picture_77/simulator2_zpsf523bdc...

Timer setting 1:64,

TCCR1B = (0<<CS12|1<<CS11|1<<CS10);
TIFR = (1<<TOV1); //Clear pending TOV1 interrupt
OCR1A = 15625;
MCUCR = 0x00;
EICRA = 0x00; //extended ext ints
EIMSK = 0x00;
TIMSK = 1<<OCIE1A;

inside main :

SegDataPort = DigitTo7SegEncoder(seconds%10,0);
SegCntrlPort = ~0x20; //~0x0010 0000 = 0x1101 1111 --> 0x1111 1110
//SegCntrlPort = 0xFD;
_delay_ms(3);
SegDataPort = DigitTo7SegEncoder(seconds/10,0);
SegCntrlPort = ~0x10;
_delay_ms(3);
SegDataPort = DigitTo7SegEncoder(minutes%10,0);
SegCntrlPort = ~0x08;
_delay_ms(3);
SegDataPort = DigitTo7SegEncoder(minutes/10,0);
SegCntrlPort = ~0x04;
_delay_ms(3);
SegDataPort = DigitTo7SegEncoder(hours%10,0);
SegCntrlPort = ~0x02;
_delay_ms(3);
SegDataPort = DigitTo7SegEncoder(hours/10,0);
SegCntrlPort = ~0x01;
_delay_ms(3);

on ISR :

ISR(TIMER1_COMPA_vect)
{
seconds++;

if(seconds == 60)
{
seconds = 0;
minutes++;
}
if(minutes == 60)
{
minutes = 0;
hours++;
}
if(hours > 23)
hours = 0;
}

Any ideas ? thank you

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

it takes a long time to simulate 1 second and 1:1024,
I'm still waiting for the result now,
I guess it will be 1000,0000 uS, which is 1s but in the PCB it's not 1s.....?

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

1 : 1024 simulator result :
[img]http://i129.photobucket.com/albums/p231/picture_77/simulator3_zps4f32ae0...

I have uploaded to the board and it's not exactly 1Hz....I don't understand why ?

Any comments ?
thanks

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

Do you mean XDIV - XTAL Divide Control Register, page 38 Atmega128A data sheet ?

Thanks for the clue mate

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

XDIV = (1<<XDIVEN|1<<XDIV0|1<<XDIV1|1<<XDIV2|1<<XDIV3|1<<XDIV4|1<<XDIV5|1<<XDIV6);

?

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

Quote:

page 38 Atmega128A data sheet ?


Quote:

1) Telling us which AVR model is involved.
2) Telling us the clock speed of said AVR.
3) Telling us how you verified that the AVR is indeed running at said speed.
4) Telling us what you expect to happen.
5) Telling us what >>does<< happen.
6) Telling us how you are testing.
7) Posting a >>complete<< test program.

After much back-and-forth, you have indirectly answered the first two questions. You haven't answered the third.

As I said, there was a >>reason<< I posted that series of questions. And in that order. But you choose to just not answer, and proceed to another episode of hand-wringing. Why?

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

Some MCUs have DIV8 fuse and some have a software controlled MCU clock divider control register. Some may have both. Until a post or two back, you did not specify Mega128. That is why detailed information is requested. Few of us posses crystal balls that work.

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

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

1) Telling us which AVR model is involved.
ATMEGA128

2) Telling us the clock speed of said AVR.
16MHz

3) Telling us how you verified that the AVR is indeed running at said speed.
I have no idea, I tried with simulator and giving me the exact value I want, as I posted above

4) Telling us what you expect to happen.
I get 1 Hz interrupt to increase second variable

5) Telling us what >>does<< happen.
I get less than 1 Hz if I follow the calculation from datasheet with 1:1024 scaler

6) Telling us how you are testing.
I test it with simulator and compare it with the real PCB

7) Posting a >>complete<< test program.

void init_devices(void)
{

//DDRB = 0xFC;
//DDRD = 0xFF; //port 0,1,2 & 3 as outputs ,port 5 as input 1111 1011
//DDRA = 0xFF;

SegDataDDR = 0xFF;
SegCntrlDDR = 0x3F;
SegCntrlPort = 0xFF;
XDIV = 0<<XDIVEN;
cli(); //disable all interrupts

TCCR1B = (1<<CS12|0<<CS11|0<<CS10);
TIFR = (1<<TOV1); //Clear pending TOV1 interrupt
//OCR1A = 15625;
OCR1A = 1;
MCUCR = 0x00;
EICRA = 0x00; //extended ext ints
EIMSK = 0x00;
TIMSK = 1<<OCIE1A;

sei(); //re-enable interrupts
}

int main(void)

{
init_devices();

while(1)
{

//TODO:: Please write your application code
//test_segment();
/* Set Minutes when SegCntrl Pin 6 Switch is Pressed*/

if((SegCntrlPin & 0x40) == 0 )
{
_delay_ms(200);
if(minutes < 59)
minutes++;
else
minutes = 0;
}
/* Set Hours when SegCntrl Pin 7 Switch is Pressed*/

if((SegCntrlPin & 0x80) == 0 )
{
_delay_ms(200);
if(hours < 23)
hours++;
else
hours = 0;
}

SegDataPort = DigitTo7SegEncoder(seconds%10,0);
SegCntrlPort = ~0x20; //~0x0010 0000 = 0x1101 1111 --> 0x1111 1110
//SegCntrlPort = 0xFD;
_delay_ms(3);
SegDataPort = DigitTo7SegEncoder(seconds/10,0);
SegCntrlPort = ~0x10;
_delay_ms(3);
SegDataPort = DigitTo7SegEncoder(minutes%10,0);
SegCntrlPort = ~0x08;
_delay_ms(3);
SegDataPort = DigitTo7SegEncoder(minutes/10,0);
SegCntrlPort = ~0x04;
_delay_ms(3);
SegDataPort = DigitTo7SegEncoder(hours%10,0);
SegCntrlPort = ~0x02;
_delay_ms(3);
SegDataPort = DigitTo7SegEncoder(hours/10,0);
SegCntrlPort = ~0x01;
_delay_ms(3);

}

}

/*Timer Counter 1 Compare Match A Interrupt Service Routine/Interrupt Handler*/
//ISR(TIMER0_COMP_vect)
ISR(TIMER1_COMPA_vect)
{
seconds++;

if(seconds == 60)
{
seconds = 0;
minutes++;
}
if(minutes == 60)
{
minutes = 0;
hours++;
}
if(hours > 23)
hours = 0;
}

The code above with 1:256 and it's giving me almost 1Hz, I think it's slower, because I set exactly the same with PC time, now it's 2 minutes slower already....
I didn't do any calculation, just put a guess, since the calculation is not right, I don't know how to set the correct clock source ??

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

bianchi77 wrote:

How can I know, it's exactly 16MHz then ?

Toggle a pin in a tight SW loop, and measure that frequency.
That confirms actual SysCLK.
You do have a 16.000MHz crystal ?

bianchi77 wrote:

I don't know why, the code I used now (almost 1Hz)

'almost' can give you a clue, just how far off 1.00s is it ? (and how stable is that value ? )

I think this can measure to 1.0000Hz, (depends in your sound card), but can certainly measure > 20Hz.

http://www.daqarta.com/

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

if I used blink LED 1 second with _delay_ms(1000), it's giving me the right 1 s....

Is it right to verify the crystal with this method ? thanks

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

The led should be one second on and one second off. If this is the case, you have proven the cpu is working at the expected frequency. The simulation seems to suggest your code is also correct. How about the M103C fuse? I've been bitten by that a couple of times.

The way to debug is to pose a question then ask yourself how you can prove it. Working logically you will arrive at the result.

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

I verified with osciloscope for _delay_ms(3) ...
supposed to be 333.33 Hz on calculation,but in the circuit is 55.4 Hz,
So I think the clock is 1 : 6, 16MHz / 6....the actual clock I have in the circuit is 2.67 MHz,

Am I right ?

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

Quote:
How about the M103C fuse?

It's off, M103C value = 1

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

bianchi77 wrote:
I verified with osciloscope for _delay_ms(3) ...
supposed to be 333.33 Hz on calculation,but in the circuit is 55.4 Hz,
So I think the clock is 1 : 6, 16MHz / 6....the actual clock I have in the circuit is 2.67 MHz,

Am I right ?

You can say you have an expected : real deviation of 6.0168:1, (assuming you measured a half period, or 3.0084 if your 55.4 is the frequency). but you need to check into how _delay_ms is coded, and what sets the expected fSys value for that, to then decide what the 'real' fSys may be.

If you short the Crystal, does it stop the scope display ?

Last Edited: Mon. Jun 16, 2014 - 03:04 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you short the Crystal, does it stop the scope display ?

Yes it stops the scope display when I short the crystal...
any other causes ?

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

bianchi77 wrote:

If you short the Crystal, does it stop the scope display ?

Yes it stops the scope display when I short the crystal...
any other causes ?

Does the Scope confirm it as 16.00MHz Oscillation ?

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

The code looks like it is for Codevision - have you double checked the project settings for the frequency?

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

Quote:
The code above with 1:256 and it's giving me almost 1Hz,
My calculation is
freq = (16000000 / 256) / 65536 = 0.953 Hz

For exact 1 Hz you have to reload TCNT1 in the interrupt.
Reload value is 65536 - 62500.

Edit:¨
Not clear why you used COMPA interrupt in normal mode.
TIMER1_OVF does the same here. (and may be less confusing)

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

If you want 1Hz, you should use CTC mode. e.g.


TCCR1A = 0;
TCCR1B = (1<<WGM12)|(4<<CS10); //CTC, div256
OCR1A = (F_CPU/256/1) - 1; //=62499 blink @ 0.5Hz

or


TCCR1B = (1<<WGM12)|(5<<CS10); //CTC, div1024
OCR1A = (F_CPU/1024/1) - 1; //=15624 blink @ 0.5Hz

or for 1kHz square wave. remember you need 2 toggles per cycle.


TCCR1A = 0;
TCCR1B = (1<<WGM12)|(3<<CS10); //CTC, div64
OCR1A = (F_CPU/64/1000/2) - 1; //=124 blink @ 1kHz

The rules are quite simple for both the Compiler and Simulator.
Be honest about the actual value of the clock/crystal in F_CPU.

You can measure the actual frequency by creating a 1Hz blink and counting 100 blinks with your wristwatch. i.e. you don't need a scope or high tech equipment.

I don't understand visovian's reply. It is never wise to reset TCNT1 in an interrupt.

Regarding your 1001040us from the Simulator.
You are probably counting the C startup code.
You should reset the cycle counter at the first hit at the breakpoint. Then run to the breakpoint again.

David.

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

Kartman wrote:
The code looks like it is for Codevision - have you double checked the project settings for the frequency?

I use Atmel Studio 6, where can I find project settings for the frequency ? thanks

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

You've got the help file.

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

Thanks David, so far, I use :

 TCCR1B = (1<<WGM12)|(5<<CS10); //CTC, div1024
OCR1A = (F_CPU/1024/1) - 1; //=15624 blink @ 0.5Hz

and compare it with PC clock,
it's match....

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

Kartman wrote:
You've got the help file.

Ok, thanks for the clue...

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

I've found it, the speed is 0, how can I change it ?
[img]http://i129.photobucket.com/albums/p231/picture_77/speedatmega128_zps299...

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

You've got the help file - it worked last time! Or would you like me to Google the answer for you whilst i'm on the train?

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

Is it, toolchain --> AVR /GNU C Compiler --> Symbol --> add F_CPU = 16000000 ?

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

I'm testing it now, have a nice ride...

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

That 0 is a red herring. All devices show "speed: 0" there. I assume Atmel had planned to show "0..16MHz" for example (and then "0..20MHz" for mega168 etc) but this is just something Atmel put in to mislead people.

The ONLY way to find out what speed a CPU is running at is to measure it. Modern AVRs have a fuse called CLKOUT and a pin called CLKO. You set the fuse and then the pin can be measured with a scope/freq-meter/LA to find out the real speed. You have chosen to use an ancient AVR so it does not have this facility. In this case the way you measure it is:

(a) just toggle a pin with the fastest loop possible. Count the cycles in the loop then measure the freq on a scop/meter/LA and work backwards to the CPU freq.

(b) make an assumption about the CPU speed, program a pin to toggle with delay based on this assumption. Measure the output on the toggling pin (usually an LED). If it toggles at the predicted rate your guess about CPU freq is proved correct. If not you can work out from the difference how far out your guess was.

(c) carefully (with a 10X probe) scope the XTAL2 pin if a crystal is being used. This is a poor-man's equivalent of the CLKOUT/CLKO facility on modern AVR

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

No. You've just found a fact box for the AVR model in question.

There are in fact several settings you need to make to simulate a certain CPU ferequency correctly:

1) The F_CPU symbol that needs to be seen in the code. You can either make this in code:

#define F_CPU 16000000UL

(be sure to place it at a point where it is seen before any #include <util/delay.h> )
Or you can use the project properties (yes, the project Properties). Cant recall under which tab, but there you can add a command line define

F_CPU=16000000UL

Any of these will make sure the ode generated by the compiler takes the CPU frequency into account. E.g. it will generate the correct number of loop-runs for _delay_ms()/_delay_us() to have correct timings.

2) Next, you also need to tell the Simulator the CPU frequency it should assume when running. You will find it in the Processor view, while the simulator is running. You simply click in that field and edit it, and the simulator will use the number you put in. It will be used for the running time calculations displayed in the same view.

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

Quote:
2) Next, you also need to tell the Simulator the CPU frequency it should assume when running. You will find it in the Processor view, while the simulator is running. You simply click in that field and edit it, and the simulator will use the number you put in. It will be used for the running time calculations displayed in the same view.

The CPU is 16MHz , I saw it at the simulator....

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

bianchi77 wrote:
Thanks David, so far, I use :

 TCCR1B = (1<<WGM12)|(5<<CS10); //CTC, div1024
   OCR1A = (F_CPU/1024/1) - 1;    //=15624 blink @ 0.5Hz 

and compare it with PC clock,
it's match....

So this is now all working 'as expected' ?

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

It's working but I don't understand why is it 5<<CS10, not 1<<CS10 ?

Thanks

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

does it mean ,
TCCR1B = (1<<WGM12)|(5<<CS10); equal to
TCCR1B = (1<<WGM12)|(1<<CS12)|(0<<CS11)|(1<<CS10);

?

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

A couple of minutes with the simulator will answer your question.

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

I got it from the simulator, it's the same,
thanks Kartman...
[img]http://i129.photobucket.com/albums/p231/picture_77/1second_zpsbd49d353.j...

Pages