7417|22

85

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

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盏灯。


  1. #include

  2. //
  3. unsigned int pubTimerInt;
  4. unsigned int pubTimerValue;

  5. void SetTimerout(unsigned int pTimeout)
  6. {
  7.   EA=1;
  8.   ET0=1;
  9.   TMOD=0x01;
  10.   pubTimerValue=65535-pTimeout;
  11.   TH0=pubTimerValue/256;
  12.   TL0=pubTimerValue%256;
  13.   TR0=1;
  14. }

  15. void intserv1(void) interrupt 1 using 1
  16. {
  17.   if (pubTimerInt>0)
  18.   {
  19.     pubTimerInt=pubTimerInt-1;
  20.   }
  21.   TH0=pubTimerValue/256;
  22.   TL0=pubTimerValue%256;  
  23. }

  24. void WhileTimeout(unsigned int pTimeout)
  25. //WhileTimeout函数
  26. //语法:WhileTimeout(pTimeout);
  27. //说明:产生pTimeout指定延时,单位为ms。
  28. //参数:unsigned int pTimeout        单位为ms的延时参数。
  29. {
  30.   TR0=1;
  31.   TH0=pubTimerValue/256;
  32.   TL0=pubTimerValue%256;  
  33.   pubTimerInt=pTimeout;
  34.   TR0=1;
  35.   while(pubTimerInt)
  36.   {
  37.   }
  38. }

  39. void ProtDevice_LO(unsigned char pConByte, unsigned char pProt)
  40. //ProtDevice函数
  41. //语法:ProtDevice(pConByte, pProt);
  42. //说明:驱动端口(低电平开启)。
  43. //参数:unsigned char pConByte                端口控制字节(高电平开启)。
  44. //                unsigned char pProt                        端口选择(0-3)
  45. {
  46.   switch(pProt)
  47.   {
  48.     case 0: P0=~pConByte;break;
  49.     case 1: P1=~pConByte;break;
  50.     case 2: P2=~pConByte;break;
  51.     case 3: P3=~pConByte;break;
  52.   }
  53. }

  54. void LoopOpen_LO(unsigned int pOpenTimeout, unsigned char pProt)
  55. //LoopOpen_LO函数
  56. //语法:LoopOpen_LO(pOpenTimeout, pProt);
  57. //说明:循环驱动端口(低电平开启)。
  58. //参数:unsigned int pOpenTimeout        开启时间设置(单位ms)
  59. //                unsigned char pProt                        端口选择(0-3)
  60. {
  61.   unsigned char tConByte;
  62.   unsigned int tLoopIndex;
  63.   unsigned int tLoopIndex_Length;

  64.   tLoopIndex_Length=7;

  65.   //开关0号。
  66.   tConByte=1;
  67.   ProtDevice_LO(tConByte, pProt);        //驱动端口
  68.   WhileTimeout(pOpenTimeout);

  69.   //开关1-7号。
  70.   for (tLoopIndex=0; tLoopIndex
  71.   {
  72.     tConByte=tConByte<<1;
  73.     ProtDevice_LO(tConByte, pProt);        //驱动端口
  74.     WhileTimeout(pOpenTimeout);
  75.   }
  76. }

  77. void main()
  78. {

  79.   unsigned char tProtA;
  80.   unsigned char tProtB;
  81.   unsigned char tConByte;
  82.   unsigned int tOpenTimeout;
  83.   unsigned int tWhileTimeout;
  84.   unsigned int tTimeoutValue;
  85.   tProtA=1;
  86.   tProtB=2;
  87.   tOpenTimeout=500;
  88.   tWhileTimeout=3000;
  89.   tTimeoutValue=12000;  //按道理应该是1000us=1ms,可这里一定要设置12000才能保证中断是1ms。
  90.   tConByte=0;
  91.   ProtDevice_LO(tConByte, tProtA);
  92.   ProtDevice_LO(tConByte, tProtB);
  93.   SetTimerout(tTimeoutValue);
  94.   while(1)
  95.   {
  96.         //第一端口
  97.         LoopOpen_LO(tOpenTimeout, tProtA);
  98.         tConByte=0;
  99.     ProtDevice_LO(tConByte, tProtA);
  100.     //第二端口
  101.     LoopOpen_LO(tOpenTimeout, tProtB);
  102.         tConByte=0;
  103.     ProtDevice_LO(tConByte, tProtB);
  104.         //等待
  105.     WhileTimeout(tWhileTimeout);
  106.   }
  107. }
复制代码


编译后的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

最新回复

哦也!   详情 回复 发表于 2008-1-23 16:10
点赞 关注

回复
举报

75

帖子

0

TA的资源

一粒金砂(初级)

沙发
 
有处理中断的时间在内,
所以实际计数值是调整的。

中断记数周期改成12000次,才够1ms,那么就用12000。
 
 

回复

76

帖子

0

TA的资源

一粒金砂(初级)

板凳
 
晶体频率注意看看。
 
 
 

回复

66

帖子

0

TA的资源

一粒金砂(初级)

4
 
呵呵,小仙妹 您好,你是搞单片机的吗?总在水源听说您的大名,从来为得一见,呵呵
 
 
 

回复

73

帖子

0

TA的资源

一粒金砂(初级)

5
 

LZ来看看我前几天转载的一个帖子,希望对你有帮助
  http://topic.eeworld.net/u/20080110/11/6be2a051-b997-4d78-a9bd-3957fdf86414.html
 
 
 

回复

75

帖子

0

TA的资源

一粒金砂(初级)

6
 

LZ来看看我前几天转载的一个帖子,希望对你有帮助
  http://topic.eeworld.net/u/20080110/11/6be2a051-b997-4d78-a9bd-3957fdf86414.html
 
 
 

回复

83

帖子

0

TA的资源

一粒金砂(初级)

7
 
80C51单片机的1个机器周期有12个振荡周期组成。12MHZ,它的时钟周期是1/12us。

当80C5l内部的定时器/计数器被选定为定时器工作模式时,计数输入信号是内部时钟脉冲,每个机器周期产生一个脉冲位,计数器增l,因此定时器/计数器的输入脉冲的周期与机器周期一样,为时钟振荡频率的l/12。当采用12MHz频率的晶体时,计数速率为 1MHz,输入脉冲的周期间隔为1us。

  1. void SetTimerout(unsigned int pTimeout)
  2. {
  3.   EA=1;
  4.   ET0=1;   /*设置T0为定时方式1*/
  5.   TMOD=0x01;
  6.   pubTimerValue=65535-pTimeout;
  7.   TH0=pubTimerValue/256;
  8.   TL0=pubTimerValue%256;
  9.   TR0=1;
  10. }
  11. /*上面正常。*/
  12. void intserv1(void) interrupt 1 using 1
  13. {
  14.   if (pubTimerInt>0)
  15.   {
  16.     pubTimerInt=pubTimerInt-1;
  17.   }
  18.   TH0=pubTimerValue/256;
  19.   TL0=pubTimerValue%256;  
  20.   
  21. [color=#FF0000]TF1=0;    [/color]               /*计数溢出标志位清0*,这个漏了!/
  22. }
复制代码


 
 
 

回复

61

帖子

0

TA的资源

一粒金砂(初级)

8
 
  1. void intserv1(void) interrupt 1 using 1
  2. {
  3.   if (pubTimerInt>0)
  4.   {
  5.     pubTimerInt=pubTimerInt-1;
  6.   }
  7.   TH0=pubTimerValue/256;
  8.   TL0=pubTimerValue%256;  
  9. [color=#FF0000]TF01=0;   [/color]                               /*漏了这个--计数溢出标志位清0*/
  10. }
复制代码
 
 
 

回复

84

帖子

0

TA的资源

一粒金砂(初级)

9
 
晕,是TF0=0
 
 
 

回复

70

帖子

0

TA的资源

一粒金砂(初级)

10
 
TF0响应后自动清0的,因此在中断处理程序里TF0总是0。加上TF0=0还是一样飞快。
我手头没有仿真器和单片机,所以上述结果是在Keil里测试发现的。还不知道真正烧到片里什么样子。
计数器周期从1000改成12000是我猜的(因为我感觉它的速度是12倍),于是我把计数器周期改成12000之后,将定时脉冲从500改成1000,发现刚好是一秒。也就是说12000次计数才是1秒。似乎压根就没有1/12分频。彻底精神崩溃了。
 
 
 

回复

67

帖子

0

TA的资源

一粒金砂(初级)

11
 
根你试验了,你的程序没问题,是keil仿真出了问题
 
 
 

回复

74

帖子

0

TA的资源

一粒金砂(初级)

12
 
根你试验了,你的程序没问题,是keil仿真出了问题
===========================================
谢谢!等我过几天单片机弄来,测试通过就给大家放分!
 
 
 

回复

79

帖子

0

TA的资源

一粒金砂(中级)

13
 
根你试验了,你的程序没问题,是keil仿真出了问题
===========================================
试验的时候main函数的tTimeoutValue=12000是否改成了tTimeoutValue=1000呢?
我自己编译的HEX是12000的设置,这在仿真时是正常的,但理论上不对。
应当改成1000后保持0.5s滚动才对。

不过现在看来keil仿真的速度真的有点不大对头。
 
 
 

回复

71

帖子

0

TA的资源

一粒金砂(初级)

14
 
keil仿真,keil里面选的什么类型的芯片?
有的厂家的51的是单周期的。
 
 
 

回复

90

帖子

0

TA的资源

一粒金砂(初级)

15
 
AT89LP2052,AT89LP4052就是单周期高速低功耗51内核单片机
 
 
 

回复

88

帖子

0

TA的资源

一粒金砂(初级)

16
 
我选的是AT89C51。
 
 
 

回复

73

帖子

0

TA的资源

一粒金砂(初级)

17
 
哈哈!今天我用面包板把单片机搭出来了,实验成功了!果然烧到AT89C51上是0.5s,而不是仿真时候那么快。

感谢MBWQ、zhujinqiang、yanglin5131421三位。请你们同时到下面帖子里接另外的100分。

http://topic.eeworld.net/u/20080113/22/a42c9278-e38d-4d0f-af0b-b7834b301f40.html
 
 
 

回复

85

帖子

0

TA的资源

一粒金砂(初级)

18
 
不会结贴?
呵呵,

方法:
管理帖子--> 输入密码(1楼右上角)--> 给各人分--> 结贴(1楼右上角)
 
 
 

回复

69

帖子

0

TA的资源

一粒金砂(初级)

19
 
不会结贴?
呵呵,

方法:
管理帖子-->   输入密码(1楼右上角)-->   给各人分-->   结贴(1楼右上角)
=====================================================================
没搞错吧!我会这么弱智吗?想催我结贴就明说嘛……
 
 
 

回复

47

帖子

0

TA的资源

一粒金砂(初级)

20
 
哈哈哈哈哈

小仙妹怎么说也是水源一大镁铝哈

嘿嘿嘿

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表