找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4161|回复: 4
收起左侧

单片机串口和定时器0冲突了怎么办?

[复制链接]
ID:584919 发表于 2019-7-16 10:33 | 显示全部楼层 |阅读模式
  1. #include <reg52.h>
  2. #include <intrins.h>
  3. #include <stdio.h>
  4. #define uint unsigned int
  5. #define uchar unsigned char

  6. sbit up = P1^0;
  7. sbit down = P1^1;
  8. sbit thousand = P2^0;    //数码管com与显示数组
  9. sbit hundred = P2^1;
  10. sbit tan = P2^2;
  11. sbit one = P2^3;

  12. uchar table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
  13. uint frequency;    //电机上下的次数,上升算一次,下降算一次
  14. uint num = 0;    //定时器计数

  15. void putin(uchar c)    ;     //串口输出
  16. void ddelay(uint z);     //设置一秒
  17. void show(uint z);         //数码管显示数字


  18. void main()
  19. {
  20.     uint q = 0;
  21.     frequency = 0;
  22.     up = 0;
  23.     down = 1;

  24.     TMOD = 0x21;    //定时器1方式2  定时器0方式1
  25.     TH0  = (65536-45872)/256; //装初值11.0592M晶振定时50ms数为45872
  26.     TL0  = (65536-45872)%256;   
  27.     TH1  = 0xf4;    //装载初值
  28.     TL1  = 0xf4;
  29.    
  30.     SCON = 0x50;    //串口方式1
  31.     PCON = 0x00;    //不倍增
  32.    
  33.     EA     = 1;        //打开全局中断
  34.     ES     = 1;        //打开串口中断
  35.     ET0  = 1;         //打开定时器0中断
  36.     TR0  = 1;        //打开定时器0,开始计时
  37.     TR1  = 1;        //打开定时器1,用于串口通信   

  38.     while(1)
  39.     {
  40.         if(num == 20) //如果到了20次,说明1秒时间
  41.         {
  42.             q++;         
  43.             num=0;
  44.         
  45.             if(q == 3) //每3秒串口发送数据
  46.             {
  47.                 up = ~up;        //指示灯
  48.                 down = ~down;
  49.                 frequency++;
  50.                 q = 0;            //重置时间
  51.                 putin(0xff);
  52.             }
  53.         }
  54.         putin(0xfe);
  55.         show(frequency);
  56.     }
  57. }



  58. void ddelay(uint z)  //设置一秒
  59. {

  60.     unsigned char h, i, j, k, l;

  61.     for (l = z; l > 0; l--)
  62.     for (h = 5; h > 0; h--)
  63.     for (i = 4; i > 0; i--)
  64.     for (j = 116; j > 0; j--)
  65.     for (k = 214; k > 0; k--);
  66. }

  67. void putin(uchar c)        //串口输出
  68. {
  69.      SBUF = c;
  70.     while(TI == 0);
  71.     TI = 0;
  72. }

  73. void show(uint z) //数码管显示数字
  74. {
  75.     uchar i,j,k,l;
  76.     i = z/1000;
  77.     j = (z%1000)/100;
  78.     k = (z%100)/10;
  79.     l = z%10;
  80.    
  81.     P0 = 0xff;
  82.     P0 = table[i];
  83.     thousand = 0;
  84.     thousand = 1;
  85.    
  86.     P0 = 0xff;
  87.     P0 = table[j];
  88.     hundred  = 0;
  89.     hundred  = 1;
  90.    
  91.     P0 = 0xff;
  92.     P0 = table[k];
  93.     tan = 0;
  94.     tan = 1;
  95.    
  96.     P0 = 0xff;
  97.     P0 = table[l];
  98.     one = 0;
  99.     one = 1;
  100. }

  101. void T0_time()interrupt 1    //定时器0中断
  102. {
  103.     TH0=(65536-45872)/256; //重新装载初值
  104.     TL0=(65536-45872)%256;
  105.     num++;
  106. }
复制代码
回复

使用道具 举报

ID:123289 发表于 2019-7-16 13:41 | 显示全部楼层
T0中断优串口中断,串口中断时间间隔是一个字节的串转并时间,相对来说是较长的。只有T0的中断服务程序运行时间,小于串口的“一个字节的串转并时间”,串口是不会丢数据的。
解决的方案是:
两种中断的服务程序尽可能用时少。
回复

使用道具 举报

ID:7485 发表于 2019-7-16 17:40 | 显示全部楼层
串口别用循环等待,也用中断方式。如果一个字节还没发送或接收完,这时产生了定时器中断,有可能会影响到串口发送和接收。需要根据需要设置中断优先权。

11.0592的晶振的初装值不对啊应该是65536-46080    就是(11.0592/12)*50000=46080
回复

使用道具 举报

ID:585414 发表于 2019-7-16 21:59 | 显示全部楼层
可以在进入串口的子程里面把总中断给关了,快出去了再开,被定时器打断会出好多乱码
回复

使用道具 举报

ID:123289 发表于 2019-7-17 10:43 | 显示全部楼层
地板的方式是错误的,沙发OK。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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