_delay_ms() problem

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

 

Hi !

 

I have an issue with _delay_ms().

 

ATmega324Pa  running on 8MHz  gcc

 

 

This code works ok.  I get 5 ms pulses on scope. 

 

#define F_CPU 8000000UL
#include "util/delay.h"

#include "config.h"
#include "string.h"


int main(void)
{	
	wdt_enable(1000);
	
	
	//TCNT1 = 0xD8EF;
	//TCCR1B = 0x01;							// timer start
	
	
	gpio_make_out(CONFIG);
	gpio_set(CONFIG);
	
	while(1)
        {
		wdt_reset();
		
		gpio_clr(CONFIG);
		_delay_ms(5);
		
		
		gpio_set(CONFIG);
		_delay_ms(5);
	
		
		//appTaskHandler();
		//appUartTaskHandler();
		
		//if( (TIFR1 & 0x01) == 0x01 )
		//{
		//	appTimerTaskHandler();
		//}
		
		
	    }
}

 

 

Problem is when I use _delay_ms(5)  in appTaskHandler i get pulse width 160ms

 

#define F_CPU 8000000UL
#include "util/delay.h"

#include "config.h"
#include "string.h"


int main(void)
{	
	wdt_enable(1000);
	
	
	//TCNT1 = 0xD8EF;
	//TCCR1B = 0x01;							// timer start
	
	
	gpio_make_out(CONFIG);
	gpio_set(CONFIG);
	
	while(1)
        {
		wdt_reset();
		
		//gpio_clr(CONFIG);
		//_delay_ms(5);
		
		
		//gpio_set(CONFIG);
		//_delay_ms(5);
	
		
		appTaskHandler();
		appUartTaskHandler();
		
		if( (TIFR1 & 0x01) == 0x01 )
		{
			appTimerTaskHandler();
		}
		
		
	}
}

 

 

appTahskHandler is in same file as main().

 

Does code size matters?

 

My main.c is  3500 lines.

 

 

Program Memory Usage     :    13750 bytes   42,0 % Full
Data Memory Usage           :    1759 bytes   85,9 % Full

 

 

Thank you !

 

 

Regards !

 

 

 

 

 

 

 

 

 

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

How do you check the length of the delay?

Perhaps a ISR or WDT reset change the thing you check

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

"apptaskHandler()" - sounds a LOT like an RTOS!

 

(if so then obviously soft loop delays aren't going to be predictable)

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

Hmm... If you don't post the code for apptaskHandler() how can we tell why delay doesn't work there?

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

 

Sweet Jesus guys !

 

I forgot to turn off 32.768kHz on RTC which is connected to PCA9701 and after ISR(INT2_vect) I don't handle this event,  left it for later.

 

My bad, sorry !

 

 

 

@sparrow 

 

[Re:]How do you check the length of the delay?

of course with oscilloscope

 

[Re:]Perhaps a ISR or WDT reset change the thing you check

That's my problem.

 

 

 

@cliff

[Re:]"apptaskHandler()" - sounds a LOT like an RTOS!

 

I just took name like this from LIGHTWEIGHT MESH stack.

 

 

my code is organized like this in general:

 

is this OK?

//********************************************************************************************************************************
// appTaskHandler()
//********************************************************************************************************************************
void appTaskHandler()
{
	switch(appState)
	{
		case APP_INITIATING_STATE:
		{	
			// define ports,  timers and interrupts
		}
		break;

		case APP_PARAMETERS_STATE:
		{
			// load paramerets form FLASH	
		}	
		break;	

		case APP_WAIT_STATE:
		{
			// circle here 
			// wait for something to happen     if so, go to APP_INTERRUPT_STATE
		}
		break;	
		
		case APP_INTERRUPT_STATE:
		{
			// handle USART interrupt
			// handle ISR gpio
		}
		break;
		
		case APP_CODE_WORD_STATE:
	¸	{
		
		}
		break;		

		default:
		break;
	}
}



//********************************************************************************************************************************
// main()
//********************************************************************************************************************************
int main(void)
{	
	wdt_enable(1000);
	
	
	//TCNT1 = 0xD8EF;
	//TCCR1B = 0x01;							// timer start
	
	
	gpio_make_out(CONFIG);
	gpio_set(CONFIG);
	
	while(1)
        {
		wdt_reset();
		
		appTaskHandler();
		appUartTaskHandler();
		
		if( (TIFR1 & 0x01) == 0x01 )
		{
			appTimerTaskHandler();
		}
	}
}

 

 

@Someguy22

Hmm... If you don't post the code for apptaskHandler() how can we tell why delay doesn't work there?

 

it is mumbo-jumbo while I'm experimenting and long I don't want to bother you

 

 

 

Thank you guys for help !

 

 

 

 

 

 

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

Hey, thanks for posting the solution to your problem.

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

The bottom line is this. If you have a micro and you want the effect of "several things happening at once". (Formerly this is often called an RTOS) then you cannot have one of your "tasks" sitting in idle _delay_ms() style loops for accurate delays. Either when the task is preempted or yields it cannot know how long the "other stuff" will be in control.

 

What you should be thinking about is a timer interrupt that regularly ticks a "heartbeat". Often this is called something like "systicks" (in fact when you reach ARM you wil find they all have a timer specifically for this). Say you arrange for that timer to interrupt every 100ms and increment a counter. Ten 10 "ticks" is 1 second. So if you want something to happen roughly 1second after a previous event you take a copy of "systicks" then keep checking the new value until it is greater than previous+10.

 

100ms may be a bit too "granular" and you may require more finesse in your timing so then you choose to use 10ms or even 1ms. (which means counting to 100 or 1000 for the elapse of a whole second).

 

In real MCU work things like _delay_ms() are almost never found. You never want the CPU to waste time/energy effectively doing nothing. Either you can use the intervening time to get on and do something more useful or you put the CPU to sleep to save energy.

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

Hi Cliff !

 

 

Thank you very much for advice !

 

 

I use timer 1  to count to 10ms and then deal with it in appTimerTaskHandler() in main(): 

 

//********************************************************************************************************************************
// main()
//********************************************************************************************************************************
int main(void)
{
	wdt_enable(1000);

	//TCNT1 = 0xD8EF;
	//TCCR1B = 0x01;							// timer start

	gpio_make_out(CONFIG);
	gpio_set(CONFIG);

	while(1)
        {
		wdt_reset();

		appTaskHandler();
		appUartTaskHandler();

		if( (TIFR1 & 0x01) == 0x01 )
		{
			appTimerTaskHandler();
		}
	}
}

 

 

I use this principle to control LEDs and other stuff .

 

I don't use _delay_ms() for LEDs, that won't make any sense.

 

 

//********************************************************************************************************************************
// appTimerTaskHandler()
//********************************************************************************************************************************
void appTimerTaskHandler()
{
	for (int i=0; i<10; i++)
	{
		if (timer_all[i].active == TRUE)
		{

			if (timer_all[i].interval <= 10)
			{
				timer_all[i].active = FALSE;
				timer_all[i].handler(&timer_all[i]);
			}
			else
			{
				timer_all[i].interval -= 10;				// -10 ms
			}

		}
	}

	TCCR1B = 0x00;										// timer stop
	TIFR1 = 0x01;										// clear TOV1

	TCCR1B = 0x01;										// timer start
	TCNT1 = 0xD8EF;

}

 

timer definition looks like this:

typedef struct _SYS_Timer
{
	uint32_t interval;
	bool active;
	void (*handler) (struct _SYS_Timer *timer);
} SYS_Timer;

 

I "borrowed" this form Alexru in LEIGHTWEIGHT MESH stack and it took me some time to figure out how it works.

 

 

I could replace _delay_ms() with my own timer of course to make some pauses in communication, but that would complicate my state machine.

 

 

Regards !

 

 

 

 

 

 

 

 

 

 

 

Last Edited: Fri. Nov 20, 2015 - 07:24 PM