找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 7317|回复: 8
打印 上一主题 下一主题
收起左侧

51单片机 外部中断 定时器0 定时器1 三个无法正常工作

[复制链接]
跳转到指定楼层
楼主
ID:251195 发表于 2018-5-6 01:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
50黑币
  1. /*预处理命令*/
  2. #include<reg52.h>    //包含单片机寄存器的头文件
  3. #include<intrins.h> //包含_nop_()函数定义的头文件
  4. #define uchar unsigned char
  5. #define uint  unsigned int
  6. #define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};

  7. sbit LED1 = P1^0;      //定义LED灯,通过LED显示调光效果
  8. sbit LED2 = P1^1;           //用来对比PWM
  9. sbit LED3 = P1^2;

  10. sbit IRIN= P3^2;         //红外接收器数据线

  11. sbit rs=P0^7;
  12. sbit rw=P0^6;
  13. sbit lcden=P0^5;

  14. unsigned char time;  //定义周期 该数字X基准定时时间 如果是10 则占空比是10 x 0.01ms /1ms

  15. void delay(unsigned char x) ;
  16. void delay_ms(uint z);

  17. char code dis []={"Countdown set:"};

  18. uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,
  19.                         0xf8,0x80,0x90};
  20. uchar IRCOM[7];
  21. uchar count,aa,sec=59,min,hour,ss,sg,ms,mg,hs,hg;

  22. //以下是1602程序
  23. void write_com(uchar com)
  24. {
  25.         rs=0;
  26.         lcden=0;
  27.         P2=com;
  28.         delay_ms(5);
  29.         lcden=1;
  30.         delay_ms(5);
  31.         lcden=0;        
  32. }

  33. void write_date(uchar date)
  34. {
  35.         rs=1;
  36.         lcden=0;
  37.         P2=date;
  38.         delay_ms(5);
  39.         lcden=1;
  40.         delay_ms(5);
  41.         lcden=0;        
  42. }

  43. void lcd_init()
  44. {
  45.         rw=0;
  46.         lcden=0;
  47.         write_com(0x38);
  48.         write_com(0x0c);
  49.         write_com(0x06);
  50.         write_com(0x01);        
  51. }
  52. void write_fm(uchar add,uchar data1,uchar data2)
  53. {        
  54.         write_com(0x80+0x40+add);
  55.         write_date(0x30+data1);
  56.         write_date(0x30+data2);
  57. }



  58. //1602程序到此结束

  59. void Countup()                           //设置关断时间
  60. {
  61.         if(min == 60)
  62.         {
  63.                 min = 0;
  64.                 hour++;
  65.                 if(hour == 24)
  66.                 {
  67.                         hour =0;
  68.                 }
  69.         }
  70. }

  71. void init()
  72. {

  73.   IRIN=1;                    //红外接收器数据初始化为高电平        
  74.         EX0 = 1;                  //使能 INT0 外部中断
  75.         IT0 = 1;               //触发方式为脉冲负边沿触发   相当于IT0=1;
  76.         
  77.         TMOD =0x11;              //定时器设置 0.01ms in 12M crystal
  78.         TH0=0xff;
  79.         TL0=0xa4;      //定时器0定时0.01mS
  80.          
  81.         TH1 = (65535-50000)/256;
  82.         TL1 = (65535-50000)%256;         //定时器1定时50mS

  83.         ET0 = 1;
  84.         ET1 = 1;                                 //开启定时器中断

  85.         TR0 = 1;
  86.         TR1 = 0;            //定时器1暂不开启
  87.         EA =1;              //允许总中断中断,

  88. }
  89. /*******************************************************************/
  90. void main()
  91. {
  92.     char i;
  93.         time = 10;               // 时间可以调整 这个是10调整 8位PWM就是256步
  94.         init();
  95.         lcd_init();
  96.         write_com(0x80);         //显示初始界面
  97.         i=0;
  98.         while (dis [i]!='\0')
  99.         {
  100.                 write_date(dis [i]);
  101.                 i++;        
  102.         }

  103.         write_fm(4,hs,hg);                //显示初始时间
  104.         write_date(':');
  105.         write_fm(7,ms,mg);
  106.         write_date(':');
  107.         write_fm(10,ss,sg);
  108.         
  109.         while(!TR1);        //等待红外启动
  110.         
  111.         while(TR1)
  112.         {
  113.                 write_fm(0,IRCOM[5],IRCOM[6]);                //显示红外键值
  114.                 Countup();
  115.                 ss = sec/10;
  116.                 sg = sec%10;
  117.                 ms = min/10;
  118.                 mg = min%10;
  119.                 hs = hour/10;
  120.                 hg = hour%10;                           
  121.                 write_fm(4,hs,hg);
  122.                 write_date(':');
  123.                 write_fm(7,ms,mg);
  124.                 write_date(':');
  125.                 write_fm(10,ss,sg);                   //1602显示时间00:00:59
  126.                 if(sec == 0 && min == 0 && hour == 0)
  127.                         {        
  128.                                 TR1 = 0;                        //停止计时
  129.                                 LED1 = 1;           //PWM灯关闭
  130.                         }

  131.         }

  132. }
  133. /**********************************************************/
  134. void IR_IN() interrupt 0 using 0                                 //外部中断触发,接收到红外信号
  135. {
  136.         unsigned char j,k,N=0;
  137.         unsigned char q=0;
  138.         EX0 = 0;   
  139.         delay(15);
  140.         if (IRIN==1)
  141.         {
  142.                 EX0 =1;
  143.                 return;
  144.         }
  145.                    //确认IR信号出现
  146.         while (!IRIN)            //等IR变为高电平,跳过9ms的前导低电平信号。
  147.                 delay(1);
  148.         
  149.         for (j=0;j<4;j++)         //收集四组数据
  150.         {
  151.                 for (k=0;k<8;k++)        //每组数据有8位
  152.                 {
  153.                         while (IRIN)            //等 IR 变为低电平,跳过4.5ms的前导高电平信号。
  154.                         {delay(1);}
  155.                         while (!IRIN)          //等 IR 变为高电平
  156.                                 delay(1);
  157.                         while (IRIN)           //计算IR高电平时长
  158.                         {
  159.                                 delay(1);
  160.                                 N++;           
  161.                                 if (N>=30)                                  //超时数据接收完毕
  162.                                 {
  163.                                         EX0=1;
  164.                                         return;
  165.                                 }                  //0.14ms计数过长自动离开。
  166.                         }                        //高电平计数完毕               
  167.                         IRCOM[j]=IRCOM[j] >> 1;     //数据最高位补“0”           位操作
  168.                         if(N>=8)
  169.                         {
  170.                                 IRCOM[j] = IRCOM[j] | 0x80;                  //数据最高位补“1”
  171.                         }  
  172.                         N=0;
  173.                 }
  174.         }
  175.         
  176.         if(IRCOM[2]!=~IRCOM[3])
  177.         {
  178.                 EX0=1;
  179.                 return;
  180.         }
  181.         
  182.         IRCOM[5]=IRCOM[2] & 0x0F;     //取键码的低四位
  183.         IRCOM[6]=IRCOM[2] >> 4;       //右移4次,高四位变为低四位
  184.         
  185.         if(IRCOM[5]>9)
  186.         {
  187.                 IRCOM[5]=IRCOM[5]+0x37;
  188.         }
  189.         else
  190.         IRCOM[5]=IRCOM[5]+0x30;
  191.         
  192.         if(IRCOM[6]>9)
  193.         {
  194.                 IRCOM[6]=IRCOM[6]+0x37;
  195.         }
  196.         else
  197.         IRCOM[6]=IRCOM[6]+0x30;

  198.         q= (((IRCOM[6]&0x0f)<<4) + (IRCOM[5]&0x0f));

  199.         

  200.         switch(q)    //判断按键键码值
  201.         {
  202.                 case 0x16:
  203.                         time = 99;break; //串口发送0
  204.                 case 0x03:
  205.                         time = 10;break;  //串口发送01
  206.                 case 0x18:
  207.                         min = min+2;break;  //串口发送02           设置关断时间
  208.                 case 0x55:
  209.                         time = 30;break;  //串口发送03
  210.                 case 0x08:
  211.                         ET1=1;TR1=1;break;  //串口发送04                        计时开始
  212.                 case 0x13:
  213.                         time = 50;break;  //串口发送05
  214.                 case 0x51:
  215.                         LED1 = 1;break;  //串口发送06                         关断LED1;
  216.                 case 0x42:
  217.                         time = 70;break;  //串口发送07
  218.                 case 0x52:
  219.                         LED1 = 0;break;  //串口发送08      开启LED1
  220.                 case 0x41:
  221.                         time = 90;break;  //串口发送09
  222.         
  223.                 default :
  224.                         break;
  225.         }

  226.          EX0 = 1;
  227. }


  228. //定时器0中断函数
  229. void tim0(void) interrupt 1 using 1
  230. {               
  231.         TH0=0xff;
  232.         TL0=0xa4;     //设置中断时间0.01mS
  233.         count++;
  234.         if(count<=time)
  235.         {
  236.                 LED1 = 0;
  237.         }
  238.         else
  239.         {
  240.                 LED1 =1;
  241.         }
  242.         if(count>=100)  //周期1ms
  243.         {
  244.                 count =0;
  245.         }
  246. }

  247. void timer3() interrupt 3 using 3
  248. {
  249.         TH1 = (65535-50000)/256;
  250.         TL1 = (65535-50000)%256;
  251.         aa++;

  252.         if(aa == 20)
  253.         {
  254.                 aa = 0;
  255.                 sec--;
  256.                 if(sec == 0)
  257.                 {
  258.                         sec = 59;
  259.                         min--;
  260.                         if(min == 0)
  261.                         {
  262.                            min  = 59;
  263.                            hour--;
  264.                            if(hour == 0)
  265.                            {
  266.                                            hour =0;
  267.                            }
  268.                         }
  269.                 }
  270.         }
  271. }
  272. /***************延时函数*****************************/
  273. void delay(unsigned char x)    //x*0.14MS
  274. {
  275.         unsigned char i;
  276.         while(x--)
  277.         {
  278.                 for (i = 0; i<13; i++) {}
  279.         }
  280. }



  281. void delay_ms(uint z)
  282. {
  283.         uint x,y;
  284.         for(x=z;x>0;x--)
  285.                 for(y=110;y>0;y--);
  286. }

复制代码

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:251195 发表于 2018-5-6 01:02 | 只看该作者
我在想是不是中断里面写太多内容了
回复

使用道具 举报

板凳
ID:155507 发表于 2018-5-6 07:33 | 只看该作者
你关闭中断比较长。

中断响应时间越短,实时性就越好。
如果我们关中断,那么所有类型的中断不论什么条件和时间都不会进入它自己的中断程序去执行工作了。

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

地板
ID:319344 发表于 2018-5-6 08:02 | 只看该作者
虽然还没看太懂,不过还是觉得发现了一些问题,外部中断服务函数使用的工作组0,别用0,0是程序不在中断服务函数里执行时用的,改为1或2,还有两个定时器的优先级如果不设置的话有一个默认的,那个是不是满足你的要求?

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

5#
ID:319344 发表于 2018-5-6 08:23 | 只看该作者
你的程序想实现的是开始时等待红外启动定时器1,启动后,1602会显示59秒,由于启动了计时,当减到0后灯就灭了,也可以设置延迟两分钟灭,对吧?我觉得你那不是PWM,就是一个周期性闪烁的灯

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

6#
ID:323222 发表于 2018-5-6 08:36 | 只看该作者
这个是不是定时器没有开
回复

使用道具 举报

7#
ID:323183 发表于 2018-5-6 09:20 | 只看该作者
中断里做得东西太多了,或是卡在那个地方死循环了

评分

参与人数 1黑币 +60 收起 理由
admin + 60 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

8#
ID:251195 发表于 2018-5-7 15:46 | 只看该作者
wenzedong 发表于 2018-5-6 08:23
你的程序想实现的是开始时等待红外启动定时器1,启动后,1602会显示59秒,由于启动了计时,当减到0后灯就灭 ...

我没有启动之前,是可以对PWM灯的亮度进行设置变化的,定义的那个59秒 我只是想测试一下,定时关断PWM灯
回复

使用道具 举报

9#
ID:251195 发表于 2018-5-7 15:48 | 只看该作者
angmall 发表于 2018-5-6 07:33
你关闭中断比较长。

中断响应时间越短,实时性就越好。

我关断的是某一个功能的中断,这样会影响其他功能中断吗?比如说我关闭外部中断0 EX0 = 0;这样会影响定时器0、1的中断程序执行?
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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