Author Topic: _delay_us problem  (Read 5305 times)

0 Members and 1 Guest are viewing this topic.

Offline m.m.mTopic starter

  • Regular Contributor
  • *
  • Posts: 105
  • Country: ir
  • EE MSc Student and Hobbyist
_delay_us problem
« on: September 22, 2014, 12:01:45 pm »
hi, I wanted to send a signal using a 433MHz transceiver and a atmega32a, so I wrote this code with fuses set to 8MHz:
Code: [Select]
#include <avr/io.h>
#include <util/delay.h>
#define F_CPU 8000000UL;

int main(void) {
DDRD=0xFF;
while(1)
{
PORTD=0xFF;
_delay_us(685);
PORTD=0x00;
_delay_us(1300);
PORTD=0xFF;
_delay_us(735);
PORTD=0x00;
_delay_us(640);
PORTD=0xFF;
_delay_us(1400);
PORTD=0x00;
_delay_us(1300);
PORTD=0xFF;
_delay_us(740);
PORTD=0x00;
_delay_us(1300);
PORTD=0xFF;
_delay_us(735);
PORTD=0x00;
_delay_us(641);
PORTD=0xFF;
_delay_us(1400);
PORTD=0x00;
_delay_us(640);
PORTD=0xFF;
_delay_us(1400);
PORTD=0x00;
_delay_us(640);
PORTD=0xFF;
_delay_us(1400);
PORTD=0x00;
_delay_us(640);
PORTD=0xFF;
_delay_us(1430);
PORTD=0x00;
_delay_us(640);
PORTD=0xFF;
_delay_us(1400);
PORTD=0x00;
_delay_us(640);
PORTD=0xFF;
_delay_us(1400);
PORTD=0x00;
_delay_us(640);
PORTD=0xFF;
_delay_us(1400);
PORTD=0x00;
_delay_us(640);
PORTD=0xFF;
_delay_us(1400);
PORTD=0x00;
_delay_us(640);
PORTD=0xFF;
_delay_us(1400);
PORTD=0x00;
_delay_us(640);
PORTD=0xFF;
_delay_us(1400);
PORTD=0x00;
_delay_us(640);
PORTD=0xFF;
_delay_us(1400);
PORTD=0x00;
_delay_us(1300);
PORTD=0xFF;
_delay_us(760);
PORTD=0x00;
_delay_us(640);
PORTD=0xFF;
_delay_us(1400);
PORTD=0x00;
_delay_us(640);
PORTD=0xFF;
_delay_us(1400);
PORTD=0x00;
_delay_us(640);
PORTD=0xFF;
_delay_us(1410);
PORTD=0x00;
_delay_us(1300);
PORTD=0xFF;
_delay_us(685);
PORTD=0x00;
_delay_ms(100);
}
}
but when I see it with my logic analyzer, all the delays are wrong, for example for the first ON time which should be 685 microseconds, I get 85 uS! what is wrong? thanks.
« Last Edit: September 22, 2014, 12:03:49 pm by m.m.m »
25 y/o Electronics Lover
 

Offline Kremmen

  • Super Contributor
  • ***
  • Posts: 1289
  • Country: fi
Re: _delay_us problem
« Reply #1 on: September 22, 2014, 12:09:07 pm »
Check the avr-libc doc page in the net. the maximum delay you can get from _delay_us is 768 / F_CPU (in MHz). So your max will be 768/8 i.e. far shorter than any of those in your code. The compiler will silently replace invalid calls with _delay_ms but obviously your mileage has varied significantly ...
Nothing sings like a kilovolt.
Dr W. Bishop
 

Offline m.m.mTopic starter

  • Regular Contributor
  • *
  • Posts: 105
  • Country: ir
  • EE MSc Student and Hobbyist
Re: _delay_us problem
« Reply #2 on: September 22, 2014, 12:14:14 pm »
Check the avr-libc doc page in the net. the maximum delay you can get from _delay_us is 768 / F_CPU (in MHz). So your max will be 768/8 i.e. far shorter than any of those in your code. The compiler will silently replace invalid calls with _delay_ms but obviously your mileage has varied significantly ...
thanks a lot, so now I should either change the F_CPU or use _delay_ms instead, am I right?
25 y/o Electronics Lover
 

Offline m.m.mTopic starter

  • Regular Contributor
  • *
  • Posts: 105
  • Country: ir
  • EE MSc Student and Hobbyist
Re: _delay_us problem
« Reply #3 on: September 22, 2014, 12:22:56 pm »
thanks a lot man, I fixed it and it worked!  :-+   
25 y/o Electronics Lover
 

Offline Jeroen3

  • Super Contributor
  • ***
  • Posts: 4078
  • Country: nl
  • Embedded Engineer
    • jeroen3.nl
Re: _delay_us problem
« Reply #4 on: September 22, 2014, 01:58:00 pm »
A better way would be to use the spi peripheral set to a bit timing of the shortest pulse required.
This will just shift the bits to the transmitter, not requiring these ambiguous and ugly delays.

Please note the delays will be wrong if you have any interrupts.
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: _delay_us problem
« Reply #5 on: September 22, 2014, 04:20:03 pm »
"685 microseconds, I get 85 uS"

685 / 85 = 8.

Maybe you clicked the /8 clock setting - your true cpu speed is 1Mhz.
================================
https://dannyelectronics.wordpress.com/
 

Offline mikerj

  • Super Contributor
  • ***
  • Posts: 3238
  • Country: gb
Re: _delay_us problem
« Reply #6 on: September 22, 2014, 10:58:23 pm »
"685 microseconds, I get 85 uS"

685 / 85 = 8.

Maybe you clicked the /8 clock setting - your true cpu speed is 1Mhz.

Why would running the CPU 8 times slower yield delays that are 8 times shorter?

The answer has already been given; the delay_us function has an inherent limit on the achievable delay for a given clock speed.
 

Offline bktemp

  • Super Contributor
  • ***
  • Posts: 1616
  • Country: de
Re: _delay_us problem
« Reply #7 on: September 23, 2014, 08:39:51 am »
The documentation clearely says, it automatically uses _delay_ms instead of _delay_us when the time is to long, so it should work upto the _delay_ms limits.

The true problem is here:
#include <util/delay.h>
#define F_CPU 8000000UL;

My guess: F_CPU is defined somewhere else and defaults to 1MHz. Therefore all delay calculations are done for 1MHz.
Swap both lines and it should work.
« Last Edit: September 23, 2014, 12:19:05 pm by bktemp »
 

Offline alank2

  • Super Contributor
  • ***
  • Posts: 2185
Re: _delay_us problem
« Reply #8 on: September 23, 2014, 12:20:40 pm »
The built in functions for delay are not that great, especially in terms of accuracy with smaller delays.  An example might be that you ask for a uS delay that is less than one clock cycle and it delays three clock cycles instead.  I've come up with a header I use which uses the internal function to generate an exact number of clock cycles.  The floating point and calculations in the code below will get optimized out by the compiler and leave you with the delay only.

Also, make certain your F_CPU is correct, if it is wrong, your delays will be wrong.

Code: [Select]
#ifndef CDELAY_H
#define CDELAY_H

#define Delay_ns(__ns) if((unsigned long) (F_CPU/1000000000.0 * __ns) != F_CPU/1000000000.0 * __ns)\
                         __builtin_avr_delay_cycles((unsigned long) ( F_CPU/1000000000.0 * __ns)+1);\
                       else __builtin_avr_delay_cycles((unsigned long) ( F_CPU/1000000000.0 * __ns))
#define Delay_us(__us) if((unsigned long) (F_CPU/1000000.0 * __us) != F_CPU/1000000.0 * __us)\
                         __builtin_avr_delay_cycles((unsigned long) ( F_CPU/1000000.0 * __us)+1);\
                       else __builtin_avr_delay_cycles((unsigned long) ( F_CPU/1000000.0 * __us))
#define Delay_ms(__ms) if((unsigned long) (F_CPU/1000.0 * __ms) != F_CPU/1000.0 * __ms)\
                         __builtin_avr_delay_cycles((unsigned long) ( F_CPU/1000.0 * __ms)+1);\
                       else __builtin_avr_delay_cycles((unsigned long) ( F_CPU/1000.0 * __ms))
#define Delay_s(__s)   if((unsigned long) (F_CPU/1.0 * __s) != F_CPU/1.0 * __s)\
                         __builtin_avr_delay_cycles((unsigned long) ( F_CPU/1.0 * __s)+1);\
                       else __builtin_avr_delay_cycles((unsigned long) ( F_CPU/1.0 * __s))

#endif
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf