找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1066|回复: 1
收起左侧

单片机自行车码表+PWM调速程序问题

[复制链接]
回帖奖励 50 黑币 回复本帖可获得 1 黑币奖励! 每人限 1 次
ID:271875 发表于 2019-5-19 13:10 | 显示全部楼层 |阅读模式
自行车速度里程测量,使用的是外部中断0计数里程脉冲,定时器0计算时间
PWM调速,使用定时器1产生PWM波形
两个程序单独使用都没问题,
但是合在一起,两个定时器一起用就出现问题,错误首先在数码管位选端出现流水灯效果,第一次切割后恢复正常,没有了流水灯效果,速度测量失效。里程测量还能用


附程序代码:
  1. //速度:单位为 m/h         里程单位cm
  2. #include<reg51.h>
  3. #define duan P0                         //段选
  4. #define wei P2                   //位选P2^4-P2^7
  5. #define zhouchang 200            //车轮周长200cm
  6. typedef unsigned char uchar;
  7. typedef unsigned int uint;
  8. typedef unsigned long ulong;
  9. uchar code display1[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //数码管驱动信号0---9,共阳
  10. uchar code bitcode[]={0x7f,0xbf,0xdf,0xef};                                  //数码管位选扫描信号  0111 1111
  11. sbit change = P3^4;                    //切换按键
  12. bit flag = 1;                       //切换标记
  13. bit flag1=0;                    //第一次切割
  14. uchar point1 = 0;               //小数点标记,速度
  15. uchar buf1[]={0,0,0,0};                                        //数码管该显示的数字,高-----低,速度
  16. uchar point2 = 0;               //小数点标记,里程
  17. uchar buf2[]={0,0,0,0};                                        //数码管该显示的数字,高------低,里程
  18. uchar num = 4;                  //数码管第num位
  19. uint time_counter = 0;                                        //每10次切割时差,定时计数
  20. uint time_counter8 = 0;                                        //8s定时计数
  21. uint external_counter = 0;                        //外部中断计数
  22. ulong s = 0;//里程
  23. ulong speed = 0;//速度

  24. sbit PWM=P1^0;              //PWM所使用的一些量
  25. sbit key1=P1^1;
  26. sbit key2=P1^2;
  27. uchar zkb,w;// zkb指占空比

  28. void delay1m(uchar x)//MS级延时函数
  29. {
  30.         uchar i,j;
  31.         for(i = 0;i < x;i++)        //连续x次,约 x ms
  32.                 for(j=0;j<120;j++);   //数120 次,约1 ms
  33. }
  34. void keyscan()         //键盘扫描
  35.   {
  36.            P1=0XFF;
  37.       while(1)
  38.           {
  39.         if(key1==0)
  40.          {
  41.           delay1m(5);
  42.            if(key1==0)
  43.            {

  44.                 if(zkb<10)
  45.                  {
  46.                    zkb++;
  47.                  zkb++;
  48.                  }
  49.               while(!key1);

  50.            }
  51.          }
  52.         if(key2==0)
  53.          {
  54.           delay1m(5);
  55.            if(key2==0)
  56.            {

  57.             if(zkb>0)  
  58.                  {
  59.                    zkb--;

  60.                  }
  61.            while(!key2);
  62.            }
  63.          }   

  64.   }
  65. }

  66. void init_display()              //初始显示0.0.0.0
  67. {
  68.         uchar i;
  69.         for(i = 0;i < 4;i++)         
  70.         {
  71.                 wei = bitcode[num - 1];
  72.                 duan = display1[buf1[num--]];
  73.                 delay1m(1);
  74.                 if(num == 0)num = 4;
  75.         }
  76. }
  77. void time0_int0_init()         //定时器0和外部中断0的初始化函数
  78. {
  79.         TMOD |= 0x11;
  80.         TH1=(65536-10)/256;
  81.         TL1=(65536-10)%256;
  82.         TL0 = (65536 - 5000) % 256;//12M晶振,5ms定时
  83.         TH0 = (65536 - 5000) / 256;
  84.         IT0 = 1;//外部中断0,负跳变触发方式
  85.         TR0 = 0;
  86.         ET0 = 1;
  87.         EX0 = 1;
  88.         EA = 1;
  89.         ET1=1;
  90.         TR1=1;

  91. }

  92. void display_function()                //显示函数
  93. {
  94.         if(flag == 0)//显示速度
  95.         {
  96.                 switch(point1)
  97.                 {
  98.                         case 0:wei = bitcode[num-1];
  99.                                  duan = display1[buf1[num-1]];
  100.                                  num--;
  101.                         break;//速度显示 0

  102.                         case 1:if(num == 1)
  103.                                         { wei = bitcode[num-1];
  104.                                           duan = 0x7f&display1[buf1[num-1]];
  105.                                           num--;
  106.                                         }
  107.                                  else
  108.                                         {
  109.                                                 wei = bitcode[num-1];
  110.                                                 duan = display1[buf1[num-1]];
  111.                                                 num--;
  112.                                         }
  113.                         break;//最高位小数点亮

  114.                         case 2:if(num == 2)
  115.                                         {
  116.                                                 wei = bitcode[num-1];
  117.                                                 duan = 0x7f&display1[buf1[num-1]];
  118.                                                 num--;
  119.                                         }
  120.                                  else
  121.                                         {
  122.                                                 wei = bitcode[num-1];
  123.                                                 duan = display1[buf1[num-1]];
  124.                                                 num--;
  125.                                         }
  126.                         break;//第二高位小数点亮

  127.                         case 3:if(num == 3)
  128.                                         {
  129.                                                 wei = bitcode[num-1];
  130.                                                 duan = 0x7f&display1[buf1[num-1]];
  131.                                                 num--;
  132.                                         }
  133.                                    else
  134.                                         {
  135.                                                 wei = bitcode[num-1];
  136.                                                 duan = display1[buf1[num-1]];
  137.                                                 num--;
  138.                                         }
  139.                         break;//第三高位小数点亮

  140.                         default:break;        

  141.                 }
  142.                 if(num == 0)num = 4;
  143.          }
  144.         else if(flag == 1)//显示里程
  145.    {
  146.                 switch(point2)
  147.                 {
  148.                         case 0:wei = bitcode[num-1];
  149.                                  duan = display1[buf2[num-1]];
  150.                                  num--;
  151.                         break;//里程显示 0

  152.                         case 1:if(num == 1)
  153.                                         {
  154.                                                 wei = bitcode[num-1];
  155.                                                 duan = 0x7f&display1[buf2[num-1]];
  156.                                                 num--;
  157.                                         }
  158.                                  else
  159.                                         {
  160.                                                 wei = bitcode[num-1];
  161.                                                 duan = display1[buf2[num-1]];
  162.                                                 num--;
  163.                                         }
  164.                         break;//最高位小数点亮

  165.                         case 2:if(num == 2)
  166.                                         {
  167.                                                 wei = bitcode[num-1];
  168.                                                 duan = 0x7f&display1[buf2[num-1]];
  169.                                                 num--;
  170.                                         }
  171.                                    else
  172.                                         {        
  173.                                                 wei = bitcode[num-1];
  174.                                                 duan = display1[buf2[num-1]];
  175.                                                 num--;
  176.                                         }
  177.                         break;//第二高位小数点亮

  178.                         case 3:if(num == 3)
  179.                                         {
  180.                                                 wei = bitcode[num-1];
  181.                                                 duan = 0x7f&display1[buf2[num-1]];
  182.                                                 num--;
  183.                                         }
  184.                                    else
  185.                                         {
  186.                                                 wei = bitcode[num-1];
  187.                                                 duan = display1[buf2[num-1]];
  188.                                                 num--;
  189.                                         }
  190.                         break;//第三高位小数点亮

  191.                         default:break;        

  192.                 }
  193.                 if(num == 0)num = 4;
  194.    }
  195. }
  196. //====================================主函数=========================================================
  197. void main()
  198. {

  199.         time0_int0_init();//定时器0和外部中断0的初始化
  200.         while(!TR0)        //上电一直未切割时就显示  0.0.0.0
  201.         {
  202.                 init_display();
  203.         }
  204.         zkb=4;

  205.         while(1)
  206.         {

  207.                 keyscan();
  208.                 if(!change)//按下切换按键显示里程
  209.                 {
  210.                         delay1m(5);
  211.                         if(!change)
  212.                         {
  213.                                 flag = ~flag;
  214.                         }
  215.                         while(!change);               
  216.                 }

  217.         }
  218. }

  219. //==================================定时器0中断函数================================
  220. void time0_interrupt() interrupt 1
  221. {
  222.         TL0 = (65536 - 5000) % 256;// 12M晶振,5ms定时
  223.         TH0 = (65536 - 5000) / 256;
  224.         display_function();
  225.         time_counter++;
  226.         time_counter8++;
  227.         if(time_counter8 >= 1600)//大于8s没切割,车子视为停下了,速度为:0,但里程还记着
  228.         {
  229.                 time_counter8 = 0;
  230.                 speed = 0;//速度为 0
  231.                 point1 = 0;
  232.                 buf1[3] = speed%10;                //显示数组赋值
  233.                 buf1[2] = speed/10%10;
  234.                 buf1[1] = speed/100%10;
  235.                 buf1[0] = speed/1000%10;
  236.         }
  237. }

  238. void time1() interrupt 3         //定时器1中断函数
  239.   {

  240.       TH1=(65536-10)/256;
  241.         TL1=(65536-10)%256;
  242.         ++w;
  243.         if(w>10)
  244.           {
  245.           w=0;
  246.           };

  247.         if(w<=zkb)
  248.         {
  249.          PWM=1;
  250.         }
  251.         else PWM=0;


  252.   }

  253. //==================================外部中断0中断函数=========================
  254. void int0_interrupt()interrupt 0
  255. {        

  256.         external_counter++;
  257.         if(external_counter ==1 )TR0 = ~TR0; //第一次切割打开定时器0
  258.         if(external_counter == 65535)external_counter = 0;
  259.         time_counter8 = 0;                //只要8秒内有切割,车子就一直在运行

  260.         if(external_counter % 10 == 0)//切割10次 更新下速度
  261.         {                                                                                     //*5是因为中断一次是5MS
  262.                  if(flag1==0)                 //第一次切割更新速度
  263.                                 {
  264.                                         speed =((ulong)(36000)*zhouchang)/(time_counter * 5);
  265.                                         flag1=1;
  266.                                 }
  267.                 else if(flag1==1){speed =((ulong)(36000)*10*zhouchang)/(time_counter * 5);} //不是第一次切割

  268.                 if((speed >= 100)&&(speed < 1000))         //100 ---- 1000       3位整数
  269.                 {
  270.                         point1 = 1;
  271.                         buf1[3] = speed%10;
  272.                         buf1[2] = speed/10%10;
  273.                         buf1[1] = speed/100%10;
  274.                         buf1[0] = 0;
  275.                 }
  276.                 else if((speed >= 1000)&&(speed < 10000))   //1000 ---- 10000        4位整数
  277.                 {
  278.                         point1 = 1;
  279.                         speed = (uint)speed;
  280.                         buf1[3] = speed%10;
  281.                         buf1[2] = speed/10%10;
  282.                         buf1[1] = speed/100%10;
  283.                         buf1[0] = speed/1000%10;
  284.                 }
  285.                 else if((speed >= 10000)&&(speed < 100000))          //10000 ----- 100000      5位整数
  286.                 {
  287.                         point1 = 2;
  288.                         buf1[3] = speed/10%10;
  289.                         buf1[2] = speed/100%10;
  290.                         buf1[1] = speed/1000%10;
  291.                         buf1[0] = speed/10000%10;
  292.                 }
  293.                 else if((speed >= 100000)&&(speed < 1000000))  //100000 ------ 1000000    6位整数
  294.                 {
  295.                         point1 = 3;
  296.                         buf1[3] = speed/100%10;
  297.                         buf1[2] = speed/1000%10;
  298.                         buf1[1] = speed/10000%10;
  299.                         buf1[0] = speed/100000%10;
  300.                 }
  301.                 time_counter = 0;
  302.         }

  303.         if(external_counter % 10 == 0)//每切割10次 更新下里程
  304.         {
  305.                  s = (ulong)external_counter * zhouchang;  //里程:单位为   cm
  306.                 if((s >= 1000)&&(s < 10000))
  307.                 {
  308.                         point2 = 1;                                                                                                   //  0.012    001212
  309.                         buf2[3] = s/100%10;
  310.                         buf2[2] = s/1000%10;
  311.                         buf2[1] = 0;
  312.                         buf2[0] = 0;
  313.                 }//   4位整数
  314.                 else if((s >= 10000)&&(s < 100000))
  315.                 {
  316.                         point2 = 1;
  317.                         buf2[3] = s/100%10;
  318.                         buf2[2] = s/1000%10;
  319.                         buf2[1] = s/10000%10;
  320.                         buf2[0] = 0;
  321.                 }//     5位整数           0.123         012345
  322.                 else if((s >= 100000)&&(s < 1000000))
  323.                 {
  324.                         point2 = 1;
  325.                         buf2[3] = s/100%10;
  326.                         buf2[2] = s/1000%10;
  327.                         buf2[1] = s/10000%10;
  328.                         buf2[0] = s/100000%10;
  329.                 } //    6位整数         1.234    1234 56
  330.             else if((s >= 1000000)&&(s < 10000000))
  331.                 {
  332.                         point2 = 2;
  333.                         buf2[3] = s/1000%10;
  334.                         buf2[2] = s/10000%10;
  335.                         buf2[1] = s/100000%10;
  336.                         buf2[0] = s/1000000%10;
  337.                 }//     7位整数          1234 567
  338.                 else if((s >= 10000000)&&(s < 100000000))
  339.                 {
  340.                         point2 = 3;
  341.                         buf2[3] = s/10000%10;
  342.                         buf2[2] = s/100000%10;
  343.                         buf2[1] = s/1000000%10;
  344.                         buf2[0] = s/10000000%10;
  345.                 } //     8位整数                 1234 5678
  346.         }
  347. }
复制代码


回复

使用道具 举报

ID:123289 发表于 2019-5-20 08:48 | 显示全部楼层
1、延时不要用DELAY硬件延时程序做!
2、中断服务程序中:不要做显示、复杂的计算!
你能做到以上两点就可以了。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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