PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : _delay_ms()



michaelb
22.05.2005, 13:40
Hallo zusammen,
ich hab ne Frage voll oft taucht in Quelltexten dieser Abschnitt auf

void warte(uint16_t wert){
for (uint16_t zeit=0;zeit<wert;zeit++)
{
_delay_ms(10);
}
}
jetzt geht es mir um das _delay_ms(10); in welcher Lib ist die Funktion? Ich hab zuerst an die delay.h gedacht aber da ist sie nicht! Ich poste mal die delay.h weil jemand gesagt hat darin wäre sie!

/* Copyright (c) 2002, Marek Michalkiewicz
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. */

/* $Id: delay.h,v 1.2.2.2 2004/02/13 21:43:37 joerg_wunsch Exp $ */

/*
avr/delay.h - loops for small accurate delays
*/

#ifndef _AVR_DELAY_H_
#define _AVR_DELAY_H_ 1

#include <inttypes.h>

/* 8-bit count, 3 cycles/loop */
static __inline__ void
_delay_loop_1(uint8_t __count)
{
asm volatile (
"1: dec %0" "\n\t"
"brne 1b"
: "=r" (__count)
: "0" (__count)
);
}

/* 16-bit count, 4 cycles/loop */
static __inline__ void
_delay_loop_2(uint16_t __count)
{
asm volatile (
"1: sbiw %0,1" "\n\t"
"brne 1b"
: "=w" (__count)
: "0" (__count)
);
}

/* TODO: macros to allow specifying delays directly in microseconds
(with MCU clock frequency defined by the user). With constant
delays, all floating point math would be done at compile time. */

#endif /* _AVR_DELAY_H_ */

ist diese lib bei euch genauso oder wo gibt es die Funktion _delay_ms(); ?
Gruß Michi

RCO
22.05.2005, 13:43
heißt glaub ich:
#include <avr/delay.h>
Schau doch einfach mal im Ordner nach. Musst aber noch nen par berechnungen machen, schau mal hier:
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial
(such nach delay)

michaelb
22.05.2005, 14:18
in der delay.h gibt es diese Funktion nicht! Hab ihr diese umgeändert oder woher bekommt ihr die _delay_ms();
Gruß Michi

michaelb
22.05.2005, 14:24
ich glaube ich meinen Fehler gefunden!
ch hab die avr-lib version 1.0.4 und im AVR-GCC Tutorial steht die Funktion _delay_ms(); gibt es erst ab der Version 1.2.0 !
Ich lad mir mal die neue runter.
Gruß Michi

RCO
22.05.2005, 16:12
Hättest du dir mal die Mikrocontroller-Seite angesehen:


#include <avr/delay.h> /* definiert _delay_ms() ab avr-libc Version 1.2.0 */

O:)
Ich hab die Funktion auch schon öfter benutzt, es könnte gut sein, dass du noch sowas wie F_CPU definieren musst.

michaelb
22.05.2005, 16:15
hallo RCO,
ich hab mir die neue Version von WinAVR gedownloadet da gibts die _delay_ms(); Funktion!
Gruß Michi

pebisoft
22.05.2005, 16:28
ich habe in der make die f_cpu und trotzdem stimmt die zeit der _delay nicht, woran liegt das.
bei meiner selbsterstellten srf04-routine müssen us gewartet werden. mit asm-routinen und for geht es, aber mit der_delay nicht.


#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <string.h>
#include <stdint.h>
#include <avr/delay.h>

#define READ 1
#define WRITE 2

#define USART_BAUD_RATE 19200
#define USART_BAUD_SELECT (F_CPU/(USART_BAUD_RATE*16l)-1)

#define MESS_PORT PORTB
#define MESS_PORT_RICHTUNG DDRB
#define MESS_PIN PINB
#define MESS_BIT PB1 // Echo-Trigger Eingang oder einfach Messeingang

#define US_PORT PORTB
#define US_PORT_RICHTUNG DDRB
#define US_BIT PB0 // Der Pin kommt zum Trigger-Puls Eingang

void usart_init(int Enable, int Interupts)
{
if (Enable & READ) UCSRB = (1<<RXEN);
if (Enable & WRITE) UCSRB |= (1<<TXEN);

if (Interupts & READ) UCSRB |= (1<<RXCIE);
if (Interupts & WRITE) UCSRB |= (1<<TXCIE);
UBRRL = (unsigned char) USART_BAUD_SELECT;
}

void usart_writeChar(unsigned char c)
{
while (!(UCSRA & (1<<UDRE))) {}
UDR = c;
while(!(UCSRA & (1<<TXC))) {}
}

void usart_writeString(unsigned char *string) {
while (!(UCSRA & (1<<UDRE))) {}
while ( *string)
usart_writeChar(*string++);
}

uint16_t start_messung(void)
{
volatile uint16_t wert,i;
wert=0;

US_PORT_RICHTUNG|=(1<<US_BIT); // US_PIN auf Ausgang
US_PORT|=(1<<US_BIT); // Trigger-Puls auf high
for (i=0; i<10; i++)
asm volatile("nop");
US_PORT&=~(1<<US_BIT); // Trigger-Puls Eingang wieder auf low
for (i=0; i<200; i++)
asm volatile("nop");

TCNT1=0; // Timerregister auf 0
TCCR1B|= (1<<CS11); // Timer starten
while (MESS_PIN & (1<<MESS_BIT)) // Warten bis Echo/Mess Eingang auf low
wert=TCNT1;
TCCR1B&= ~(1<<CS11); // Timer wieder aus
return wert;
}

int main (void)
{

char s[10];
uint16_t wert_1;
usart_init( (READ + WRITE) , READ);

for (;;) {

wert_1=start_messung();
itoa( wert_1, s, 10);

usart_writeString(s);
usart_writeString("\r");
}
}


mfg pebisoft

michaelb
23.05.2005, 11:27
das mit der Delay stimmt bei mir auch nicht! Ich meine zeitlich!
Wenn ich in meinem Code
_delay_ms(1000); eingebe müsste es doch eine Sekunde warten macht es aber nicht denn es wartet kürzer!
Gruß Michi

lekro
23.05.2005, 14:51
_delay_ms(1000); eingebe müsste es doch eine Sekunde warten macht es aber nicht denn es wartet kürzer! Es könnte sicher nicht schaden, bei so einem Problem mal einen kurzen Blick in die Dokumentation zu werfen.

Zu _delay_ms gibt es nämlich eine wichtige Anmerkung.

pebisoft
23.05.2005, 14:58
dann raus damit......
ich habe keine vernüftige erklärung dafür gefunden, weil die routine ja aufruf-fertig serviert wird, in _ms und _us.
mfg pebisoft

michaelb
23.05.2005, 20:19
Hi Lekro,
kannst des mal posten ich bin genauso gespannt wie pebisoft! ich dachte auch das so eine abruffertige Routine gehen muss!
Gruß Michi

lekro
23.05.2005, 21:41
...das ist nicht euer Ernst, oder? :/
Zu _delay_ms gibt es doch insgesamt nur drei Zeilen Dokumentation. Die schnell selbst zu lesen geht bestimmt schneller, als hier zu posten.

Na gut, weil ich mir heute unnötige Diskussionen ersparen will: Hier (http://www.nongnu.org/avr-libc/user-manual/group__avr__delay.html) steht zu _delay_ms deutlich diese Anmerkung:

The maximal possible delay is 262.14 ms / F_CPU in MHz.
Um damit also 1000ms warten zu können bräuchtest du einen Takt von irgendwas unter 262kHz.

pebisoft
23.05.2005, 23:13
dann ist doch die ganze routine zum aufrufen völliger schwachsinn.
dann müste ich 30000 eingeben wenn ich 1000ms warten soll bei 8mhz
und rund 10000 wenn ich 1000us warten soll... oder...
mfg pebisoft

michaelb
24.05.2005, 10:02
hallo zusammen,
*zusammensack* des ist ja idiotisch!
Was bedeutet überhaupt zum Beispiel 10KHZ wieviel Impulse sind das pro Sekunde?
Gruß Michi

lekro
24.05.2005, 16:07
dann ist doch die ganze routine zum aufrufen völliger schwachsinn.
dann müste ich 30000 eingeben wenn ich 1000ms warten soll bei 8mhz
und rund 10000 wenn ich 1000us warten soll... oder... Nein, der Parameter bezeichnet schon die Millisekunden. Der Trick hinter _delay_ms ist, dass mit dem Parameter eine Berechnung durchgeführt wird, und zwar zur Compilezeit. Das heißt, der Compiler rechnet den übergebenen Wert von ms nach "Wartetakte" um. Für diese Umrechnung braucht der Compiler eben die Takt-Geschwindigkeit des Mikrocontrollers, da bei höherem Takt die Wartschleife schneller durchläuft als bei niedrigerem. Bei höherem Takt muss der Compiler den Parameter "1 ms" z.B. in mehr Wartetakte umrechnen als bei einem langsamen Takt.

lekro
24.05.2005, 16:11
Was bedeutet überhaupt zum Beispiel 10KHZ wieviel Impulse sind das pro Sekunde? 1 Hz ("1 Hertz") bezeichnet eine Schwingung pro Sekunde. 10 kHz sind also 10.000 Takt-Impulse pro Sekunde.

Du kannst den AVR aber soweit ich weiß minimal mit einem Uhrenquarz, also etwa 32kHz, takten. Aber selbst das kann schon zu Schwierigkeiten führen (zu langsam für manche ISP-Adapter o.ä.).

pebisoft
24.05.2005, 18:02
dann frage ich, warum funktioniert mein srf04 mit _delay... nicht. nach der aussage von lekro müsste es aber funktionieren....weil....weil ja die _delayroutine automatisch umrechnet.
funktioniert aber nicht.
mfg pebisoft

michaelb
24.05.2005, 21:08
hi lekro,
danke für deine Antwort! Hat für mich einiges klargestellt!
gruß Michi

Fisch-Ei
26.06.2005, 01:06
BTW: so ist das problem leicht zu lösen:


uint_8 temp;

...

temp = 0;
while(temp < 152) //Delay von 5 Sekunden
{
_delay_ms(33); /*maximal mögliche Delay-Zeit: 262,14ms/F_CPU in MHz
Bei 8Mhz = 32,77ms*/
temp++;
}

KingNothing
26.06.2005, 12:27
Nur als anmerkung, ich denke bei längeren wartezeiten ist es sinnvoller einen Timer-Interrupt zu verwenden, da hier der µc auch während des "wartens" noch zur verfügung steht.

Fisch-Ei
27.06.2005, 16:26
oder so... aber wie genau schaut dann dieses interrupt aus? ich weiß, dass die frage naiv ist, aber dafür ist es ja ein forum ;)

KingNothing
29.06.2005, 18:43
http://www.mc-project.de/Pages/AVR/Timer/timer.html
vielleicht hilft dir das ja

matzel
11.07.2005, 21:36
Hi!

Kann es sein, dass ein Fehler im http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial ist ?

Im Abschnitt 9.5.2.2 (Tasten-)Entprellung


#include <avr/io.h>
#include <inttypes.h>
#ifndef F_CPU
#define F_CPU 3686400UL /* Quarz mit 3.6864 Mhz */
#endif
#include <avr/delay.h> /* definiert _delay_ms() ab avr-libc Version 1.2.0 */

/* Einfache Funktion zum Entprellen eines Tasters */
inline uint8_t debounce(volatile uint8_t *port, uint8_t pin)
{
if ( ! (*port & (1 << pin)) )
{
/* Pin wurde auf Masse gezogen, 100ms warten */
_delay_ms(100);
if ( ! (*port & (1 << pin)) )
{
/* Anwender Zeit zum Loslassen des Tasters geben */
_delay_ms(100);
return 1;
}
}
return 0;
}

int main(void)
{
DDRB &= ~( 1 << PB0 ); /* PIN PB0 auf Eingang (Taster) */
PORTB |= ( 1 << PB0 ); /* Pullup-Widerstand aktivieren */
...
if (debounce(&PINB, PB0)) /* Falls Taster an PIN PB0 gedrueckt.. */
PORTD = PIND ^ ( 1 << PD7 ); /* ..LED an Port PD7 an-
bzw. ausschalten */
...
}

Hier wird ein delay mit 100ms angegeben. Aber 262.14ms/ 3.6864Mhz ergeben 71,1ms. Oder habe ich das nicht richtig verstanden ?