找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2806|回复: 10
收起左侧

单片机+电机能加减速,但是LCD1062输出转速无法实时显示

[复制链接]
ID:749922 发表于 2020-5-17 20:54 | 显示全部楼层 |阅读模式
300黑币
C51单片机产生PWM输入L298驱动电机,控制启停,正反转,加减速,这些都可以实现,可以以反馈到LCD1062上。但是通过T1定时器、外中断INT1组合测速(脉冲频率)无法实时显示到屏幕,就是可以显示,但是数值不变化。也不知道为啥。
个人认为问题应该出在测速模块或者外中断1函数里,但是找不出原因,请大佬看看!

单片机源程序如下:
  1. #include <reg52.h>
  2. #include<string.h>
  3. #include <intrins.h>
  4. #define uchar unsigned char
  5. #define uint unsigned int
  6.      
  7. sbit lcdrs=P2^0;       //寄存器选择,0:数据寄存器。1:为状态/命令寄存器
  8. sbit lcden=P2^1;         //--LCD控制引脚

  9. sbit speed=P3^2;                                        //测速端口
  10. sbit ENA=P2^2;                                        //电机使能控制端

  11. sbit key1=P1^0;         //启动按键
  12. sbit key2=P1^1;                                        //正转按键
  13. sbit key3=P1^2;                                        //反转按键
  14. sbit key4=P1^3;                                        //加速按键
  15. sbit key5=P1^4;                                        //减速按键
  16. sbit key6=P1^5;                                        //停止按键
  17. sbit Zheng=P1^6;                                                //正转输出端口
  18. sbit Fan=P1^7;                                                //反转输出端口

  19. uchar Timer0_flag=4;
  20. uchar Timer0_BiaoZhi=0;//初始化占空比为1:3(高:低)

  21. uchar gewei;
  22. uchar shiwei;
  23. uchar baiwei;

  24. /******标志位设置*****/
  25. uchar KEY1=0;//优先级标志
  26. uchar KEY2=0;//加速标志

  27. uchar INT1_FLAG=0;
  28. uchar COUNTER_high=0;
  29. uchar COUNTER_low=0;
  30. uchar SUM=0;
  31. uint TIMER1_COUNTER=0;
  32. uint INT1_tingzhi=0;                //在要测速时置0

  33. /****面板显示****/
  34. uchar code lcd_desktop10[]="WUU";//不显示
  35. uchar code lcd_desktop11[]="RUN";//运行
  36. uchar code lcd_desktop12[]="FWD";//正转
  37. uchar code lcd_desktop13[]="REV";//反转
  38. uchar code lcd_desktop14[]="JIA";//加速
  39. uchar code lcd_desktop15[]="JAN";//减速
  40. uchar code lcd_desktop16[]="OFF";//停止
  41. uchar code num[]={'0','1','2','3','4','5','6','7','8','9'};//要显示的转速数字。

  42. //-----lcd液晶屏头文件-----//
  43. /**延时函数**/
  44. void delayms(uchar xms)   
  45. {
  46.         uchar i,j;
  47.         for(i=xms;i>0;i--)
  48.         for(j=110;j>0;j--);
  49. }

  50. /****LCD写命令******/
  51. void write_command(uchar com)//com写入命令
  52. {
  53.         lcdrs=0;    //LED选择输入命令
  54.         P0=com;     //向P0口输入命令39-32端口
  55.         delayms(2);  //延时
  56.         lcden=1;     //打开LCD使能
  57.         delayms(2);  //一个高脉冲
  58.         lcden=0;     //关闭LED使能
  59. }

  60. /**************LCD写数据,来源网上*********/
  61. void write_data(uchar date)//数据为DATA
  62. {
  63.         lcdrs=1;  //设置为输入数据
  64.         P0=date;  //将数据赋给P0口
  65.         delayms(2);  //延时
  66.         lcden=1;     //置高
  67.         delayms(2);
  68.         lcden=0;     //置低完成高脉冲
  69. }

  70. /********LCD初始化,来源网上****************/
  71. void lcd_init()//显示模式设置
  72. {
  73.         lcden=0;
  74.         write_command(0x38);   //设置16×2 显示5×7点阵,8位数据接口
  75.         write_command(0x0c);   //设置开始显示不显示光标(指令4)
  76.         write_command(0x06);   //写一个字符后地址指针加一(指令3)
  77.         write_command(0x01);   //显示清零数据指针清零(指令1)
  78. }

  79. /**电机初始化函数**/
  80. void motor_init(void)
  81. {
  82.         ENA=0;                                //        停止
  83. }

  84. void ZhongDuanKaiQi(void)
  85. {
  86.         EA=1;               
  87.         ET0=1;        //计时器0允许中断。产生脉冲。
  88.         ET1=1;        //计时器1允许中断。对低电平进行计时。
  89.         //EX1=1;        //INT0允许中断。测速。由外部来启动。
  90.         IT1=1;        //外部中断1低电平触发。
  91.         PX1=0;        //外中断0为低级中断。
  92.         PT0=1;  //定时器0为高优先级中断
  93.         PT1=0;  //外中断1为低优先级中断
  94.         TMOD=0x12;//定时器工作方式控制
  95. }
  96. /***定时器T1初始化!!!等待外部脉冲的到来***/
  97. void Timer1_init(void)
  98. {
  99.         TH1=0;
  100.         TL1=0;                //等待外部脉的到来。INT1
  101. }
  102. /*****定时T0初始化*****/
  103. void Timer0_init(void)
  104. {
  105.         TH0=0;
  106.         TL0=0;
  107.         TR0=1;
  108. }
  109. /********测速模块,显示速度*******/
  110. void speed_test(void)
  111. {
  112. //        TIMER1_COUNTER;
  113.         COUNTER_high=TH1;
  114.         COUNTER_low=TL1;
  115.         SUM=COUNTER_high*256+COUNTER_low+TIMER1_COUNTER*65536;//得到的是多少us。
  116.         //count:每百16位进1,16位为65536;TH1:每8位进1,8位为256;TL1:每次进1;即TL1由0增加度到内255时,TH1加1,TL1回0,TH1由0增加到65535时,count加1,TH1回0,三者之和为总次数。
  117.         SUM=SUM/1000;                                //化为毫秒。
  118.         SUM=1000/SUM;                                //圈每秒。
  119.         SUM=SUM*60;                                        //圈每分钟;三位数。
  120.         gewei=SUM%10+0x30;
  121.         shiwei=SUM/10%10+0x30;
  122.         baiwei=SUM/100+0x30;
  123.         write_command(0x80+0x4c);
  124.         write_data(baiwei);
  125.         write_command(0x80+0x4d);
  126.         write_data(shiwei);
  127.         write_command(0x80+0x4e);
  128.         write_data(gewei);
  129.         SUM=0;
  130.         TIMER1_COUNTER=0;               
  131. }

  132. /********外中断1函数**********/
  133. void INT1_QIDONG() interrupt 2
  134. {
  135.         INT1_tingzhi++;
  136.         if(INT1_tingzhi==5)
  137.         {
  138.                 INT1_tingzhi=5;EX1=0;//关闭中断。
  139.         }
  140.         if(INT1_tingzhi<=4)
  141.         {
  142.                 INT1_FLAG++;
  143.           if(INT1_FLAG==2)
  144.                         {
  145.                                 INT1_FLAG=0;TR1=0;speed_test();
  146.                         }
  147.                 else
  148.                         {
  149.                                 Timer1_init();
  150.                                 TR1=1;
  151.                         }
  152.         }
  153. }
  154. /******定时器T1计数*******/
  155. void Timer1_QIDONG() interrupt 3
  156. {
  157.         TIMER1_COUNTER++;
  158. }



  159. /****T0中断发出信号并进行通道选择****/
  160. void Timer0() interrupt 1
  161. {        
  162.         Timer0_flag--;
  163.         if((Timer0_BiaoZhi)>=(Timer0_flag))
  164.         {
  165.                 if(KEY2==0)
  166.                 {
  167.                         Zheng=1;Fan=0;
  168.                 }
  169.                 else
  170.                 {
  171.                         Zheng=0;Fan=1;
  172.                 }
  173.         }
  174.         else
  175.         {
  176.                 Zheng=0;Fan=0;                                
  177.         }        
  178.         if(Timer0_flag==0) Timer0_flag=5;
  179. }


  180. void Guan(void)
  181. {
  182.         ET0=0;
  183.         EX1=0;
  184.         ET1=0;        
  185. }


  186. void keyscan()                         //按键扫描函数
  187. {
  188.         uint i=0;
  189.         if(key1==0)   //按键K1启动按钮。只有该位启动时,后面的几位才有效。启动T0计数开始发出脉冲。
  190.         {
  191.                 delayms(10);
  192.                 if(key1==0)
  193.                 {
  194.                         while(!key1);
  195.                         KEY1=5;
  196.                         Fan=0;
  197.                         Zheng=0;
  198.                         ENA=1;
  199.                         KEY2=0;//初始化为正转。
  200.                   Timer0_BiaoZhi=0;
  201.                         Timer0_flag=4;
  202.                         
  203.                         ZhongDuanKaiQi();//开启中断        
  204.                         Timer0_init();//                初始化并开始发出脉冲外中断已经开启。
  205.                         EX1=1;                                        //外中断开启;测速,显示速度。
  206.                         
  207.                         write_command(0x80);
  208.                         for(i=0;i<strlen(lcd_desktop10);i++)//显示正转。
  209.                         write_data(lcd_desktop11[i]);
  210.                 }
  211.         }
  212.         
  213.   if(key2==0&&KEY1==5) //按键K2按下,(正转)只改变转向(标志位改变输出端口)
  214.         {
  215.                 delayms(10);
  216.                 if(key2==0)
  217.                 {
  218.                         while(!key2);
  219.                         KEY2=0;                //正转标志,电机正向旋转。
  220.                         //KEY2=(~1);
  221.                
  222.                         KEY1=5;
  223.                         write_command(0x80);
  224.                         for(i=0;i<strlen(lcd_desktop11);i++)//显示正转。
  225.                         write_data(lcd_desktop12[i]);
  226.                 }
  227.         }
  228.         
  229.         if(key3==0&&KEY1==5) //按键K3按下,(反转)只改变转向
  230.         {
  231.                 delayms(10);
  232.                 if(key3==0)
  233.                 {
  234.                         while(!key3);
  235.                         KEY2=~0;                        //反转标志。
  236.                         //KEY2=(~0);
  237.                
  238.                         KEY1=5;
  239.                         write_command(0x80);
  240.                         for(i=0;i<strlen(lcd_desktop12);i++)//显示反转。
  241.                         write_data(lcd_desktop13[i]);
  242.                 }
  243.         }
  244.    if(key4==0&&KEY1==5)        //按键K4按下,(加速)改变装入的数值?循环次数?执行if里面的语句,通过size++来改变幅值的频率
  245.          {
  246.                  delayms(10);
  247.                  if(key4==0)
  248.                  {
  249.                          while(!key4);
  250.                          if(Timer0_BiaoZhi<4)
  251.                          {
  252.                                  Timer0_BiaoZhi++;
  253.                          }
  254.                          else
  255.                          {
  256.                                  Timer0_BiaoZhi=4;
  257.                          }
  258.                           EX1=1;
  259.                           KEY1=5;
  260.                          write_command(0x80);
  261.                         for(i=0;i<strlen(lcd_desktop13);i++)//显示加速。
  262.                         write_data(lcd_desktop14[i]);
  263.                  }
  264.                
  265.          }
  266.          
  267.          if((key5==0)&&(KEY1==5))         //按键K5按下,(减速)对其它标志位没有影响。
  268.          {
  269.                  delayms(5);
  270.                  if(key5==0)
  271.                  {
  272.                          while(!key5);
  273.                          if(Timer0_BiaoZhi==0)
  274.                          {
  275.                                  Timer0_BiaoZhi=0;
  276.                          }
  277.                          else
  278.                          {
  279.                                  Timer0_BiaoZhi--;
  280.                          }
  281.                           EX1=1;
  282.                           KEY1=5;
  283.                          write_command(0x80);
  284.                         for(i=0;i<strlen(lcd_desktop14);i++)//显示减速。
  285.                         write_data(lcd_desktop15[i]);
  286.                  }
  287.          }
  288.          if((key6==0)&&(KEY1==5))//按键K6按下,电机停止转动使能端和计数启动关闭,计数器工作否?设立标志位。此按键按下后除K1外无法启动
  289.          {
  290.                  delayms(5);
  291.                  if(key6==0)
  292.                  {
  293.                          while(!key6);
  294.                          //置位,保证后续操作正常。
  295.                         
  296.                         
  297.                         
  298.                          EA=0;                                //总中断关
  299.                          motor_init();                //电机关
  300.                          Guan();
  301.                          write_command(0x80);
  302.                         for(i=0;i<strlen(lcd_desktop15);i++)//显示停止。
  303.                         write_data(lcd_desktop16[i]);                                 
  304.                  }
  305.          }
  306. }

  307. /*主函数*/
  308. void main()
  309. {

  310.         ZhongDuanKaiQi();//初始化
  311.         motor_init();                        //电机停止
  312.         lcd_init();
  313.         while(1)
  314.         {
  315.                 keyscan();
  316.                
  317.         }
  318. }
复制代码
11111.jpg





电路图和程序,可以仿真。
电机控制及显示.zip (68.96 KB, 下载次数: 8)

回复

使用道具 举报

ID:749922 发表于 2020-5-18 11:13 | 显示全部楼层
没人回答吗
回复

使用道具 举报

ID:682488 发表于 2020-5-18 11:27 | 显示全部楼层
用T2口试试,或许是片子质量有问题呢
回复

使用道具 举报

ID:749922 发表于 2020-5-18 13:24 | 显示全部楼层
大长虫 发表于 2020-5-18 11:27
用T2口试试,或许是片子质量有问题呢

仿真的话,应该和片子没关系吧。然后我觉得程序的问题在于那个函数sun算出来的是一个确定的值,但是我现在找不出问题在哪里
回复

使用道具 举报

ID:754714 发表于 2020-5-18 13:44 | 显示全部楼层
建议调整测速函数与显示函数各种的参数,是否二者存在某项参数的不匹配。
回复

使用道具 举报

ID:749922 发表于 2020-5-18 14:56 | 显示全部楼层
1649293198 发表于 2020-5-18 13:44
建议调整测速函数与显示函数各种的参数,是否二者存在某项参数的不匹配。

我刚才把sum的函数去掉,发现没有给sum(也就是输出的速度)赋值,他也能输出096,给他赋值也还是输出096,也就是输出的数字完全就不是我想要的,这是为啥??
回复

使用道具 举报

ID:749922 发表于 2020-5-18 15:02 | 显示全部楼层
1649293198 发表于 2020-5-18 13:44
建议调整测速函数与显示函数各种的参数,是否二者存在某项参数的不匹配。

我刚才把sum的函数去掉了,也就是没有给sum(要输出的速度)赋值,但是仿真的时候还是能出现096,给它赋值的时候也是输出096,这是为什么?
回复

使用道具 举报

ID:749922 发表于 2020-5-18 16:17 | 显示全部楼层
现在的问题就是,sum的值就是0,函数没有用,是因为外部中断没有起作用开始不能使T1开始计时吗?
回复

使用道具 举报

ID:752225 发表于 2020-5-18 17:04 来自手机 | 显示全部楼层
你液晶程序在读写数据时不用判断忙不忙吗?可以百度一下判忙哪里是不是出现了问题
回复

使用道具 举报

ID:752225 发表于 2020-5-18 17:07 来自手机 | 显示全部楼层
还有在哪里添加延时非常重要,不过51的应该对延时要求不大,这个要参考数据手册,我两个1602液晶发现不能公用一个程序,当初困扰了很久,多半是延时和判忙哪里有问题,个人建议
回复

使用道具 举报

ID:732506 发表于 2020-5-19 02:56 | 显示全部楼层
图太小,看不清测速端口信号从何而来?如果不是来自电机,应该人为注入一定频率的信号来模拟电机转动。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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