Ja viem, ze sa to nezda, ale pouzivat casove slucky na generovanie casu je divne. Aj na tu LEDku.
Ja by som Ti doporucil sa na casove slucky (asi iba s vynimkou 1-wire, tam je to bez nich kvoli kratkym casom velmi osemetne ) hned na zaciatku vykaslat a pouzit nieco, co ti zabezpeci “presny cas”. A medzi tym, nech sa robi nieco poriadne. A nemusi sa jednoat hned o prerusenie
// mega32, blikanie LEDkou
#define PREDVOLBA_ZAP 1000
#define PREDVOLBA_VYP 2000
#define TLED 2 // napriklad na pine 2 portu B
#define OUT_LED (DDRB |=(1<<TLED))
#define SET_LED (PORTB |=(1<<TLED))
#define RES_LED (PORTB &=~(1<<TLED))
#define PREDDELIC_HLAVNEJ_CINNOSTI 1000
static uint8_t stav_led;
static uint16_t cnt_hlavnej_cinnosti;
int main(void)
{
OUT_TLED;
// prednastavenie modu citaca pocitania do hodnoty v OCR a nastavenie casovej zakladne
TCCR1B = (1<<WGM12) + (1<<CS10) + (1<<CS12);
// prednastavenie prvej casovej zakladni
OCR1A = PREDVOLBA_ZAP;
stav_led = FALSE;
cnt_hlavnej_cinnosti = PREDDELIC_HLAVNEJ_CINNOSTI;
for(;;) {
// testovanie dosiahnutia hodnoty citaca v OCR0
if (TIFR & (1<<OCF1A)) {
// vynulovanie flag, musi sa pomocou logickej funkcie or |
TIFR = TIFR | (1<<OCF1A);
// ---------------- zaciatok likania LEDkou -------------------
if (stav_led == TRUE) {
stav_led = FALSE;
// _ZAP, _VYP uz podla toho ako mas naletovanu LEDku
OCR1A = PREDVOLBA_ZAP;
RES_TLED;
}
else {
stav_led = TRUE;
OCR1A = PREDVOLBA_VYP;
SET_TLED;
}
// ---------------- koniec likania LEDkou -------------------
// tu sa moze robit nieco uzitocne, naprikad nacitavat tlacitko, ako to ze ma ta LEDka vlastne blikat, alebo nieco ine
cnt_hlavnej_cinnosti--;
if (cnt_hlavnej_cinnosti == 0) {
cnt_hlavnej_cinnosti = PREDDELIC_HLAVNEJ_CINNOSTI;
fn_hlavna_cinnost();
}
}
}
}
Lahko si zmenis casovac, alebo predvolby.
fn_hlavna_cinnost()
sa prirodzene musi stihnut do dalsieho dosiahnutia predvolby OCR1A casovacom. Inak by sa to muselo riesit cez prerusenie. Ale to je jasna vec.
ak by si chcel predsa len nejake delay, tak prikladam kod,ktory som stiahol tu niekde z webu. Autora nepoznam, ale dufam, ze mi bude odpustene
Re: AVR - na optimalizaci nezávislé Delay rutiny
Posted: Wed 19 of Dec, 2007 [22:58],
Tiez som s tym bojoval, az som si urobil vlastne... (mikrosekundovu som prevzal a upravil)
// delay for a minimum of <us> microseconds
// the time resolution is dependent on the time the loop takes
// e.g. with 4Mhz and 4 cycles per loop, the resolution is 1 us
void delay_us(WORD time_us)
{
WORD delay_loops, dummy;
// one loop takes 4 cpu cycles
delay_loops = (time_us / 4) * CYCLES_PER_US;
asm volatile ("\n"
"mov %A0, %A1\n\t"
"mov %B0, %B1\n"
"L_dl2%=:\n\t"
"sbiw %A0, 1\n\t"
"brne L_dl2%=\n\t"
:"=&w" (dummy) //& znaci, ze sa pouzije len register
:"r"((unsigned short) (delay_loops))
);
}
void delay_ms(WORD time_ms)
{
WORD loops, reminder, i;
if(time_ms < 256)
delay_ms_max255((unsigned char)time_ms);
else
{
loops = time_ms / 255;
reminder = time_ms % 255;
for(i=loops; i; i-- )
{
delay_ms_max255(255);
}
delay_ms_max255((unsigned char)reminder);
}
}
void delay_ms_max255(BYTE time_ms)
{
WORD delay_count = F_CPU / 4000;
WORD cnt;
if(!time_ms) //test na 0, zaberie 2 instrukcie, ale pomoze
return; //lebo by sa cyklilo 255 krat
asm volatile ("\n"
"L_dl1%=:\n\t"
"mov %A0, %A2\n\t"
"mov %B0, %B2\n"
"L_dl2%=:\n\t"
"sbiw %A0, 1\n\t"
"brne L_dl2%=\n\t"
"dec %1\n\t" "brne L_dl1%=\n\t":"=&w" (cnt)
:"r"(time_ms), "r"((unsigned short) (delay_count))
);
}