REAL ONE SECOND by timer 0---->problem in my code

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

 

hi dears.

i try to write a code in atmel studio to make a real one second. actually i want to toggle one pin in each second.

i use atmega16 and 2MHz frequency. i want to divide by 64 prescaler. by formulas i calculate that timer should 122 time overflow and 18 clock to reach 1 second. 

i decide to use overflow ISR and ctc mode. that mean i have a variable named overflow, i count overflowes and then compare OCR. i dont know if this is true or not.

my code is below but dont work truely. where is my fault.?

#define F_CPU 2000000

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

volatile overflow;

void init_timer0(){
	TCCR0 |= (1 << WGM01)|(1 << CS00)|(1 << CS01);
	 TCNT0 = 0;
	 OCR0 = 18;
	TIMSK |=(1<<TOIE0);
	sei();
	overflow=0;
}

ISR (TIMER0_OVF_vect){
	overflow++;
}

void main(void)
{
	DDRB|=(1<<0);
	init_timer0();
	while (1)
	{
		if(overflow>=122){
			if(TIFR&(1<<OCF0)){
			PORTB ^=(1<<0);
			TCNT0=0;
			overflow=0;
		    TIFR|=(1<<OCF0);
			}
		}
	}

 

1000ms/8.192ms=122.07            0.07*255=18      122 overflow +  18clock

}

 

 

 

Aasshh

Last Edited: Fri. Sep 13, 2019 - 05:51 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

How are you getting the 2MHz clock? With an external 2 MHz crystal? Are the fuses set correctly?

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

What do you mean that it "doesn't work"?  What results are you observing?  How is that different than what you expected.

 

(remember that any timing exercise is only going to be as accurate as the clock source that you are starting with)

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 test and simulate it in porteouse only. i cant get the result. it blink so fast. my answer is about coding. is my code and method right ? i count overflows then compare OCR or not? this code above doesnt work well. it blink fast-what is problem?

Aasshh

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

Unless your hardware clock's frequency is 2MHz, your

#define F_CPU 2000000

will mean NOTHING!

 

Answer the 3 questions in post #2.

Ross McKenzie ValuSoft Melbourne Australia

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

I only want to test first in porteous not in real board. I didnt program my avr yet and dont need to set feousbit. Only i want to see result in porteous. I have a atmega16 micro and connect a led to it simply. And set in micro 2MHz internal f_cpu.i click on micro on porteous and set 2MHz for it. and run my code exe file. And see led blinking fast. Not in one second. I only want to find that my code is true or not

Aasshh

Last Edited: Sat. Sep 14, 2019 - 05:59 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm quite sure you can spell 'Proteus' - it's on the screen of the software. Proteus has simulated instruments - why not use these to test your code? Like the oscilloscope. You can toggle a port pin in the ovf isr and measure with the virtual oscilloscope. What does this tell you? Narrow down the problem using the tools you have at hand. I'm sure your teacher will be impressed when you explain your techniques for debugging. In in a few minutes, with a bit of effort, you will have narrowed down the problem and be well on your way to solving it.

 

For us native speakers of ye olde english, 'Hi dears' doesn't really work well. Just sayin'. Maybe "Hi all" might be a better way to begin a conversation.

Last Edited: Sat. Sep 14, 2019 - 07:37 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have a question. Clear question. Is my method true or false? Can i code to this porpose ? Timer is 8 bit and the count is bigger than 255. I want to first count overflows and if reached 122 then check and compare ocr=28 with tcnt0.

Aasshh

Last Edited: Sat. Sep 14, 2019 - 07:55 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

false. You've enabled CTC mode - the timer is going to hit 18, then go back to 0.

 

 

My calcs say 2000000/64/19/122 = 13.4Hz. Does this match what you observe? You could've told us what you measured also you could've used the techniques to mentioned to measure the actual interrupt rate. This would've lead you to a solution.

 

 

I'd suggest you set the timer up in CTC mode to give a useful tick time - say 1ms or maybe 10ms. Count them.

My calcs suggest /8 prescale and OCR0 = 249 will give 1ms ticks. Count 1000 of them.

Or /256 prescale and OCR0 of 77. Every 8th tick, set OCR0 to 76. This gives 10ms. Count 100 of them.

 

 

Last Edited: Sat. Sep 14, 2019 - 09:36 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Aashkanpasha wrote:
Is my method true or false ?

false

 

In CTC mode, your Overflow ISR should not have run at all, so I don't understand how your if(overflow>=122) ever became true. The LED toggle should not be happening.

 

Perhaps this is a bug in porteous and you should be using Proteus instead smiley

 

Last Edited: Sat. Sep 14, 2019 - 10:15 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


This is my calculation to fine timercount for f_cpu=2000000 and presclare=64

 

                                   

 

 

Timer0 is 8 bit register so can count maximum to 255. So: 

 

It mean that, 122 times should TCNT0 overflows and  then in 123 only count till 137 of 255(0.54*255).

So I should code something that count 122 time overflow and then compare TCNT0 with OCR=137.

In below code where is wrong?

 

void init_timer0(){       //this line define a function to initialize timer0
	TCCR0 |= (1 << WGM01)|(1 << CS00)|(1 << CS01);
	 TCNT0 = 0;
	 OCR0 = 137;
	TIMSK |=(1<<TOIE0);
	sei();
	overflow=0;
}

----------------------------------------------------------------------------- 
ISR (TIMER0_OVF_vect){
	overflow++;     //if overflow occure,add one unit to  overflow variable
}
-----------------------------------------------------------------------------

void main(void)
{
	DDRB|=(1<<0);
	init_timer0();
	while (1)
	{
		if(overflow>=122){
			if(TIFR&(1<<OCF0)){  //check if in 123 time of flowing TCNT=OCR
			PORTB ^=(1<<0);
			TCNT0=0;
			overflow=0;
		    TIFR|=(1<<OCF0);
			}
		}
	}

 

Aasshh

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

Your mathematics looks like nonsense.

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

Hint.   Write a 1ms CTC timer.   Count 1000 interrupts in ISR(TIMER0_COMP) i.e. 1000 x 1ms

 

You can do different maths.  e.g. 250 x 4ms or 200 x 5ms or 100 x 10ms.

 

Some of these CTC times are easier than others.

Yes,  you can use a non-CTC timer and count n OVF interrupts.   Then do a COMP interrupt for the last time interval.   (hard)

 

Seriously.   I am sure that your University gives the same assignment to its students every year.

You could use your Google skills to see a previous year's winning student solution.

 

I always advise printing the datasheet page for CTC mode in Timer0.    You only need one sheet of paper. 

Then sitting down with a nice cup of tea,  pencil and paper.

 

David.

 

p.s.   this assignment is simple.   but if it develops your Google skills this will be helpful for all future projects.

Last Edited: Sat. Sep 14, 2019 - 02:40 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I suggest that you use the timer that makes it easy to do what you want.  That's the 16-bit timer1.  Set the pre-scaler to 64 and the 16-bit count register to 34285 (65535-31250).  {0xffff is the roll-over value and triggers an overflow interrupt:  31250 is 2MHz/64prescaler Turn on the timer and it will overflow one a second when its 2's complement is loaded into the timer1 count register.}

  

Don't do all this nonsense with counting overflows of an 8-bit timer.

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

You have an answer. A clear answer. The timer won’t overflow as you have enabled CTC mode. When the timer value matches the OCR0 value, the hardware resets the timer to 0. Therefore you get divide by OCR0+1.
There’s at least four specific defects in your code.

Understand that programming and computers is complex. It is very difficult to get everything correct at first. Therefore you need to ‘debug’ - this is a very specific skill you need to learn.
Had you followed the hints i gave you, you could observe the output of the timer. Based on the observations you could better understand what the timer is doing and fix your code - without having to ask on a forum. In a time frame of minutes instead of hours.

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

Thanks. Your answers are so helpul Thank you.
I learn more from your guides.
I didnt know that in ctc mode i can not count overflowes till you said. Thanks.
My project is to write a code that want me me to:
If we have a avr that a led is connedted to it. And f_cpu is 2000000Hz. By 256 presclare how we can make real 2000ms? By CTC mode. The code we should write is in below model:

Void init_timer0(){
TCCR0=????
TXNT0=????
.....
}

ISR(????){
?????
}

Void main(){
Init_timer0();
?????
While(1){
????
}

Please help me to see register values snd calculations. Thank you

Aasshh

Last Edited: Mon. Sep 16, 2019 - 11:59 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

15625 ;-)

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

I calculated and reached this count15625 .but how can value registers in ctc mode

Aasshh

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

Well in CTC mode note that there is always an "off by one" thing going on so the number you actually use would be 15624 (because 0 itself is "one count").

 

Anyway it's all pretty clear isn't it? You set the CS bits to set up the /256 prescaler you have been told to use. You set the WGM bits to select CTC mode. You set the interrupt enable bits to enable the compare match interrupt, you set the output compare register to set the upper limit for the counting (15624) and you provide a compare match interrupt vector. That vector will then be hit every 2000ms if you set everything else right. You can either have that ISR() code itself do whatever the real "output" is - like flashing an LED or whatever. Or you may choose to just have the interrupt set some kind of volatile flag variable then in the main() program loop you have code waiting to see a change of the flag then actioning whatever output is required. If the action is trivial put it in the ISR, if it is a "long procedure" then just do it with a flag.

Last Edited: Mon. Sep 16, 2019 - 01:57 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

2MHz / 256 means each timer tick is 128us.    15625 ticks for 2 seconds.

 

You just need to see how many different ways you can get 15625 with an 8-bit timer e.g.

1 x 15625

5 x 3125

25 x 625

125 x 125

 

So you can create a 25 CTC timer and count 625 TIMER0_COMP interrupts.

 

Seriously.    You should be able to work this out for yourself.

And students would spend less time on their assignments by "thinking" instead of wasting time on Forums.

 

We will not do your homework for you.    But we have given you lots of hints.

 

David. 

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

David, his brief included the use of /256 so I'm not sure he gets a lot of choice about the numbers.

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

I gave him ALL the possible numbers.

 

He has wasted three days on this assignment.

 

He just has to print out the Clear Timer on Compare Match (CTC) Mode paragraph from the 8-bit Timer/Counter0 with PWM chapter of the datasheet.

Then sit down with a nice cup of tea.

 

Yes,   of course he has to read it several times.    But this would be a lot "quicker" than writing messages on the Forum.

And most importantly he would understand the solution.

 

If you look carefully at the numbers,  you would see that 2 seconds is possible with div256.   But 1 second would not work with div256.

Other prescaler values are available for the 1 second problem e.g. div1, div8, div64, ...

 

The OP has Proteus.    I presume he has AS7.0 or AS4.18 Simulators too.

Even if he chooses CTC values by guesswork,  a Simulator will give the exact timing.

 

Learning how to use a Simulator is just as important as learning how to read a datasheet.

It will enable you to solve AVR problems with peripherals e.g. Timer, ADC, EEPROM, ...

 

David.

Last Edited: Mon. Sep 16, 2019 - 03:22 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you both men.
Thanks alot.
Sorry you are right. I cant considrate well on mather. Soory. I had a heart surgery last month and i have a little money problem and alot if pain. These couse i cant considrate. Sorry. Thank you alot

Aasshh

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

Aashkanpasha wrote:
I calculated and reached this count15625 .but how can value registers in ctc mode

I can't believe you have asked this question after you nearly got there in post #1. You seem to have gone backwards.

 

Although in #1 you stated different requirements, that matters not; your original code needs only trivial mods to work correctly. I struggle to believe that having written the code in #1 and given all the help you've already received.here; you can't make the simple leap to working code and successfully completing your assignment.

 

Hint:

Both your original requirements and this 2s interval can be done using CTC mode ONLY.

You need not consider the ISR(TIMER0_OVF_vect) only ISR(TIMER0_COMP_vect) needs implementing.

 

PS

WTF: I Just checked the spelling of that TIMER0_COMP_vect vector, and it doesn't exist on mega16(a).

You'll have to use a different timer and of course read the datasheet again.

 

Last Edited: Mon. Sep 16, 2019 - 08:41 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

On my PC the Pack directories show:

.\ATmega_DFP\1.0.91\include\avr\iom16.h:#define TIMER0_COMP_vect_num    19
.\ATmega_DFP\1.0.91\include\avr\iom16.h:#define TIMER0_COMP_vect                _VECTOR(19)
.\ATmega_DFP\1.1.130\include\avr\iom16.h:#define TIMER0_COMP_vect_num   19
.\ATmega_DFP\1.1.130\include\avr\iom16.h:#define TIMER0_COMP_vect               _VECTOR(19)
.\ATmega_DFP\1.2.203\include\avr\iom16.h:#define TIMER0_COMP_vect_num   19
.\ATmega_DFP\1.2.203\include\avr\iom16.h:#define TIMER0_COMP_vect               _VECTOR(19)
.\ATmega_DFP\1.2.209\include\avr\iom16.h:#define TIMER0_COMP_vect_num   19
.\ATmega_DFP\1.2.209\include\avr\iom16.h:#define TIMER0_COMP_vect               _VECTOR(19)
.\ATmega_DFP\1.3.300\include\avr\iom16.h:#define TIMER0_COMP_vect_num   19
.\ATmega_DFP\1.3.300\include\avr\iom16.h:#define TIMER0_COMP_vect               _VECTOR(19)
.\ATmega_DFP\1.0.91\include\avr\iom16a.h:#define TIMER0_COMP_vect_num  19
.\ATmega_DFP\1.0.91\include\avr\iom16a.h:#define TIMER0_COMP_vect      _VECTOR(19)  /* Timer/Counter0 Compare Match */
.\ATmega_DFP\1.1.130\include\avr\iom16a.h:#define TIMER0_COMP_vect_num  19
.\ATmega_DFP\1.1.130\include\avr\iom16a.h:#define TIMER0_COMP_vect      _VECTOR(19)  /* Timer/Counter0 Compare Match */
.\ATmega_DFP\1.2.203\include\avr\iom16a.h:#define TIMER0_COMP_vect_num  19
.\ATmega_DFP\1.2.203\include\avr\iom16a.h:#define TIMER0_COMP_vect      _VECTOR(19)  /* Timer/Counter0 Compare Match */
.\ATmega_DFP\1.2.209\include\avr\iom16a.h:#define TIMER0_COMP_vect_num  19
.\ATmega_DFP\1.2.209\include\avr\iom16a.h:#define TIMER0_COMP_vect      _VECTOR(19)  /* Timer/Counter0 Compare Match */
.\ATmega_DFP\1.3.300\include\avr\iom16a.h:#define TIMER0_COMP_vect_num  19
.\ATmega_DFP\1.3.300\include\avr\iom16a.h:#define TIMER0_COMP_vect      _VECTOR(19)  /* Timer/Counter0 Compare Match */

Yes,  it is possible that your GCC "iom16.h" file has a different spelling.

 

@Aashcanpasha,

 

I am sorry to hear about your health problems.    Especially if you are a young student.

 

David.

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


Ahh - My mistake was to assume the TIMER vectors were grouped sensibly together as they are on the more familiar (to me) mega328 family.

 

 

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

I have seldom worried about the actual vector number.

In practice,  you just need to get the spelling right.

 

If your project has "priority" issues,  the typical critical vectors are INT0 and INT1.   Followed by Timer vectors.    It does look as if TIMER0_COMP was a bit of an afterthought.  Likewise INT2.

 

David.

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


I DO WHAT you said me.

by       F_CPU=2000000         presclare=64      timer2    for 1 second blinking     i calculated:

 

                                 

31249=250*125

is these calculations wright?

 

i write this code. but led blink in 8 second not 1 second. why?

#include <avr/interrupt.h>

volatile compare=0;

void init_timer2(){
	TCCR2 |=(1<<CS22)|(WGM21<<1);    //CTC mode rnable and presclare is 64
	TCNT2=0;
	OCR2 = 250;                                  //compare value
	TIMSK |=(1<<OCIE2);
	sei();
	compare=0;
}


ISR (TIMER2_COMP_vect){
	compare++;			                 // Increase The Number Of compare
}


void main(void)
{
	DDRB|=(1<<0);
	init_timer2();
	while (1)
	{
		if(compare==125){
			PORTB ^=(1<<0);		       // Toggle LED
			TCNT2=0;				// Reset Timer/Counter2 Variable
			compare=0;				// Reset compare Counter
		}
	}	
}

 

but in timer1 i write a code it worked wrigh  and no problem. so why is my code wrong in timer2 above:

#define F_CPU 2000000

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

volatile overflow;

void init_timer1(){
	TCCR1A |= 0x00;
	TCCR1B|= (1 << WGM12)|(1 << CS10)|(1 << CS11);    //timer1         
	 TCNT1 = 0;                                                 
	 OCR1A = 31249;
	TIMSK|=(1<<OCIE1A) ;                          
	sei();
}

ISR(TIMER1_COMPA_vect){
	PORTB ^=(1<<0);
}

void main(void)
{
	DDRB|=(1<<0);
	init_timer1();
	while (1)
	{
	}
}

 

Aasshh

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

"volatile" is not a type. Your variables need a type as well.

 

As for the difference in timer 2 versus timer 1, I thought you were using Proteus. It's a simulator/debugger. Surely it can show you what is different?

 

(having said that I checked your maths and most of your bit setting and I can't immediately see why it would not work - I expect that it would)

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

in timer 2 led blinking. but not in 1 second in 4 second. i send you timer 1 code too. it works well. but in timer 2 it doesnt work properly- i calculated for 1 second but it blink in 4 second- i check all thing and all calculations- i test my code in proteus.   what should i do?

Aasshh

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

First off.   You should correct any spelling mistakes and format the code nicely.

 

I ran both of your programs in the AS7.0 Simulator.

 

Timer1 toggled at  999,989.50 µs

Timer2 toggled at 4,095,359.50 µs

 

Study the datasheet and you will see why.

 

David.

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

Yes your test is true. And mattch with my simulation in proteus. Do You find why my code is wrong?which line is wrong?

Aasshh

Last Edited: Tue. Sep 17, 2019 - 06:03 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hint. Format your code nicely. It will make your tea taste better.
Look at the WGM bits in the Simulator. Compare with the datasheet.
.
Then think about how long it took you to format the code so that it was nice to read.
And compare with the 4 days spent on the project.
.
David.

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

O my god.
You are gentleman that didnt call me stupid. Or crazy. You answer me with calmness.thank you. I find my craziness.

Aasshh

Last Edited: Tue. Sep 17, 2019 - 07:13 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Now it is time to tell me a brief about As7.0 simulator. What is it? Is it a Independent software? AS 7 is atmel studio7? How you calculate or simulate and see 1se=999.9898us?

Aasshh

Last Edited: Tue. Sep 17, 2019 - 07:39 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Google atmel studio simulator
One of the first hits is a video from microchip.

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

Aashkanpasha wrote:

 

hi dears.

i try to write a code in atmel studio to make a real one second. actually i want to toggle one pin in each second.

i use atmega16 and 2MHz frequency. i want to divide by 64 prescaler. by formulas i calculate that timer should 122 time overflow and 18 clock to reach 1 second. 

i decide to use overflow ISR and ctc mode. that mean i have a variable named overflow, i count overflowes and then compare OCR. i dont know if this is true or not.

my code is below but dont work truely. where is my fault.?

#define F_CPU 2000000

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

volatile overflow;

void init_timer0(){
	TCCR0 |= (1 << WGM01)|(1 << CS00)|(1 << CS01);
	 TCNT0 = 0;
	 OCR0 = 18;
	TIMSK |=(1<<TOIE0);
	sei();
	overflow=0;
}

ISR (TIMER0_OVF_vect){
	overflow++;
}

void main(void)
{
	DDRB|=(1<<0);
	init_timer0();
	while (1)
	{
		if(overflow>=122){
			if(TIFR&(1<<OCF0)){
			PORTB ^=(1<<0);
			TCNT0=0;
			overflow=0;
		    TIFR|=(1<<OCF0);
			}
		}
	}

 

1000ms/8.192ms=122.07            0.07*255=18      122 overflow +  18clock

}

 

 

 

 

Hi Aashkanpasha,
are you sure the Waveform generation bit you used?
  

(1 << WGM01)

Am I wrong or have you set a PWM, 9bit Phase Correct?

The TOP is 0x1FF and not 0xFF

 

Regards

 

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

Thank you for your answers.
BUT can you give me a brief explaination how you simulate and debug in AS7 .how you finded real time that reach by my code?by simulator or debuge?? I mean how you finded 999.898 us for my code.

 

i choose simulator in atmel tools and press alt+f5 to dibug. but i dont know how can i fine my simulation result to compare with real 1 second.can u guid me?

Aasshh

Last Edited: Wed. Sep 18, 2019 - 09:27 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am sure that there are Tutorials and videos on using the "AS7.0 Simulator"

 

You view the CPU frequency,  cycles, time elapsed,  ... from Debug->Windows->Processor Status

 

Cycles are always correct.

Edit the Frequency.  You get accurate Stop Watch.

 

You can edit any of the values.  e.g. change Z register,  reset Cycles, ...

 

I am sure that Proteus Simulator will do all of these things.

I do not own a Proteus licence.

 

I strongly recommend that you learn one IDE at a time.

i.e.  learn everything about Proteus before you try AS7.0

 

We can help you with AS7.0

Not many Forum members own Proteus.    (ask Proteus questions on Proteus website)

 

David.

Last Edited: Wed. Sep 18, 2019 - 09:37 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


Aashkanpasha wrote:
n you give me a brief explaination how you simulate and debug in AS7 .
If you have created a mega16 project in AS7 your screen probably looks like this:

 

 

The picture of the hammer just says "None on" because no debugging device has been selected yet. So click on that and you get to:

 

 

The only important thing here is that droplist beneath "Select debugger". Click that to drop the list and show available selections:

 

 

If I had some kind of Atmel debugger plugged into a USB port on my PC then that/they would also be listed there. But I don't so the only really usable option here is "Simulator" so simply click to select this. You can see it has been selected here:

 

 

as that always shows you what the active debugger is (could be something like Atmel-ICE or JTAGICE3 or something if you had one of those). For the next bit I need a program to simulate/debug so I went with this:

 

 

I could now use Build-Build <project name> (or Solution) from:

 

 

to build the code. But that fact is that if I tell AS7 to debug it (which in this case means "run it in the simulator" - because that's what I have selected) it's going to build the code first each time anyway. So I can just use:

 

 

(or press Alt-F5 as it suggests) but personally I think it's quicker to select this from the toolbar:

 

 

When I click that (or select the menu entry or press Alt-F5) then I see it very quickly build the code then the screen switches (in my case) to look like:

 

 

The key thing here is that yellow arrow on line 4. That shows where the code is about to execute. It has run a bit of the program so far and entered main() then stopped at the very first statement in main() (this is why the menu entry is called "Start debugging and break"). So now I am running the code - but only in a simulator - not a real AVR. The next thing to note are these buttons:

 

 

The downwards pointing arrow means "run one statement then stop again" - that is "step into". The middle one means "step over" and also runs one statement at a time but if the statement is the invocation of a function it does not step into it but steps over the execution of the entire thing (that is calls it, runs it then stops when control returns). The last one is "step out" - that's for when you have stepped into a function call but you just want it to continue until it gets back to the place the function was called from.

 

So if I just make one step with "step into" then it will execute one statement (the DDRB= line) and the situation will be this:

 

 

I deliberately set the selection in the "IO" view to be "PORTB" so I could see the DDRB/PINB/PORTB registers associated with port B. Because I just did a "DDRB = 0xFF" statement the IO view has changed to show that DDRB has a new value (red means "just updated") so that shows that DDRB now contains 0xFF. The yellow arrow is now on the next statement that will execute - the "PORTB ^= 0xFF" line. So when I let that execute I expect to see an update to "PORTB". So if I make one more "step into" this happens:

 

 

So the previous DDRB change has now gone grey (because it's no longer "just changed") but the things in red show that not only did the statement change PORTB (it set it to 0xFF) but the simulated PINB reads back as the current state of PORTB so that is all red (0xFF) too. If I step again:

 

 

now al of PORTB (and PINB) are back to 0x00 and so it will go on from here - the program is infinite simply toggling the state of all the PORTB bits every time (that's what the ^= 0xFF operation does).

 

When I look at "Processor Status" I see:

 

 

This keeps count of the number of cycles executed so if I step to allow it to go round the while(1) loop and do one more "PORTB ^= 0xFF;" then this updates to:

 

 

So it's moved on by 4 cycles (also red bits in the SREG status register show the S, N and Z flags have changed)

 

The "Frequency" field in this display is editable. You can change it to whatever speed your real AVR runs at (perhaps 8MHz or 16MHz?) and when you do the "stop watch" updates to show the real world time that would have been taken for the number of cycles executed. At any time you can right click on the "cycle counter" field and reset that counter.

 

 

So by resetting it, then running some instructions (perhaps running to a breakpoint?) then you can see how many cycles (and also what time) a certain sequence takes.

 

To set a breakpoint really needs a slight more complicated program to play with so stop debugging this current program with:

 

 

and you will return to edit/compile mode. Then you can change the code:

 

 

That is your own code (with a few fixes) and I have clicked in the grey area to the left of line 18 so the red "blob" shows I have placed a breakpoint in the ISR(). As I've just started to debug/simulate this it has run to the start of main() and so far it has executed 27 cycles. If I just use:

 

 

that tells it to just "continue to run" and it will do so until it hits the breakpoint in the ISR()...

 

(this takes a very very very long time as the simulator runs much much slower than a real AVR - to help it on it's way I may changes the CS00|CS01 bits to reduce the prescaler):

 

And this is where the simulator shows it's worrth as (by stopping it from time to time) I can see that it never hits the overflow interrupt - I see TCNT0 reset and yet it never overflowed. So then I studied the code and the datasheet and find that you have set it into CTC mode which means it will count up to the OCR0 value and then reset. So this really needs a compare match interrupt, not an overflow interrupt. So...

 

 

The yellow bits in the margin on lines 12 and 17 show that I have edited these lines to change the interrupt to be OCIE0 and TIMER0_COMP_vect. So now...

 

 

It first hits the interrupt after 73 cycles which at 2MHz equates to 36.5us after it started. If I now let it run again:

 

 

so it has just moved on from 73 to 108 cycles between interrupts (remember I reduced the /64 prescaler though!). If I click in the current breakpoint it will be removed and instead I can put one on line 28 inside the code that chacks for overflow>= 122 then I see this after letting it run again:

 

 

So in total it took 4548 cycles to get into that conditional code - not sure why you have the check for OCF0 in TIFR there but anyway.

 

If I restore the /64 prescaler and restart:

 

 

There's now a noticeable delay for it to get there but after 74,196 microsecond (74.2ms) from power on it has hit the conditional code for the first time. If I let it run again then it just sticks at the OCF0 test. So with that removed:

 

 

While I could try and work out the difference between 148,375us and 74,196us it's perhaps easier to reset the cycle counter and switch the display from us to ms then let it run again:

 

 

So one cycle of this is 74.18ms at 2MHz.

 

Anyway I think that gives you an idea of how to proceed...