Atmega328P _delay_ms default function gives 2x delay of set value

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

I am writing program in Atmel Studio for Atmega328P and downloading that on arduino board with avrdude.exe

 

#define F_CPU 16000000UL

 

#include <avr/io.h>

#include <util/delay.h>

 

 

int main( void )

{

/* Initializations */

DDRB |= (1 << DDB5);   // LED on-off output pin

while (1)

{

PINB |= ( 1<<PINB5);

_delay_ms(1000);

PINB &= ~( 1<<PINB5);

_delay_ms(1000);

}

}

 

This is the DSO snap for that pin. Its toggling after every 2 sec.

 

For the modified code like:

#define F_CPU 16000000UL

 

#include <avr/io.h>

#include <util/delay.h>

 

 

int main( void )

{

/* Initializations */

DDRB |= (1 << DDB5);   // LED on-off output pin

while (1)

{

PINB |= ( 1<<PINB5);

_delay_ms(1000);

PINB &= ~( 1<<PINB5);

_delay_ms(400);

}

}

 

It generates square wave with 1.4s . This is very weird. 

 

Initially I thought its some clock issue. So I generated PWM, and it gets generated with correct frequency. 

 

Please help me with this.

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

I am guessing this is a Studio project and you are using an Arduino for hardware?

 

If so, in teh Fuses Section of Studio for programming check to see if the DIV8 fuse  is set to be programmed.  There will be a 'Check' in the little box next to DIV8 if this is the case uncheck that box and hit Write/Program.

 

JIm

 

EDIT:

/* Initializations */
DDRB |= (1 << DDB5);   // LED on-off output pin
while (1)
{
PINB |= ( 1<<PINB5);
_delay_ms(1000);
PINB &= ~( 1<<PINB5);
_delay_ms(400);
}
}
 

It generates square wave with 1.4s . This is very weird. 

No, thats correct.  The HIGH side of the wave form is set for 1000ms, the LOW side is set for 400ms....Look at your code carefully 

If you want a career with a known path - become an undertaker. Dead people don't sue! - Kartman

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

Last Edited: Mon. Dec 25, 2017 - 03:15 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

PINB is changing the pullup, not the port output right?

What if you use PORTB instead of PINB

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

Thank you!

This worked.

Updated code:

 

#define F_CPU 16000000UL

 

#include <avr/io.h>

#include <util/delay.h>

 

 

int main( void )

{

/* Initializations */

DDRB |= (1 << DDB5);   // LED on-off output pin

while (1)

{

PORTB |= ( 1<<PORTB5);

_delay_ms(1000);

PORTB &= ~( 1<<PORTB5);

_delay_ms(400);

}

}

 

But in the datasheet I found this:

That's why i was setting PINB.

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

Yeah, I have a little trouble understanding that as well, but I always thought I was the only one(Until your post ;) )

 

I always write to PORT as well.  

 

Glad to read its working for you finally.

 

Jim

If you want a career with a known path - become an undertaker. Dead people don't sue! - Kartman

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

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

The PINB &= ~( 1<<PINB5); will not affect the PB5 pin (it would toggle the other pins on PORTB that are set as output; however, they are all inputs).

David (aka frog_jr)

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

Priyanka.K wrote:
But in the datasheet I found this: That's why i was setting PINB.

Do you understand why your code in post #1 worked as it did, or are you still puzzled about that?

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

I added a comment to let you know what is happening to you.

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

int main( void )
{
	/* Initializations */
	DDRB |= (1 << DDB5);   // LED on-off output pin

	while (1)
	{
		PINB |= ( 1<<PINB5);	// (toggle PORTB5)
		_delay_ms(1000);
		PINB &= ~( 1<<PINB5);	// (not effect)
		_delay_ms(1000);
	}
	// (As a result, the port output is inverted once every 2 seconds.)
}

 

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

alank2 wrote:
PINB is changing the pullup, not the port output right?

No.

 

jgmdesign wrote:
Yeah, I have a little trouble understanding that as well, but I always thought I was the only one(Until your post

Interesting -- what part of "writing to PIN toggles corresponding bit(s) in PORT" is not clear?

 

Now, the ramifications lead to a number of combinations.  But PORT always controlled output state when an output, and pullup when an input.

 

=================

Back when men were men and AVR8s didn't have all the newfangled features, it was a painful process to toggle an output pin.  Several cycles and instructions to do the job, and RMW considerations as well -- one could not toggle an output in an ISR for debugging purposes without thinking about possible RMW.

 

Around the time of [Mega48-family introduction?] the AVR chip designers added the feature, and use a write to PIN to implement -- thus avoiding having another I/O register.

 

There have been examples here of algorithms making great use of the toggle feature.  IME for "general" work it is more of a "Meh."; toggle most done on a debugging indicator.

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

theusch wrote:

alank2 wrote:

PINB is changing the pullup, not the port output right?

 

No.

 

Ahh yes, it is toggling the output.  I forgot about that.  Setting PORTB while set as in input sets the pullup.

 

DDRx -->  input/ouput direction

PORTx --> when output, sets high or low output, when input sets pullup enabled or not enabled

PINx --> when set, it toggles output, when read it shows the pin state

 

Right?

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

Note that using update operators on a PIN register presents logical difficulties.

Compiler writers generally resolve the issue by ignoring it.

The result is that update operations can behave differently depending on the the optimization level.

The first PINB update probably toggled PORTB.5 with an SBI instruction.

The second probably did nothing with a CBI instruction.

With low optimization, both probably also cleared 7 PORTB bits,

International Theophysical Year seems to have been forgotten..
Anyone remember the song Jukebox Band?