Radic znakoveho LCD SPLC780D

Miroslav ©inko sinkomiro na gmail.com
Středa Srpen 4 19:14:57 CEST 2010


Funkcie z toho delay.h stoja za p*d. V komentari je uvedene, ze ma byt
zapnuta optimalizacia (samo osebe je to divne pri "nezmyselnych"
cykloch), ale uz nepisu aka a na ktorej verzii GCC. Pred par rokmi som
sa s nimi tiez trapil, nepomohlo nic. Ten display kludne nemusi bezat
kvoli tymto delayom... Aj ked pozrel som lss a nejake tie cykly tam
su...
Skuste tieto funkcie, mam ich overene. Zaklad je tiez z nejakej
kniznice, ale trochu som si ich upravil.

prototypy do headra:
#define CYCLES_PER_US ((F_CPU+500000)/1000000) 	// cpu cycles per microsecond
void delay_ms(WORD time_ms);
void delay_ms_max255(BYTE time_ms);
void delay_us(WORD time_us);

tela:

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)
{
#define DELAY_COUNT (F_CPU/4000) //internal loop takes 4 cycles; x1000
for miliseconds
WORD cnt;

	if(!time_ms)			//test na 0, zaberie 2 instrukcie, ale pomoze
		return;				//lebo by sa cyklilo 255 krat

	asm volatile (
		"L_dl1%=:\n"
			"ldi %A0, %2\n"		//low byte of delay count into local var cnt
			"ldi %B0, %3\n"		//high byte
		"L_dl2%=:\n"
			"sbiw %A0, 1\n"		//internal loop (2 cycles)
			"brne L_dl2%=\n"	//              (2 cycles)
			"dec %1\n"			//decrement time_ms
			"brne L_dl1%=\n"
			: "=&w" (cnt) :  "r"(time_ms), "M"(DELAY_COUNT & 0xFF), "M"(DELAY_COUNT >> 8)
	);
}

------------------
Pripadne si delay_us zamente tuto "vytuningovanu", kde nie je vstupom
pocet us, ale priamo pocet loops. Na prepocet z mikrosekund mam potom
makro, ktorym v kode volam funkciu. Povodna delay_us robi velku chybu
prepoctu pri nizkej F_CPU, co je prirodzene...

do headra:
void delay_us_loops(WORD delay_loops);
//macro - input in microseconds
#define DELAY_US(time_us)
delay_us_loops((WORD)((double)(time_us)*(double)F_CPU/4000000.0))

telo:
void delay_us_loops(WORD delay_loops)
{
WORD dummy;
	// one loop takes 4 cpu cycles
	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) //& means usage of register only, not memory variable
                  :"r"((unsigned short) (delay_loops))
	);
}


miro

2010/8/4, Petr Toąovský <PetrTosHW na ptmodel.cz>:
> Aby toho nebylo malo, tak me zlobi debugovani v AVR studiu (posledni release
> s aktualnim WinAVR). Pri krokovani se pri prechodu na funkce z delay.h
> ztrati kurzor (PC registr odskoci nekam kde to IDE nemuze zobrazit v C
> kodu). Mel jsem za to ze to zpusobuji optimalizace, ale uz jsou vypnute a je
> to stejne. Jedinou vadu co jsem nasel, tak v disassemble okne je na radku s
> funkci z delay.h napsana cesta k souboru a za tim File not found, ale funkce
> se normalne vola a delka zpozdeni sedi ... takze jsem z toho mirne receno
> zmaten. Celkem mi to brani najit nejake nestandardni chovani viz prvni
> dotaz. Logicky analyzator budu mit az zitra.
> Pomuze mi nekdo z tohoto stavu ve kterem jsem se zasekl? :-)


More information about the Hw-list mailing list