Sida 2 av 3

Re: Min C kod fungerar inte (AVR)

Postat: 29 oktober 2010, 09:32:24
av johano
BTW, det verkar vara ett trevligt kort det där, finns det några kvar till försäljning?

johan

Re: Min C kod fungerar inte (AVR)

Postat: 29 oktober 2010, 10:09:20
av thepirateboy
Ja, jag har två till och får troligen in fler under nästa vecka.

Re: Min C kod fungerar inte (AVR)

Postat: 29 oktober 2010, 10:14:45
av johano
Du har pm

/johan

Re: Min C kod fungerar inte (AVR)

Postat: 29 oktober 2010, 11:36:44
av sodjan
> För att jag har ändrat till portd.

Ja, *nu* ja !
Min kommentar avsåg naturligstvis den kod du hade postat och
som fanns tillgänglig när jag gjorde kommentaren.

Och även då du skrev "Den gör väl portd till utgång?" så fanns det ingen
annan kod än den där det stog "DDRC = 0xff; //Sätter portb till utgång".

Slutligen, min kommentar har inte ett smack med viss port att göra igentligen, det hela
handlade om att du satte DDR *C* i instruktionen men nämner PORT *B* i kommentaren !

Att det var just C och B är ointressant, att det var *olika* var det viktiga och slarviga.
Det verkar du fortfarande ha kollosalt svårt att förstå...

Re: Min C kod fungerar inte (AVR)

Postat: 29 oktober 2010, 21:49:38
av jesse
sodjan skrev:> _delay_ms(2000) brukar ge en fördröjning på 2 sekunder, inte 0.2 sekunder.

Det jag har hittat om _delay_ms() är att om man överskrider maxvärdet
för parametern så kommer den att börja räkna parametern som 1/10 ms.
Alltså 0.2 sek med 2000 som parameter.
The maximal possible delay is 262.14 ms / F_CPU in MHz.

When the user request delay which exceed the maximum possible one, _delay_ms() provides
a decreased resolution functionality. In this mode _delay_ms() will work with a resolution of
1/10 ms, providing delays up to 6.5535 seconds (independent from CPU frequency).
The user will not be informed about decreased resolution.
Men det kanske är en annan _delay_ms() som jag har hittat...

Å andra sidan så lär det inte hjälpa om lysdioden sitter på fel pinne i alla fall...
Det är fortfarande något här som jag inte fattar? Eller, jo... nej :(

Jag simulerade delay_ms(200), delay_ms(300) och delay_ms(2000) för F_CPU=1 MHz.
Vid 200 fick jag en fördröjning på exakt 200 ms. Vid 300 fick jag 312 ms och (2000) gav 2080 ms fördröjning. Det verkar vara fel när de säger " with a resolution of 1/10 ms"??? Hur uppnår jag det? Den där maxgränsen begriper jag inte. Jag får samma resultat om jag sätter F_CPU till 20 MHz

Re: Min C kod fungerar inte (AVR)

Postat: 29 oktober 2010, 22:12:05
av thepirateboy
Blir det någon förändring om du ändrar optimeringen (-Os, -O2 osv)?

Re: Min C kod fungerar inte (AVR)

Postat: 29 oktober 2010, 23:18:01
av jesse
Det ska man inte göra - för då blir det fel, enligt lib-instruktionerna.
Det ska alltid vara -Os
-02 ger dock samma resultat, utan optimering blir det lite bara fel: 203.42 ms...

Re: Min C kod fungerar inte (AVR)

Postat: 30 oktober 2010, 01:05:17
av sodjan
Nej, jag fattar inte heller hur man korrekt ska tolka beskrivningen av _delay_ms()...

Men å andra sidan så finns/fanns det större problem med koden så den kanske
inte spelar så stor roll... :-)

Re: Min C kod fungerar inte (AVR)

Postat: 30 oktober 2010, 07:41:10
av Muppis
Värt att tänka på är att Windows har en upplösning på 10ms i sina timers.

Re: Min C kod fungerar inte (AVR)

Postat: 30 oktober 2010, 09:11:42
av SvenW
För er som inte har koden hemma:
(Flyttalsoperationerna sker i kompilatorn och tar inga
resurser i AVR-processorn)

Kod: Markera allt

/**
   \ingroup util_delay

   Perform a delay of \c __ms milliseconds, using _delay_loop_2().

   The macro F_CPU is supposed to be defined to a
   constant defining the CPU clock frequency (in Hertz).

   The maximal possible delay is 262.14 ms / F_CPU in MHz.

   When the user request delay which exceed the maximum possible one,
   _delay_ms() provides a decreased resolution functionality. In this
   mode _delay_ms() will work with a resolution of 1/10 ms, providing
   delays up to 6.5535 seconds (independent from CPU frequency).  The
   user will not be informed about decreased resolution.
 */
void
_delay_ms(double __ms)
{
	uint16_t __ticks;
	double __tmp = ((F_CPU) / 4e3) * __ms;
	if (__tmp < 1.0)
		__ticks = 1;
	else if (__tmp > 65535)
	{
		//	__ticks = requested delay in 1/10 ms
		__ticks = (uint16_t) (__ms * 10.0);
		while(__ticks)
		{
			// wait 1/10 ms
			_delay_loop_2(((F_CPU) / 4e3) / 10);
			__ticks --;
		}
		return;
	}
	else
		__ticks = (uint16_t)__tmp;
	_delay_loop_2(__ticks);
}

#endif /* _UTIL_DELAY_H_ */

Kod: Markera allt

/** \ingroup util_delay_basic

    Delay loop using a 16-bit counter \c __count, so up to 65536
    iterations are possible.  (The value 65536 would have to be
    passed as 0.)  The loop executes four CPU cycles per iteration,
    not including the overhead the compiler requires to setup the
    counter register pair.

    Thus, at a CPU speed of 1 MHz, delays of up to about 262.1
    milliseconds can be achieved.
 */
void
_delay_loop_2(uint16_t __count)
{
	__asm__ volatile (
		"1: sbiw %0,1" "\n\t"
		"brne 1b"
		: "=w" (__count)
		: "0" (__count)
	);
}

#endif /* _UTIL_DELAY_BASIC_H_ */


Re: Min C kod fungerar inte (AVR)

Postat: 30 oktober 2010, 21:16:54
av monstrum
Varför hålla på att försöka få fruktansvärt exakta delay-funktioner? För mig känns det helt orelevant ifall delay(1000) ger fördröjning 1,0 s eller 1,1 s.
Ska man ha en exakt fördröjning så använder man en hårdvaru-timer alternativt en mjukvarubaserad dito som utgår från en kontinuerlig interrupt-timer.

Re: Min C kod fungerar inte (AVR)

Postat: 30 oktober 2010, 21:42:15
av Icecap
Jag kan bara hålla med, visst behövs delay lite då och då men att ha dessa problem med dessa funktioner fattar jag helt enkelt inte.

Jag startar alltid en timer-interrupt som fungerar till det jag behöver, det har hänt i enstaka fall att jag har stoppat ett program en viss tid (t.ex. visande en sign-on på ett display efter initiering) men jag har aldrig använd delay() till sånt.

I vissa fall där man ska testa en viss enkel funktion kan det vara vettigt att använda sånt men aldrig i en skarp version!

Re: Min C kod fungerar inte (AVR)

Postat: 31 oktober 2010, 13:19:22
av jesse
För mig känns det helt orelevant ifall delay(1000) ger fördröjning 1,0 s eller 1,1 s.
Nu var väl problemet att _delay_ms(2000) kunde ge en fördröjning på 200ms istället för 2000 enligt vissa inlägg här? Det är ju en viss skillnad. Dessutom så finns det ju ingen som helst anledning varför _delay_ms(1000) skulle ge en fördröjning på 1100 ms. Så värdelösa är faktiskt inte dessa fördröjningsrutiner. Noggrannheten är givetvis 1 ms och inget annat. Så visst ska man kunna använda sig av dessa och kunna lita på dem.

Re: Min C kod fungerar inte (AVR)

Postat: 31 oktober 2010, 18:33:25
av stekern
I vissa fall kan dessa _delay rutiner dessutom bli nogrannare än att köra med timer interrupt, i och med bortsparning på stacken.
(detta går givetvis att rundgå genom att skriva timer isren i asm, men då ska man kunna hålla tungan rätt i mun).

Re: Min C kod fungerar inte (AVR)

Postat: 31 oktober 2010, 19:45:25
av Icecap
Jag har aldrig varit i en situation där det är viktigt att ett 2 sek delay är exakt 2 sek, när man når den storlek är det alltid på ett ungefär och ska det vara exakt går det att skriva ISR'n så att latensen är ganska liten.

Min erfarenhet är att användandet av _delay() nästan uteslutande sker hos oerfarna programmerare, inget ont i det men när de mer vana går ifrån det är det kanske an anledning...

Själva delay-funktionen använder man ju lite varstans, lekar man t.ex. med 1-Wire är delay ju totalt oumbärligt men även där kan man leka lite. Jag gjorde t.ex. en avläsning av temperatur som körde i min 10Hz timer-ISR.

För att sända en '1' ska man ju dra datalinjen '0' kortvarigt och sedan '1', ska man sända '0' ska man hålla datalinjen '0' i längre tid.
Jag löste det vid att göra en sekvensstyring som startade med att lägga '0' ut.

Sedan gjorde jag lite annat som gick snabbt och kollade sedan om det skulle vara en '1' eller '0', skulle det vara en '1' höjde jag datalinjen. sedan gjorde jag färdigt i ISR'n och slutade med att lägga en '1' ut på datalinjen.

På detta vis gjorde jag annat under tiden som 1-Wire funktionen kördes och det kostade väldigt lite ISR-tid - och fungerade perfekt.

Visst tog det en del interrupts (= tid) men temperaturen ändras inte speciellt snabbt så det var knappast ett större problem, jag hade knappast extra overhead och det kör fortfarande efter vad jag vet. Används i 2 textskyltar, ett i Svappavaara och ett i Abisko/Björkliden.