Min C kod fungerar inte (AVR)
Re: Min C kod fungerar inte (AVR)
BTW, det verkar vara ett trevligt kort det där, finns det några kvar till försäljning?
johan
johan
-
- EF Sponsor
- Inlägg: 2109
- Blev medlem: 27 augusti 2005, 20:57:58
- Ort: Borlänge
Re: Min C kod fungerar inte (AVR)
Ja, jag har två till och får troligen in fler under nästa vecka.
Re: Min C kod fungerar inte (AVR)
> 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å...
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)
Det är fortfarande något här som jag inte fattar? Eller, jo... nejsodjan 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.
Men det kanske är en annan _delay_ms() som jag har hittat...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.
Å andra sidan så lär det inte hjälpa om lysdioden sitter på fel pinne i alla fall...

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
-
- EF Sponsor
- Inlägg: 2109
- Blev medlem: 27 augusti 2005, 20:57:58
- Ort: Borlänge
Re: Min C kod fungerar inte (AVR)
Blir det någon förändring om du ändrar optimeringen (-Os, -O2 osv)?
Re: Min C kod fungerar inte (AVR)
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...
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)
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...
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)
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)
För er som inte har koden hemma:
(Flyttalsoperationerna sker i kompilatorn och tar inga
resurser i AVR-processorn)
(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)
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.
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)
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!
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)
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.För mig känns det helt orelevant ifall delay(1000) ger fördröjning 1,0 s eller 1,1 s.
Re: Min C kod fungerar inte (AVR)
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).
(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)
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.
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.