用汇编吧.下面是我以前玩AVR时常用的.保存成M8_delay_110592.asm.(如果用8M,12M,16M等整数的晶体就更加精确)
/**************************************************
延时子程序
系统时钟=11.0592
使用R25(高):R24(低)传送参数
R25:R24内容不改变
**************************************************/
.DEF DELAY_L = R24
.DEF DELAY_H = R25
.DEF DELAY_TEMP = R16
/////////////////////////
//
// 1微秒
// 11.0592M
//
DELAY_1US:
RJMP DELAY_1US_NEXT1 //2时钟周期*2+7==11个时钟周期,运行时间约1us
DELAY_1US_NEXT1:
RJMP DELAY_1US_EXIT
DELAY_1US_EXIT:
RET
//////////////////////////////////////////
//
// 延时程序
// 延时量R25(高):R24(低)
// 最少延时3微秒,最多65535微秒(65.535毫秒)
// 系统时钟=11.0592M
//
DELAY_US:
PUSH DELAY_H
PUSH DELAY_L
PUSH DELAY_TEMP
IN DELAY_TEMP,SREG
PUSH DELAY_TEMP
SBIW DELAY_L,3
BRCS DELAY_US_EXIT0 //小于3退出
BREQ DELAY_US_EXIT1 //等于3退出
LDI DELAY_TEMP,17 //实际上是每16.89个偱环要加多一个NOP
DELAY_US_LOOP:
RJMP DELAY_US_NEXT0
DELAY_US_NEXT0:
DEC DELAY_TEMP
BRNE DELAY_US_LOOP_NEXT
RJMP DELAY_US_LOOP_NEXT //本来是两条NOP指令,但为了节省程序空间,改用一条RJMP指令(这条指令使用两个时钟周期,但只使用一个字的储存空间)
DELAY_US_LOOP_NEXT:
SBIW DELAY_L,1
RJMP DELAY_US_LOOP_NEXT1
DELAY_US_LOOP_NEXT1:
BRNE DELAY_US_LOOP
DELAY_US_EXIT0:
NOP
DELAY_US_EXIT1:
NOP
RJMP DELAY_US_NEXT1
DELAY_US_NEXT1:
RJMP DELAY_US_NEXT2
DELAY_US_NEXT2:
POP DELAY_TEMP
OUT SREG,DELAY_TEMP
POP DELAY_TEMP
POP DELAY_L
POP DELAY_H
RET
//////////////////////////////////////////////////
//
// 1毫秒
// 每次延时会增加25个时钟周期的损耗
// 使用R25:R24传送参数,返回时R25:R24中的值不变
//
DELAY_MS:
PUSH DELAY_H
PUSH DELAY_L
PUSH DELAY_TEMP
IN DELAY_TEMP,SREG
PUSH DELAY_TEMP
DELAY_MS_LOOP0:
PUSH DELAY_H
PUSH DELAY_L
RJMP DELAY_MS_NEXT1
DELAY_MS_NEXT1:
RJMP DELAY_MS_NEXT2
DELAY_MS_NEXT2:
RJMP DELAY_MS_NEXT3
DELAY_MS_NEXT3:
RJMP DELAY_MS_NEXT4 //这4个指令是为了产生8个时钟周期的损耗
DELAY_MS_NEXT4:
LDI DELAY_H,HIGH(1008)
LDI DELAY_L,LOW(1008)
RCALL DELAY_US
POP DELAY_L
POP DELAY_H
SBIW DELAY_L,1
BRNE DELAY_MS_LOOP0
POP DELAY_TEMP
OUT SREG,DELAY_TEMP
POP DELAY_TEMP
POP DELAY_L
POP DELAY_H
RET
/*********************************************************
以上延时程序共使用42个字(82字节)的程序储存空间
*********************************************************/