global variable struggle

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

Hello all, 

I have been struggling with my code, resp. understanding, what is going on. 

My original task is to produce 40 kHz PWM signal on OC0A pin (Arduino Uno PIN6) for 1 second, than put the PIN6 off for 1 second and repeat this forever. I wrote code below BUT it does not work. In time, I was able to make it work by exchanging if(Count>80000){  for if(TCCR0B == 0x00){. Furthermore, I was able to find out, that problem is in the condition itself because variable Count in while loop keeps value 0 because condition if(Count==0){ works. I just do not understand WHY. Variable count is declared as global! Any explanation, link or hint is highly welcomed.  

#define F_CPU 16000000
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

unsigned long int Count = 0;

int main(void)
{
	DDRD = 0x40;	// set port D as all outputs
	PRR |= (0 << PRTIM0);	//enable timer T0
	TIMSK0 |= (1 << OCIE0A);    //Set the ISR COMPA vect
	sei();         //enable interrupts
	TCCR0A = 0x42;	// CTC, no prescaler, OCR0A = top
	TCCR0B = 0x01;	// no prescaler
	OCR0A = 200;	// 12.5 usec without prescaler
	while (1)
	{
	if(Count>80000){
//	if(TCCR0B == 0x00){
		_delay_ms(1000);
		Count = 0;
		TCCR0B = 0x01;
	}
	}
}

ISR (TIMER0_COMPA_vect)  // timer1 OCR1A interrupt
{
	if(Count>80000){	// 1 second with 80 kHz counting
		TCCR0B = 0x00;	// stop the timer
		TCNT0 = 0x00;	// clear T0
	}
	Count++;
}

 

Always learning (struggling)

Last Edited: Wed. Sep 11, 2019 - 02:56 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You’ve selected CTC mode, so why do you stop the timer and zero it? That’s what CTC does for you!

Declare count volatile.

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

Count is shared between ISR() and main(). It *must* be "volatile". Also, as a variable that is wider than 1 byte it must be atomically protected.

 

PS what is the granularity of your time base. Running a ticker at 80kHz with a period of 12.5us seems very unwise unless you really do need a granularity so fine. Most embedded systems would be happy with a "tick" at 10ms or around there which suggests a prescale in the /1024 region.

 

Otherwise your program is going to spend a large percentage of the CPu time simply servicing the ticker interrupt.

 

What's more, if you change the timebase you can probably reduce the width of "count" to just 16 bits - but that still needs atomic protection.

Last Edited: Wed. Sep 11, 2019 - 11:58 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

volatile ..... what a magical word ..... it works!

Thanks a lot to you both for your help!

 

Kartman wrote:
You’ve selected CTC mode, so why do you stop the timer and zero it? That’s what CTC does for you! Declare count volatile.

I stop the timer so it does not toggle OCOA pin anymore. TCNT0 zeroing makes sure, that there is no residual value left. So once timer starts again I get 40 kHz signal at very first cycle.

 

 

clawson wrote:
PS what is the granularity of your time base. Running a ticker at 80kHz with a period of 12.5us seems very unwise unless you really do need a granularity so fine. Most embedded systems would be happy with a "tick" at 10ms or around there which suggests a prescale in the /1024 region.

The 40kHz signal is going to feed ultrasonic sensor. 80 000 ticks is just arbitrary number to make it last for 1 second. In real application there will be just a few cycles. 1 byte variable will surely be enough.   

 

clawson wrote:
Also, as a variable that is wider than 1 byte it must be atomically protected.

I am afraid I do not understand what does "atomically protected" mean. Can you explain or forward me to some source of information? 

Always learning (struggling)

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

Sekel wrote:
Can you explain or forward me to some source of information? 
https://www.nongnu.org/avr-libc/user-manual/group__util__atomic.html

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

Sekel wrote:
volatile ..... what a magical word

It's not magic - it's standard 'C' !

 

Nothing specific to AVR or microcontrollers - it applies anywhere you have multiple "threads" of execution, or data that can get modified outside the compiler's visibility.

 

https://www.avrfreaks.net/commen...

 

 

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...