51单片机定时器初值用变量设置定时不准确,为什么,求高手。TH0=(65536-X)/256,TL0=(65536-X)%256
晶振12MTH0=(65536-1000)%256;TL0=(65536-1000)%256;这种定时方式是准确的但是如果我用变量x=1000;TH0=(65536-x)...
晶振12M
TH0=(65536-1000)%256;
TL0=(65536-1000)%256;
这种定时方式是准确的
但是如果我用变量
x=1000;
TH0=(65536-x)%256;
TL0=(65536-x)%256;
定时时间就不对了,这是不是正常现象,还是我程序有问题,全部如下
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
uchar pwm;uint a,b,c,d;
sbit out=P0^0;
void main(void)
{
out=0;
pwm=50;
a=2000;
TMOD=0x11;
TH0=(65536-2000)/256;
TL0=(65536-2000)%256;
TH1=(65536-1000)/256;
TL1=(65536-1000)%256;
TR0=1;
TR1=0;
ET0=1;
ET1=1;
EA=1;
while(1);}
void timer0(void)interrupt 1
{
a=2000;
TR0=0;
TR1=0;
TH0=(65536-2000)/256; TL0=(65536-2000)%256;
TH1=(65536-1000)/256; TL1=(65536-1000)%256;
TR0=1;
TR1=1;
out=1;
}
void timer1(void)interrupt 3
{
TR1=0;
out=0;
} 展开
TH0=(65536-1000)%256;
TL0=(65536-1000)%256;
这种定时方式是准确的
但是如果我用变量
x=1000;
TH0=(65536-x)%256;
TL0=(65536-x)%256;
定时时间就不对了,这是不是正常现象,还是我程序有问题,全部如下
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
uchar pwm;uint a,b,c,d;
sbit out=P0^0;
void main(void)
{
out=0;
pwm=50;
a=2000;
TMOD=0x11;
TH0=(65536-2000)/256;
TL0=(65536-2000)%256;
TH1=(65536-1000)/256;
TL1=(65536-1000)%256;
TR0=1;
TR1=0;
ET0=1;
ET1=1;
EA=1;
while(1);}
void timer0(void)interrupt 1
{
a=2000;
TR0=0;
TR1=0;
TH0=(65536-2000)/256; TL0=(65536-2000)%256;
TH1=(65536-1000)/256; TL1=(65536-1000)%256;
TR0=1;
TR1=1;
out=1;
}
void timer1(void)interrupt 3
{
TR1=0;
out=0;
} 展开
5个回答
展开全部
看一下C代码编译后的汇编代码就知道了,用变量方式很耗时,而直接用数字,编译器已经将算式的值算好了,代码里就是一个MOV指令而已,只需1us!!!
TH0=(65536-2000)/256; TL0=(65536-2000)%256;
汇编后,只要2us就完事了。 而用变量方式,单片机很忙,计算几十乃至上百微妙才完事!
15: TH0=(65536-a)/256;
C:0x0190 AE09 MOV R6,a(0x09)
C:0x0192 AF0A MOV R7,0x0A
C:0x0194 AB07 MOV R3,0x07
C:0x0196 AA06 MOV R2,0x06
C:0x0198 E4 CLR A
C:0x0199 C3 CLR C
C:0x019A 9B SUBB A,R3
C:0x019B FF MOV R7,A
C:0x019C E4 CLR A
C:0x019D 9A SUBB A,R2
C:0x019E FE MOV R6,A
C:0x019F 7401 MOV A,#0x01
C:0x01A1 9400 SUBB A,#0x00
C:0x01A3 FD MOV R5,A
C:0x01A4 E4 CLR A
C:0x01A5 9400 SUBB A,#0x00
C:0x01A7 FC MOV R4,A
C:0x01A8 E4 CLR A
C:0x01A9 FB MOV R3,A
C:0x01AA 7A01 MOV R2,#0x01
C:0x01AC F9 MOV R1,A
C:0x01AD F8 MOV R0,A
C:0x01AE 1201EA LCALL C?SLDIV(C:01EA)
C:0x01B1 8F8C MOV TH0(0x8C),R7
16: TL0=(65536-a)%256;
C:0x01B3 AE09 MOV R6,a(0x09)
C:0x01B5 AF0A MOV R7,0x0A
C:0x01B7 AB07 MOV R3,0x07
C:0x01B9 AA06 MOV R2,0x06
C:0x01BB E4 CLR A
C:0x01BC C3 CLR C
C:0x01BD 9B SUBB A,R3
C:0x01BE FF MOV R7,A
C:0x01BF E4 CLR A
C:0x01C0 9A SUBB A,R2
C:0x01C1 FE MOV R6,A
C:0x01C2 7401 MOV A,#0x01
C:0x01C4 9400 SUBB A,#0x00
C:0x01C6 FD MOV R5,A
C:0x01C7 E4 CLR A
C:0x01C8 9400 SUBB A,#0x00
C:0x01CA FC MOV R4,A
C:0x01CB E4 CLR A
C:0x01CC FB MOV R3,A
C:0x01CD 7A01 MOV R2,#0x01
C:0x01CF F9 MOV R1,A
C:0x01D0 F8 MOV R0,A
C:0x01D1 1201EA LCALL C?SLDIV(C:01EA)
C:0x01D4 AF03 MOV R7,0x03
C:0x01D6 8F8A MOV TL0(0x8A),R7
17: TH1=(65536-1000)/256;
C:0x01D8 758DFC MOV TH1(0x8D),#0xFC
18: TL1=(65536-1000)%256;
C:0x01DB 758B18 MOV TL1(0x8B),#0x18
TH0=(65536-2000)/256; TL0=(65536-2000)%256;
汇编后,只要2us就完事了。 而用变量方式,单片机很忙,计算几十乃至上百微妙才完事!
15: TH0=(65536-a)/256;
C:0x0190 AE09 MOV R6,a(0x09)
C:0x0192 AF0A MOV R7,0x0A
C:0x0194 AB07 MOV R3,0x07
C:0x0196 AA06 MOV R2,0x06
C:0x0198 E4 CLR A
C:0x0199 C3 CLR C
C:0x019A 9B SUBB A,R3
C:0x019B FF MOV R7,A
C:0x019C E4 CLR A
C:0x019D 9A SUBB A,R2
C:0x019E FE MOV R6,A
C:0x019F 7401 MOV A,#0x01
C:0x01A1 9400 SUBB A,#0x00
C:0x01A3 FD MOV R5,A
C:0x01A4 E4 CLR A
C:0x01A5 9400 SUBB A,#0x00
C:0x01A7 FC MOV R4,A
C:0x01A8 E4 CLR A
C:0x01A9 FB MOV R3,A
C:0x01AA 7A01 MOV R2,#0x01
C:0x01AC F9 MOV R1,A
C:0x01AD F8 MOV R0,A
C:0x01AE 1201EA LCALL C?SLDIV(C:01EA)
C:0x01B1 8F8C MOV TH0(0x8C),R7
16: TL0=(65536-a)%256;
C:0x01B3 AE09 MOV R6,a(0x09)
C:0x01B5 AF0A MOV R7,0x0A
C:0x01B7 AB07 MOV R3,0x07
C:0x01B9 AA06 MOV R2,0x06
C:0x01BB E4 CLR A
C:0x01BC C3 CLR C
C:0x01BD 9B SUBB A,R3
C:0x01BE FF MOV R7,A
C:0x01BF E4 CLR A
C:0x01C0 9A SUBB A,R2
C:0x01C1 FE MOV R6,A
C:0x01C2 7401 MOV A,#0x01
C:0x01C4 9400 SUBB A,#0x00
C:0x01C6 FD MOV R5,A
C:0x01C7 E4 CLR A
C:0x01C8 9400 SUBB A,#0x00
C:0x01CA FC MOV R4,A
C:0x01CB E4 CLR A
C:0x01CC FB MOV R3,A
C:0x01CD 7A01 MOV R2,#0x01
C:0x01CF F9 MOV R1,A
C:0x01D0 F8 MOV R0,A
C:0x01D1 1201EA LCALL C?SLDIV(C:01EA)
C:0x01D4 AF03 MOV R7,0x03
C:0x01D6 8F8A MOV TL0(0x8A),R7
17: TH1=(65536-1000)/256;
C:0x01D8 758DFC MOV TH1(0x8D),#0xFC
18: TL1=(65536-1000)%256;
C:0x01DB 758B18 MOV TL1(0x8B),#0x18
展开全部
TL0=(65536-2000)%256和TL0=(65536-a)%256在编译之后的代码是完全不同的,TL0=(65536-2000)%256在编译之后的代码可能会是:MOV TL0,#30H。TL0=(65536-a)%256在编译之后,因为a是变量,所以会有一段两字节的减法运算代码,而且TH0=(65536-a)/256和TL0=(65536-a)%256还可能会计算两次。所以在执行的时候,时间差异会比较大。如果把a定义成一个宏,那就可以得到和前一种方式一样的结果,而且修改也很方便,缺点就是不能在程序执行过程中改变a的值
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
第一种用法是常用的用法,我刚看了一下你的程序,那个x在这个程序中可能就是那个a,a是uint,就是无符整型,而直接用1000,这个是int型,系统默认的,我感觉问题出在这,计算时出错。你可以把X设成int型,再试试!
追问
我把a类型定义成int之后,定时时间还是和uint一样……和直接带数字的偏差很大。求帮助啊
追答
你再试一些long int型
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
//工作频率12M,所以定时器脉冲频率为1M=1000000
#define F 12
#define IT0_Cost 11 // 定时器0中断平均花费时间11us
#define ONE_SECOND (F*1000000/12) // 机器周期
#define TIMES 50 // 50ms中断一次
#define oTH0 (65536-ONE_SECOND*TIMES/1000 + IT0_Cost) / 256
#define oTL0 (65536-ONE_SECOND*TIMES/1000 + IT0_Cost) % 256
#define F 12
#define IT0_Cost 11 // 定时器0中断平均花费时间11us
#define ONE_SECOND (F*1000000/12) // 机器周期
#define TIMES 50 // 50ms中断一次
#define oTH0 (65536-ONE_SECOND*TIMES/1000 + IT0_Cost) / 256
#define oTL0 (65536-ONE_SECOND*TIMES/1000 + IT0_Cost) % 256
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
TH0=(65536-1000)%256;
TL0=(65536-1000)%256;
这种定时方式是准确的
但是如果我用变量
x=1000;
TH0=(65536-x)%256;//高位
TL0=(65536-x)%256
确认对么?
TH0=(65536-x)/256;
TL0=(65536-1000)%256;
这种定时方式是准确的
但是如果我用变量
x=1000;
TH0=(65536-x)%256;//高位
TL0=(65536-x)%256
确认对么?
TH0=(65536-x)/256;
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询