找回密码
 立即注册

QQ登录

只需一步,快速开始

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

基于电位器式传感器位移测量仪的设计-STC89C52单片机

[复制链接]
跳转到指定楼层
楼主
基于STC89C52电位器式传感器位移测量仪的设计
本文的位移测量仪的设计要求为:采集和处理测量电路的信号,显示测量位移,测量范围是0-50mm精度为0.1mm。设计能和计算机进行通信的标准接口,并将测量数据发送到计算机。

位移传感器模块使用米朗科技KPM12型直线位移传感器,它是一种非线绕电位器式传感器,它也是一种线性电位器式传感器,其原理相当简单,类似于滑动变阻器。
将计算机的波特率与单片机串口通信的波特率设置相同均为9600,完成了通信的相关初始化后,通过指令让系统通过通信模块完成数据的传输,最后再计算机串口调试助手可以看到测量结果。
关键词: 位移传感器;51单片机;A/D转换


单片机源程序如下:

  1. /*=============================================================*/
  2. #include<reg52.h>        //器件配置文件
  3. #include <intrins.h>
  4. #include "lcd.h"


  5. #define u8 unsigned char  
  6. #define u16 unsigned int
  7. #define uchar unsigned char
  8. #define uint unsigned int
  9.        






  10. unsigned char voltage[] = {'0','0','0','.','0',0};


  11. unsigned int circuit,aa,bb,cc,dd,ac,setv1,setv2;

  12. float u,k;

  13. unsigned int j,ppm,cp;

  14.         uint dat=0,shidu;

  15.        
  16. void ConfigUART(unsigned int baud);              //串行口配置函数
  17. void ConfigTimer0();                             //定时器0配置函数
  18. void SendData(unsigned char ch);                 //字符发送函数
  19. void SendString(char *s);                        //字符串发送函数
  20. void AlarmJudge(void);                                                                                                                //警报
  21. void delayms(unsigned int ms);
  22. void UartSend();                                                                 //串口数据发送函数

  23. //AD管脚

  24. sbit ADCS         =P3^5;
  25. sbit ADCLK  =P3^2;
  26. sbit ADDI         =P3^3;
  27. sbit ADDO         =P3^4;


  28. sbit Buzzer_P  = P2^1;                // 蜂鸣器的管脚

  29. sbit KEY  = P1^3;                // “设置”按键的管脚
  30. sbit KeyDown_P = P1^4;                // 按键的管脚

  31. uint set_value = 30;
  32. uint set_value_count = 0;                //警报设置菜单
  33. uint key_count=1;


  34.        
  35. /***********************************
  36. 函数名:   Adc0832
  37. 功能:    启动AD转换将值储存于 dat




  38.        
  39. ***********************************/





  40. unsigned int Adc0832(unsigned char channel)
  41. {
  42.                         uchar i=0;
  43.                         uchar j;

  44.                         uchar ndat=0;
  45.                 //        uchar  Vot=0;

  46.                         if(channel==0)channel=2;        //  10
  47.                         if(channel==1)channel=3;        //        11
  48.        
  49.         ADDI=1;
  50.                 _nop_();
  51.                 _nop_();
  52.         ADCS=0;                                //拉低CS端 开始
  53.                 _nop_();
  54.                 _nop_();
  55.         ADCLK=1;                        //拉高CLK端
  56.                 _nop_();
  57.                 _nop_();
  58.         ADCLK=0;                        //拉低CLK端,形成下降沿1  第一个脉冲的下降沿,此前DIO必须是高电平
  59.                 _nop_();
  60.                 _nop_();
  61.         ADCLK=1;                        //拉高CLK端
  62.        
  63.         ADDI=channel&0x1;                        //
  64.        
  65.                 _nop_();
  66.                 _nop_();
  67.                
  68.         ADCLK=0;                //拉低CLK端,形成下降沿2
  69.        
  70.         _nop_();
  71.         _nop_();
  72.        
  73.         ADCLK=1;//拉高CLK端
  74.        
  75.         ADDI=(channel>>1)&0x1;
  76.        
  77.         _nop_();
  78.         _nop_();
  79.        
  80.         ADCLK=0;//拉低CLK端,形成下降沿3
  81.        
  82.         ADDI=1;//控制命令结束 输入端DI失去作用,应置1
  83.        
  84.         _nop_();
  85.         _nop_();
  86.        
  87.        
  88.         dat=0;
  89.        
  90.         for(i=0;i<8;i++)
  91.         {
  92.                 dat|=ADDO;//收数据        (或)
  93.                 ADCLK=1;
  94.                 _nop_();
  95.                 _nop_();
  96.                 ADCLK=0;//形成一次时钟脉冲
  97.                 _nop_();
  98.                 _nop_();
  99.                 dat<<=1;                //左移一位
  100.                 if(i==7)dat|=ADDO;   //将输出数据DO通过或运算储存在dat最低位
  101.         }
  102.        
  103.        
  104.         for(i=0;i<8;i++)                //验证
  105.         {
  106.                 j=0;
  107.                 j=j|ADDO;                //收数据
  108.                 ADCLK=1;
  109.                 _nop_();
  110.                 _nop_();
  111.                 ADCLK=0;//形成一次时钟脉冲
  112.                 _nop_();
  113.                 _nop_();
  114.                 j=j<<7;                //从 ADD0开始
  115.                 ndat=ndat|j;
  116.                 if(i<7)ndat>>=1;
  117.         }
  118.        
  119.        
  120.         ADCS=1;//拉低CS端
  121.         ADCLK=0;//拉低CLK端
  122.         ADDO=1;//拉高数据端,回到初始状态
  123.         dat<<=8;
  124.         dat|=ndat;  


  125.         return(dat);            //return ad data
  126. }





  127. void Conut(void)
  128. {

  129.                  circuit=shidu/256;                // 数字量
  130.        
  131.         u=(float)circuit;
  132.         k=(float)circuit;
  133.                 u=u*0.5977;
  134.                 u=u*10;                                //提取一位小数
  135.                 k=k*0.5977;
  136.        
  137.         cp=(int)k;                // 警报值
  138.        
  139.         ppm=(int)u;
  140.         aa=ppm/1000;
  141.          bb=ppm%1000/100;
  142.         cc=ppm%100/10;
  143.          dd=ppm%10;
  144.        
  145.         setv1 = set_value/10;
  146.         setv2 = set_value%10;
  147.        
  148.        
  149.         voltage[0] = (char)('0'+ aa);
  150.         voltage[1] = (char)('0'+ bb);
  151.         voltage[2] = (char)('0'+ cc);
  152.         voltage[4] = (char)('0'+ dd);
  153.        


  154. }




  155. /***********************************
  156. 函数名:  delayms()
  157. 功能:    延时 ms 毫秒

  158. ***********************************/
  159. void DelayMs(uint time)
  160. {
  161.         uint i,j;
  162.         for(i=0;i<time;i++)
  163.                 for(j=0;j<112;j++);
  164. }

  165. /***********************************
  166. 函数名:  LcdDisplay()

  167. ***********************************/


  168. void LcdDisplay(void)
  169. {        LCD1602_write_com(0x80+3);

  170.         LCD1602_write_word("KPM12-150mm");
  171.        
  172.         LCD1602_write_com(0x80+0+0x40);
  173.         LCD1602_write_word("  ");
  174.        
  175.   LCD1602_write_com(0x80+2+0x40);
  176.         LCD1602_write_word("X=");
  177.         LCD1602_write_com(0x80+4+0x40);          
  178.         LCD1602_write_data(0x30+aa);
  179.         LCD1602_write_com(0x80+5+0x40);
  180.         LCD1602_write_data(0x30+bb);
  181.   LCD1602_write_com(0x80+6+0x40);          
  182.         LCD1602_write_data(0x30+cc);               
  183.         LCD1602_write_com(0x80+7+0x40);          
  184.         LCD1602_write_word(".");       
  185.        
  186.         LCD1602_write_com(0x80+8+0x40);
  187.         LCD1602_write_data(0x30+dd);       
  188.         LCD1602_write_com(0x80+9+0x40);
  189.         LCD1602_write_word("mm");
  190.        
  191.                 LCD1602_write_com(0x80+12+0x40);
  192.         LCD1602_write_word("!=");
  193.           LCD1602_write_com(0x80+14+0x40);          
  194.         LCD1602_write_data(0x30+setv1);               
  195.          LCD1602_write_com(0x80+15+0x40);          
  196.         LCD1602_write_data(0x30+setv2);               


  197.        
  198.        
  199. }

  200. void LcdDisplay2(void)
  201. {
  202.   LCD1602_write_com(0x80+3+0x40);
  203.         LCD1602_write_word("cccc");

  204.        
  205.         LCD1602_write_com(0x80+3);

  206.         LCD1602_write_word("aaa");

  207.        
  208.        
  209. }

  210. /***********************************
  211. 函数名:AlarmJudge
  212.                                                                                         警报

  213. ***********************************/
  214. void AlarmJudge(void)
  215. {                       
  216. if(cp > set_value)
  217.                 {
  218.                
  219.                         Buzzer_P=0;
  220.                         delayms(50);

  221.                         Buzzer_P=1;
  222.                         delayms(50);
  223.                        
  224.                        
  225.                 }
  226.         else
  227.         {
  228.                 Buzzer_P=1;
  229.        
  230.         }
  231. }


  232. /* UART字符发送函数 */
  233. void SendData(unsigned char ch)
  234. {
  235.     SBUF = ch;                                   //启动发送
  236.         while(!TI);                                  //等待结束
  237.         TI = 0;
  238. }



  239. /* UART字符串发送函数 */
  240. void SendString(unsigned char *s)
  241. {
  242.     while(*s)                                    //循环发送
  243.     {
  244.         SendData(*s++);
  245.     }
  246. }


  247. void UartSend()
  248. {
  249.         SendString("x=");
  250.         SendString(voltage);

  251.         SendString("mm \r\n");
  252. }

  253. /* 串口配置函数,baud-通信波特率 */
  254. void ConfigUART(unsigned int baud)
  255. {
  256.     SCON  = 0x50;                                //配置串口为模式1
  257.     TMOD &= 0x0F;                                //清零T1的控制位
  258.     TMOD |= 0x20;                                //配置T1为模式2
  259.     TH1 = 256 - (11059200/12/32)/baud;           //计算T1重载值
  260.     TL1 = TH1;                                   //初值等于重载值
  261.     ET1 = 0;                                     //禁止T1中断
  262.     ES  = 1;                                     //使能串口中断
  263.     TR1 = 1;                                     //启动T1
  264.                 EA = 1;                                      //打开总中断
  265. }


  266. /* UART中断服务函数 */
  267. void InterruptUART() interrupt 4
  268. {
  269.     if(RI)                                       //接收到字节
  270.     {
  271.         RI = 0;                                  //清零接收中断标志位
  272.     }
  273.     if(TI)                                       //字节发送完毕
  274.     {
  275.         TI = 0;                                  //清零发送中断标志位
  276.     }
  277. }

  278. /***********************************
  279. 主函数
  280. ***********************************/


  281. void main()
  282. {               


  283.         Init_LCD1602();
  284.        
  285.         ConfigUART(9600);                            //配置串行口工作模式及参数
  286.        
  287.        


  288.        
  289.         while(1)
  290.           {               
  291.                        
  292.                                        
  293.                         shidu=Adc0832(0);                                        //获取AD值
  294.                         Conut();                                                                        //计算       
  295.        
  296.                
  297.                          if(KEY==0)                                                                                //按键
  298.   {
  299.                
  300.   DelayMs(30);
  301.    if(KEY==0)                                                                                        //去抖
  302.    while(!KEY);
  303.         {        
  304.                 LCD1602_write_com(0x01);                        //清屏指令
  305.    key_count++;                                                                                //菜单计数
  306.         }
  307.        
  308.    if(key_count==3)
  309.                         key_count=1;
  310.           LCD1602_write_com(0x01);                        //清屏指令
  311.    
  312.   }

  313.   if(key_count==1)                                                //界面1
  314.   {
  315.                
  316.   LcdDisplay();
  317.                
  318.                
  319.                
  320.                  if(KeyDown_P==0)                                //判断按键2
  321.   {
  322.                
  323.                 DelayMs(30);
  324.    if(KeyDown_P==0)
  325.    while(!KeyDown_P);
  326.          {
  327.    set_value_count++;
  328.          set_value = set_value+10;                //按一次+10mm
  329.                  
  330.                
  331.          }
  332.          
  333.    if(set_value_count==7)
  334.          {
  335.                  set_value = 30;
  336.    set_value_count=0;
  337.          
  338.          }
  339.                

  340.    
  341.   }
  342.        
  343.   }
  344.        
  345.        
  346.   if(key_count==2)                                                        //界面2
  347.   {
  348.                
  349.                 LcdDisplay2();       
  350.                
  351.    }

  352.        
  353.                        
  354.                 UartSend();                              //串口发送
  355.                        
  356.                 for(j=0;j<30000;j++);                            //延时读取
  357.                        
  358.        
  359.        
  360.        
  361.           AlarmJudge();               
  362. }

  363. }         
复制代码

Keil代码与Proteus仿真51hei附件下载:
位移传感器.zip (85.9 KB, 下载次数: 20)

评分

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

查看全部评分

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

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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