|
Keil下初次玩AT89C51,被定时器搞吐血了!特来求救!
[复制链接]
原本用循环延时,见下帖子:
http://topic.eeworld.net/u/20080113/22/a42c9278-e38d-4d0f-af0b-b7834b301f40.html
后来发现C编译后的循环不是精确到时钟周期的。于是改用定时器(代码如下)。
据说89C51定时器是1/12分频的,应该是1us一个记数,1ms理应是1000次记数(定时器初始值65536-1000=64536)。
可实际把程序写出来Keil下仿真发现明显过快。后来把中断记数周期改成12000次,才够1ms,彻底吐血。
由于手头没有仿真器和单片机,程序只在Keil下软件仿真,实在不知道究竟怎么回事,特来求救。
谁能帮我搞清楚这个问题,此帖及上面那帖子总共200分全给他。最好哪位老兄有单片机实际帮我测试一下。
此程序应该是以500ms的间隔依次点亮连接在P1、P2的16盏灯。
- #include
- //
- unsigned int pubTimerInt;
- unsigned int pubTimerValue;
- void SetTimerout(unsigned int pTimeout)
- {
- EA=1;
- ET0=1;
- TMOD=0x01;
- pubTimerValue=65535-pTimeout;
- TH0=pubTimerValue/256;
- TL0=pubTimerValue%256;
- TR0=1;
- }
- void intserv1(void) interrupt 1 using 1
- {
- if (pubTimerInt>0)
- {
- pubTimerInt=pubTimerInt-1;
- }
- TH0=pubTimerValue/256;
- TL0=pubTimerValue%256;
- }
- void WhileTimeout(unsigned int pTimeout)
- //WhileTimeout函数
- //语法:WhileTimeout(pTimeout);
- //说明:产生pTimeout指定延时,单位为ms。
- //参数:unsigned int pTimeout 单位为ms的延时参数。
- {
- TR0=1;
- TH0=pubTimerValue/256;
- TL0=pubTimerValue%256;
- pubTimerInt=pTimeout;
- TR0=1;
- while(pubTimerInt)
- {
- }
- }
- void ProtDevice_LO(unsigned char pConByte, unsigned char pProt)
- //ProtDevice函数
- //语法:ProtDevice(pConByte, pProt);
- //说明:驱动端口(低电平开启)。
- //参数:unsigned char pConByte 端口控制字节(高电平开启)。
- // unsigned char pProt 端口选择(0-3)
- {
- switch(pProt)
- {
- case 0: P0=~pConByte;break;
- case 1: P1=~pConByte;break;
- case 2: P2=~pConByte;break;
- case 3: P3=~pConByte;break;
- }
- }
- void LoopOpen_LO(unsigned int pOpenTimeout, unsigned char pProt)
- //LoopOpen_LO函数
- //语法:LoopOpen_LO(pOpenTimeout, pProt);
- //说明:循环驱动端口(低电平开启)。
- //参数:unsigned int pOpenTimeout 开启时间设置(单位ms)
- // unsigned char pProt 端口选择(0-3)
- {
- unsigned char tConByte;
- unsigned int tLoopIndex;
- unsigned int tLoopIndex_Length;
- tLoopIndex_Length=7;
- //开关0号。
- tConByte=1;
- ProtDevice_LO(tConByte, pProt); //驱动端口
- WhileTimeout(pOpenTimeout);
- //开关1-7号。
- for (tLoopIndex=0; tLoopIndex
- {
- tConByte=tConByte<<1;
- ProtDevice_LO(tConByte, pProt); //驱动端口
- WhileTimeout(pOpenTimeout);
- }
- }
- void main()
- {
- unsigned char tProtA;
- unsigned char tProtB;
- unsigned char tConByte;
- unsigned int tOpenTimeout;
- unsigned int tWhileTimeout;
- unsigned int tTimeoutValue;
- tProtA=1;
- tProtB=2;
- tOpenTimeout=500;
- tWhileTimeout=3000;
- tTimeoutValue=12000; //按道理应该是1000us=1ms,可这里一定要设置12000才能保证中断是1ms。
- tConByte=0;
- ProtDevice_LO(tConByte, tProtA);
- ProtDevice_LO(tConByte, tProtB);
- SetTimerout(tTimeoutValue);
- while(1)
- {
- //第一端口
- LoopOpen_LO(tOpenTimeout, tProtA);
- tConByte=0;
- ProtDevice_LO(tConByte, tProtA);
- //第二端口
- LoopOpen_LO(tOpenTimeout, tProtB);
- tConByte=0;
- ProtDevice_LO(tConByte, tProtB);
- //等待
- WhileTimeout(tWhileTimeout);
- }
- }
复制代码
编译后的HEX文件内容:
:1000E200D2AFD2A9758901C374FF9FF51274FF9E26
:0A00F200F511F58C85128AD28C22DC
:03000B0002009D53
:10009D00C0E0C0D0D3E5149400E51394004008E50A
:1000AD0014151470021513E511F58C85128AD0D034
:0300BD00D0E0325E
:1000FC00AD07AC06D28CE511F58C85128A8C138D6C
:0A010C0014D28CE514451370FA229A
:1000C000ED14600F14601114601324037013EFF427
:1000D000F58022EFF4F59022EFF4F5A022EFF4F58D
:0200E000B0224C
:060062008D0EAB07AA069B
:10006800750F0075100779017F011200C0AF0312E8
:1000780000FC900000C3E5829510E583950F5014AD
:10008800E925E0F9FFAD0E1200C0AF03AE02120081
:04009800FCA380E164
:01009C002241
:10000E00750801750902750A01750BF4750C0B75EF
:10001E000DB87BE07A2EE4F9FFAD081200C0AD09F1
:10002E001200C07FE07E2E1200E2AD08AF0BAE0ACA
:10003E00120062E4F9FFAD081200C0AD09AF0BAEBD
:10004E000A120062E4FFAD091200C0AF0DAE0C1231
:04005E0000FC80D64C
:03000000020116E4
:0C011600787FE4F6D8FD75811402000E1D
:00000001FF
|
|