找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5524|回复: 3
收起左侧

基于单片机+霍尔元件电机转速测量系统电路程序设计

  [复制链接]
ID:853387 发表于 2020-12-2 21:02 | 显示全部楼层 |阅读模式

如图1所示,此方案是以STC89C52RC单片机作为主控芯片,采用霍尔测速传感器磁场频率测速法测量电机转速、采集电机参数,向单片机输入脉冲信号。选取LCD1602液晶显示屏显示电机每分钟转速及占空比。采取独立按键作为按键模块,为单片机提供按键信息,实现电机启动/停止、正转、反转、加速、减速功能。选择双极PWM控制配合H型桥式驱动电路实现电机驱动,利用USB-TTL转串口模块完成系统供电以及烧录程序。整体硬件需求较小,硬件成本较低。


3.8总体方案框图




四、电路设计

4.1总体电路设计原理图


图2 系统电路设计原理图

系统电路构成:由STC89C52RC单片机最小系统作为运算处理和控制的核心,采用USB-TTL转串口实现电路5V供电,选择3144测速传感器(P3.3)作为输入模块,LCD1602液晶显示模块(P0.0—P0.7,P2.7:RS,P2.6:RW,P2.7:EN)作为显示电路,并配合按键电路控制直流电机、设定占空比,最后通过由三级管及开关二极管组成的H桥电路(P3.4,P3.7)驱动5V直流电机,共六个部分组成,如图2所示。

4.2供电电路

图3 供电模块接线电路图

在PCB板子的一侧焊上四个排针,外接USB-TTL转串口的5V,RXD,TXD,GND端口,实现对电路的5V供电以及对STC89C52RC单片机程序的烧录,具体电路如图3所示。

4.3直流电机驱动电路

图4 电机驱动模块电路图

直流电机驱动电路由四个三极管组成H桥驱动电路,H桥的输入受STC89C52RC单片机输出的PWM信号控制,在实现转速控制的同时,也可以实现正反转控制,具体电路如图4所示。

4.4霍尔传感器测速模块电路

图5 霍尔传感器测速模块实物图

霍尔传感器测速模块电路应用霍尔效应原理,是由电压调整器、霍尔电压发生器、差分放大器、施密特触发器,温度补偿电路和集电极开路的输出级组成的磁敏传感电路。使用3144E开关型霍尔传感器,其输入为磁感应强度,输出是一个数字电压信号。当传感器感应到磁场时,数字输出低电平,信号灯亮;如果没有感应到磁场,则数字输出高电平,信号灯不亮,准确度、可靠性高。

图6 霍尔传感器测速模块接线电路图

霍尔传感器测速模块的数字信号输出端口通过10K的上拉电阻与STC89C52RC的P3.3端口相连,使其输出信号更稳定,如图6所示。

4.5按键电路

图7 按键电路图

按键电路由5个普通的自复位式四脚按键组成,将它们同一侧的引脚纵向连在一起接到GND,另一端分别接入STC89C52RC单片机的P1.0—P1.4引脚,主要实现电机启动/停止、正转、反转、加速、减速,如图7所示。

4.6单片机及显示电路

图8 单片机最小系统图

图9 LCD1602液晶显示图

单片机及显示电路包括单片机最小系统、LCD1602液晶显示,如图8、图9所示,LCD1602液晶显示通过并行通信接口(D0—D7,P2.7:RS,P2.6:RW,P2.7:EN)与单片机相连,在电路中主要实现电机转速及占空比的显示。

单片机通过P3.4、P3.7端口向直流电机驱动电路输出PWM信号,控制电机转速。霍尔传感器测速模块电路输出的方波信号送入单片机的P3.3端口。

4.7元器件清单

表1 元器件清单表

元器件
型号规格
个数
IC插座集成块
40P脚
1
测速传感器模块
Risym
1
轻触式开关
直插6*6*5 中二脚
1
轻触式开关
直插6*6*5 四脚
5
单排排针
插针 1*40PIN
2
1/4W金属膜电阻
10K
2
1/4W金属膜电阻
1K
4
1/4W金属膜电阻
4.7K
1
蓝白滑动变阻器
10K
1
排阻
103
1
排母
40P脚
1
铝电解电容
10uf
1
瓷片电容
33pf 50v
2
独石电容
104
2
石英晶振
12M 直插2脚
1
开关二极管
1N4148
4
微型直流电机
RC300带线
1
万用板
10*15cm
1
三极管
S8050
4
三极管
S8550
2
显示屏
LCD1602
1
USB转串口模块(刷机板)
CH340模块
1
单片机
STC89C52RC
1


元器件的选择,根据可靠性、可行性、稳定性、价格以及最终方案,选择元器件均为直插式,选择STC89C52RC单片机为主控芯片,使用IC插座集成块,方便单片机的更换,利用排母使LCD1206实现外接模式,方便显示屏安装与拆卸。

五、软件设计

程序设计部分主要包括主程序、初始化子程序、键盘扫描子程序、LCD1602显示子程序、中断子程序、信息处理子程序及PWM生成程序七个部分组成,大致通过LCD1602显示信息,通过按键输入信息,对LCD1602显示的转速和占空比等信息进行操作。

5.1主程序

主程序中主程序中包含了初始化程序,键盘扫描程序,主程序代码如下:

void main()
{
flag_1=0;
              m=100;                           
              zhuansu=0;                                         
              flag=0;
              zheng=1;                                                      
              fan=0;
    init();               
              while(1)
              {
                            keyscan();                                         
              }
}


5.2中断程序

1.外部中断

(1)工作过程:每来一个电机脉冲信号,产生中断计数。

(2)流程图:如图11所示。

(3)程序:

void int1()interrupt 2                                         
{
  zhuansu++;

}

2.定时器中断

(1)工作过程:TT0 定时器每2秒定时中断一次,读取记录的脉冲个数,显示转速。

(2)流程图:如图12所示。

(3)程序:

void int2()interrupt 3                                         

{
  

TH0=0xdc;
  TL0=0x00;               
  flag++;
  if(flag==200)
  {                                         
              display();                                                         
              zhuansu=0;                                                      
              flag=0;
  }
}

5.3键盘扫描程序



(1)工作过程:按键1按下时占空比加一,按键2按下时占空比减一,按键3按下时电机正转,按键4按下时电机反转,按键5按下时电机启动/停止。

(2)流程图:如图13所示。

(3)程序:

void keyscan()
{
  if(num1==0)   
  {
     delay(20);
              if(num1==0)
              {
                            if(m<=199)
                                          m++;
                            displaym();
     }
  }
  if(num2==0)
  {
                delay(20);
              if(num2==0)
              {
                              if(m>=1)
                                          m--;
                            displaym();

              }
  }
  if(num3==0)
  {
                delay(20);
              if(num3==0)
              {
                            zheng=1;
                            fan=0;
              }
  }
  if(num4==0)
  {
     delay(20);
              if(num4==0)
              {
                            zheng=0;            
                            fan=1;               
              }
  }
  if(num5==0)
  {
     delay(20);
              if(num5==0)
              {
                            while(num5==0);
                            kai=1-kai;
              }
  }
}

5.4信息处理子程序


1.占空比显示

(1)工作过程:在LCD1602上显示占空比,若转速百位为零则百位显示空格、其余正常显示,反之百位也正常显示;若转速十位为零则只显示个位,反之十位也正常显示、百位显示空格。

(2)流程图:如图14所示。

(3)程序:

void displaym()

{
  write_com(0xcb);
  if(m/200%10!=0)
                write_data(m/200%10+0x30);                                          
  else
                write_data(' ');

  if(m/200%10==0&&m/20%10==0)
                write_data(' ');
  else
                write_data(m/20%10+0x30);                           
  write_data(m/2%10+0x30);                                                      
}

2.转速显示:

(1)工作过程:在LCD1602上显示转速,若转速万位为零则万位显示空格、其余正常显示,反之都正常显示;若转速千位为零则万位、千位显示空格、其余正常显示,反之千位也正常显示;若转速百位为零则万位、千位、百位显示空格、其余正常显示,反之百位也正常显示;若转速十位为零则只显示个位,反之十位也正常显示、其余显示空格。

(2)流程图:如图15所示。

(3)程序:

void display()
{
  write_com(0x82);
  zhuansu=zhuansu*30;                                 

  if(zhuansu/10000!=0)
                write_data(zhuansu/10000+0x30);                  
  else
                write_data(' ');

  if(zhuansu/1000==0)
                write_data(' ');
  else
                write_data(zhuansu%10000/1000+0x30);            

  if(zhuansu/100==0)
                write_data(' ');
  else
                write_data(zhuansu%10000%1000/100+0x30);   

  if(zhuansu/10==0)
                write_data(' ');
  else
                write_data(zhuansu%10000%1000%100/10+0x30);
  write_data(zhuansu%10000%1000%100%10+0x30);
  write_com(0xd0);}


5.5PWM生成子程序



(1)工作过程:电机正转时,若0<flag_1<m,向电机输出高电平;若m<flag_1<199,向电机输出低电平。电机反转时,若0<flag_1<m,向电机输出低电平;若m<flag_1<199,向电机输出高电平。

(2)流程图:如图15所示。

(3)程序:

void int3()interrupt 1                              
{
  TH1=0xff;
  TL1=0x00;               
              flag_1++;
              if(flag_1>199)
              flag_1=1;
              if(kai==1)                                      
              {
                            if(zheng==1)                              
                            {
                                          if(flag_1<m)               
                                 {
                                          out=0;
                                          out1=1;
                                          }
                                          else
                                          {
                                             out=1;
                       out1=1;
                                          }
                            }
                            if(fan==1)                                          
                  {
                                          if(flag_1<m)               
                      {
                                out=1;
                                          out1=0;
                                            }
                                          else                                            
                                            {
                       out=1;
                                 out1=1;
                                            }
                            }
              }
              if(kai==0)                                                
              {
                out=1;
                out1=1;
              }
}

六、制作、调试过程

6.1制作

图17 万用板元件分布图

将电路原理图绘制完成,然后根据原理图准备相应的元件,再根据要求改变各元件的属性并把各个元件按原理图焊接于万用板之上。焊接完成后,用万用表检测电路的通断情况,检查无误后,向IC插座集成块中插入芯片,下载测试程序,观察LCD1602显示模块、电机、霍尔传感器测速模块以及按键是否按程序正常运行。

图18 PCB照片预览及3D仿真

图19 PCB实物图

图20 万用板实物图

6.2调试

利用制作的实物进行运行调试,通过按不同的按键,观察LCD1602显示情况,判断是否存在逻辑错误的情况。调试过程中,肯定会出现因逻辑错误而显示不正常,需要配合仿真调试进行排查。发现出错原因后,及时想办法解决问题。

图21 实物调试图


九、附录

图 22  系统电路原理图


图 2  实物正面电路

图 3  实物反面电路走线


图 4  实物调试

单片机系统程序:


  1. #include <reg52.h>
  2. #define uchar unsigned char
  3. #define uint unsigned int
  4. void displaym();
  5. sbit en=P2^5;               
  6. sbit rs=P2^7;               
  7. sbit rw=P2^6;   
  8. sbit num1=P1^2;               
  9. sbit num2=P1^3;               
  10. sbit num3=P1^0;               
  11. sbit num4=P1^1;               
  12. sbit num5=P1^4;               
  13. sbit out=P3^4;            
  14. sbit out1=P3^7;                           
  15. uint zhuansu,flag,z1,z2,m,flag_1,zheng,fan,kai;
  16. void delay(uint z)
  17. {

  18. uint x,y;
  19. for(x=0;x<z;x++)
  20.      for(y=0;y<110;y++);
  21. }
  22. void write_com(uchar com)  
  23. {
  24.   rs=0;
  25.   P0=com;
  26.   delay(5);
  27.   en=0;
  28.   delay(10);
  29.   en=1;
  30. }
  31. void write_data(uchar date)  
  32. {
  33.   rs=1;
  34.   P0=date;
  35.   delay(5);
  36.   en=0;
  37.   delay(5);
  38.   en=1;
  39. }
  40. void init()         
  41. {
  42.   en=0;
  43.   rw=0;
  44.   write_com(0x01);   
  45.   write_com(0x38);                           
  46.   write_com(0x0c);                           
  47.   TMOD=0x01;                    
  48.   TH0=0xdc;
  49.   TL0=0x00;            
  50.   EA=1;                  
  51.   ET0=1;              
  52.   TR0=1;
  53.   EX1=1;
  54.   IT1=1;               
  55.   TH1=0xfc;
  56.   TL1=0x66;         
  57.   ET1=1;              
  58.   TR1=1;
  59.   write_com(0x80);
  60.   write_data('V');
  61.   write_data(':');
  62.   write_com(0x87);                           
  63.   write_data('r');
  64.   write_data('p');
  65.   write_data('m');
  66.   write_com(0xc0);
  67.   write_data('z');
  68.   write_data('h');
  69.   write_data('a');
  70.   write_data('n');
  71.   write_data('k');
  72.   write_data('o');
  73.   write_data('n');
  74.   write_data('g');
  75.   write_data('b');
  76.   write_data('i');                    
  77.   write_data(':');                           
  78.   displaym();
  79. }
  80. void keyscan()           
  81. {
  82.   if(num1==0)   
  83.   {
  84.      delay(20);         
  85.               if(num1==0)
  86.               {
  87.                             if(m<=199)
  88.                                           m++;
  89.                             displaym();      
  90.      }
  91.   }
  92.   if(num2==0)
  93.   {
  94.                 delay(20);
  95.               if(num2==0)
  96.               {
  97.                               if(m>=1)
  98.                                           m--;
  99.                             displaym();     
  100.               }
  101.   }
  102.   if(num3==0)
  103.   {
  104.                 delay(20);
  105.               if(num3==0)
  106.               {
  107.                             zheng=1;            
  108.                             fan=0;               
  109.               }
  110.   }
  111.   if(num4==0)
  112.   {
  113.      delay(20);
  114.               if(num4==0)
  115.               {
  116.                             zheng=0;            
  117.                             fan=1;            
  118.               }
  119.   }
  120.   if(num5==0)
  121.   {
  122.      delay(20);
  123.               if(num5==0)
  124.               {
  125.                             while(num5==0);
  126.                             kai=1-kai;
  127.               }
  128.   }
  129. }
  130. void display()
  131. {
  132.   write_com(0x82);
  133.   zhuansu=zhuansu*30;                                 
  134.   if(zhuansu/10000!=0)
  135.                 write_data(zhuansu/10000+0x30);                     
  136.   else
  137.                 write_data(' ');
  138.   if(zhuansu/1000==0)
  139.                 write_data(' ');
  140.   else
  141.                 write_data(zhuansu%10000/1000+0x30);               
  142.   if(zhuansu/100==0)
  143.                 write_data(' ');
  144.   else
  145.                 write_data(zhuansu%10000%1000/100+0x30);
  146.   if(zhuansu/10==0)
  147.                 write_data(' ');
  148.   else
  149.                 write_data(zhuansu%10000%1000%100/10+0x30);
  150.   write_data(zhuansu%10000%1000%100%10+0x30);
  151.   write_com(0xd0);                 
  152. }
  153. void displaym()
  154. {
  155.   write_com(0xcb);
  156.   if(m/200%10!=0)
  157.                 write_data(m/200%10+0x30);                           
  158.   else
  159.                 write_data(' ');
  160.   if(m/200%10==0&&m/20%10==0)
  161.                 write_data(' ');
  162.   else
  163.                 write_data(m/20%10+0x30);                           
  164.   write_data(m/2%10+0x30);                           
  165. }

  166. void main()
  167. {
  168.   flag_1=0;
  169.               m=100;                                         
  170.               zhuansu=0;                                         
  171.               flag=0;
  172.               zheng=1;                           
  173.               fan=0;
  174.     init();
  175.               while(1)
  176.               {
  177.               keyscan();                           
  178.               }
  179. }

  180. void int1()interrupt 2
  181. {
  182.   zhuansu++;
  183. }

  184. void int2()interrupt 3                           
  185. {
  186.   TH0=0xdc;
  187.   TL0=0x00;
  188.   flag++;
  189.   if(flag==200)            
  190.   {
  191.               display();            
  192.               zhuansu=0;                                                         
  193.               flag=0;
  194.   }
  195. }

  196. void int3()interrupt 1            
  197. {
  198.   TH1=0xff;
  199.   TL1=0x00;
  200.               flag_1++;
  201.               if(flag_1>199)
  202.               flag_1=1;
  203.               if(kai==1)
  204.               {
  205.                             if(zheng==1)            
  206.                             {
  207.                                           if(flag_1<m)
  208.                                  {
  209.                                           out=0;
  210.                                           out1=1;
  211.                                           }
  212.                                           else
  213.                                           {
  214.                                              out=1;
  215.                        out1=1;
  216.                                           }
  217.                             }
  218.                             if(fan==1)
  219.                   {
  220.                                           if(flag_1<m)            
  221.                       {
  222.                                 out=1;
  223.                                           out1=0;
  224.                                             }
  225.                                           else            
  226.                                             {
  227.                        out=1;
  228.                                  out1=1;
  229.                                             }
  230.                             }
  231.               }
  232.               if(kai==0)
  233.               {
  234.                 out=1;
  235.                 out1=1;
  236.               }
  237. }
复制代码
完整的Word格式文档51黑下载地址:

基于霍尔元件电机转速测量系统设计.docx (5.7 MB, 下载次数: 85)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:796531 发表于 2021-4-13 19:12 | 显示全部楼层
好东西,正好在做一个PWM升压电路,思路参考一下
回复

使用道具 举报

ID:765415 发表于 2021-4-30 00:11 | 显示全部楼层
楼主好厉害,不过有个问题想请教一下,霍尔传感器不是感应磁铁吗,你的风扇上好像没有,但是也能感应,请问是什么原理呢(⊙o⊙)?
回复

使用道具 举报

ID:889094 发表于 2021-4-30 08:19 来自手机 | 显示全部楼层
程序结构性很好,学习了,一点注释没有,放下一周再过来看就会费劲,像lcd1602显示部分,定时器初始化和中断服务部分,可以注释好形成单独文件或模块,便于再利用。另外没有说明晶振就直接出来的delay函数有点突兀
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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