找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2184|回复: 5
收起左侧

51单片机判断低电平持续时间请问我的源码哪里出错了?

[复制链接]
ID:718523 发表于 2020-5-29 00:47 | 显示全部楼层 |阅读模式
下面的代码运行的结果是LED错乱,感觉每个灯的闪烁是随机的好像没有规律并不是按照我的代码执行的。我要的结果是低电平持续时间1秒时D3闪两下,持续时间是2秒时D2闪两下,持续时间是3秒时D1闪两下。大佬帮我看下吧。

单片机源程序如下:
  1. #include<reg51.h>  //  包含51单片机寄存器定义的头文件
  2. #define uint unsigned int //unsigned是无符号,int是整型。定义uint为无符号整型。
  3. unsigned char Countor; //设置全局变量,储存定时器T0中断次数
  4. sbit D0=P1^0;
  5. sbit D1=P1^1;
  6. sbit D2=P1^2;
  7. sbit D3=P1^3;

  8. /**************************************************************
  9. 函数功能:延时 delayms(1000); 1秒
  10. **************************************************************/
  11. void Delay1ms()                //@12.000MHz
  12. {
  13.         unsigned char i, j;

  14.         i = 2;
  15.         j = 239;
  16.         do
  17.         {
  18.                 while (--j);
  19.         } while (--i);
  20. }

  21. void delayms(uint x)
  22. {
  23.         while(x--)Delay1ms();
  24. }

  25. /**************************************************************
  26. 函数功能:主程序
  27. **************************************************************/
  28. void main(void){
  29.         while(1){
  30.         while(D0==0);//等待眼前的低电平过去
  31.         while(D0==1);//等待下一个低电平来到
  32.                 if(D0 == 0){
  33.             EA=1;                  //开总中断
  34.                 ET0=1;                 //定时器T0中断允许         
  35.                 TMOD=0x01;             //使用定时器T0的模式2
  36.                 TH0=(65536-46083)/256; //定时器T0的高8位赋初值
  37.                 TL0=(65536-46083)%256; //定时器T0的高8位赋初值
  38.                 TR0=1;                 //启动定时器T0
  39.                 Countor=0;            //从0开始累计中断次数
  40.                 //while(D0-1);//无限循环等待中断
  41.                 while(D0==0);//等待低电平结束
  42.                 TR0=0;//关闭定时器                                 
  43.                 //T=N*65536+TH0*256+TL0; //N是定时器溢出次数

  44. if(Countor>=60)  //若累计满20次,即计时满1s
  45. {
  46.         D1=0;delayms(1000);D1=1;delayms(1000);D1=0;delayms(1000);D1=1;
  47.         Countor=0;  //将Countor清0,重新从0开始计数
  48.         
  49. }
  50. if(Countor>=40)  //若累计满20次,即计时满1s
  51. {
  52.         D2=0;delayms(1000);D2=1;delayms(1000);D2=0;delayms(1000);D2=1;
  53.         Countor=0;  //将Countor清0,重新从0开始计数
  54. }
  55. if(Countor>=20)  //若累计满20次,即计时满1s
  56. {
  57.         D3=0;delayms(1000);D3=1;delayms(1000);D3=0;delayms(1000);D3=1;
  58.         Countor=0;  //将Countor清0,重新从0开始计数
  59. }


  60.                                    }
  61.          }
  62.       
  63. }


  64. /**************************************************************
  65. 函数功能:定时器T0的中断服务程序
  66. **************************************************************/
  67. void Time0(void) interrupt 1 using 0 //“interrupt”声明函数为中断服务函数
  68.                  //其后的1为定时器T0的中断编号;0表示使用第0组工作寄存器
  69. {
  70.    Countor++;   //中断次数自加1               
  71.           TH0=(65536-46083)/256; //定时器T0的高8位重新赋初值
  72.         TL0=(65536-46083)%256; //定时器T0的高8位重新赋初值
  73. }
复制代码



回复

使用道具 举报

ID:660091 发表于 2020-5-29 09:14 | 显示全部楼层
首先,你把初始化这些也放到while(1)里面去了
其次, Countor>20时就执行第三个if(这个if里面把 Countor清零了),也就是前两个if永远无法执行,
回复

使用道具 举报

ID:476599 发表于 2020-5-29 09:26 | 显示全部楼层
你这个不管按下几秒都是闪2下?感觉没看明白,都是闪2下要区分吗?
回复

使用道具 举报

ID:389856 发表于 2020-5-29 10:56 | 显示全部楼层
本帖最后由 墨栀 于 2020-5-29 13:00 编辑

定时器工作方式2只有低八位参与计数,高八位存的是预置值,而且一般定时器计数器都会用工作方式1,方式2用于波特率发生器
回复

使用道具 举报

ID:389856 发表于 2020-5-29 11:09 | 显示全部楼层
发现你的程序逻辑是先等待当前低电平过去,再对下一个低电平计时,计时完循环,如果判断D0的时候是低电平,那就要等待这一个低电平过去,再对下个低电平计时。这种情况如果你的D0输入不是一个高低电平时间等长的信号,那就很可能出现乱闪的情况了
回复

使用道具 举报

ID:401564 发表于 2020-5-29 19:15 | 显示全部楼层
STC的51单片机都有设定成上升沿和下降沿中断的
1:你把外部中断设定成下降沿和上升沿中断
2:进入中断之后先判断触发中断的引脚电平:高电平就是上升沿触发,低电平就是上升沿触发
3:如果是低电平就开始计时,可以使用定时器,如果是高电平就停止计时,然后退出中断
这不就完事了吗?
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表