基于STC89C52電位器式傳感器位移測量儀的設(shè)計(jì)
本文的位移測量儀的設(shè)計(jì)要求為:采集和處理測量電路的信號,顯示測量位移,測量范圍是0-50mm精度為0.1mm。設(shè)計(jì)能和計(jì)算機(jī)進(jìn)行通信的標(biāo)準(zhǔn)接口,并將測量數(shù)據(jù)發(fā)送到計(jì)算機(jī)。
位移傳感器模塊使用米朗科技KPM12型直線位移傳感器,它是一種非線繞電位器式傳感器,它也是一種線性電位器式傳感器,其原理相當(dāng)簡單,類似于滑動變阻器。 將計(jì)算機(jī)的波特率與單片機(jī)串口通信的波特率設(shè)置相同均為9600,完成了通信的相關(guān)初始化后,通過指令讓系統(tǒng)通過通信模塊完成數(shù)據(jù)的傳輸,最后再計(jì)算機(jī)串口調(diào)試助手可以看到測量結(jié)果。 關(guān)鍵詞: 位移傳感器;51單片機(jī);A/D轉(zhuǎn)換
單片機(jī)源程序如下:
- /*=============================================================*/
- #include<reg52.h> //器件配置文件
- #include <intrins.h>
- #include "lcd.h"
- #define u8 unsigned char
- #define u16 unsigned int
- #define uchar unsigned char
- #define uint unsigned int
-
- unsigned char voltage[] = {'0','0','0','.','0',0};
- unsigned int circuit,aa,bb,cc,dd,ac,setv1,setv2;
- float u,k;
- unsigned int j,ppm,cp;
- uint dat=0,shidu;
-
- void ConfigUART(unsigned int baud); //串行口配置函數(shù)
- void ConfigTimer0(); //定時(shí)器0配置函數(shù)
- void SendData(unsigned char ch); //字符發(fā)送函數(shù)
- void SendString(char *s); //字符串發(fā)送函數(shù)
- void AlarmJudge(void); //警報(bào)
- void delayms(unsigned int ms);
- void UartSend(); //串口數(shù)據(jù)發(fā)送函數(shù)
- //AD管腳
- sbit ADCS =P3^5;
- sbit ADCLK =P3^2;
- sbit ADDI =P3^3;
- sbit ADDO =P3^4;
- sbit Buzzer_P = P2^1; // 蜂鳴器的管腳
- sbit KEY = P1^3; // “設(shè)置”按鍵的管腳
- sbit KeyDown_P = P1^4; // 按鍵的管腳
- uint set_value = 30;
- uint set_value_count = 0; //警報(bào)設(shè)置菜單
- uint key_count=1;
-
- /***********************************
- 函數(shù)名: Adc0832
- 功能: 啟動AD轉(zhuǎn)換將值儲存于 dat
-
- ***********************************/
- unsigned int Adc0832(unsigned char channel)
- {
- uchar i=0;
- uchar j;
- uchar ndat=0;
- // uchar Vot=0;
- if(channel==0)channel=2; // 10
- if(channel==1)channel=3; // 11
-
- ADDI=1;
- _nop_();
- _nop_();
- ADCS=0; //拉低CS端 開始
- _nop_();
- _nop_();
- ADCLK=1; //拉高CLK端
- _nop_();
- _nop_();
- ADCLK=0; //拉低CLK端,形成下降沿1 第一個(gè)脈沖的下降沿,此前DIO必須是高電平
- _nop_();
- _nop_();
- ADCLK=1; //拉高CLK端
-
- ADDI=channel&0x1; //
-
- _nop_();
- _nop_();
-
- ADCLK=0; //拉低CLK端,形成下降沿2
-
- _nop_();
- _nop_();
-
- ADCLK=1;//拉高CLK端
-
- ADDI=(channel>>1)&0x1;
-
- _nop_();
- _nop_();
-
- ADCLK=0;//拉低CLK端,形成下降沿3
-
- ADDI=1;//控制命令結(jié)束 輸入端DI失去作用,應(yīng)置1
-
- _nop_();
- _nop_();
-
-
- dat=0;
-
- for(i=0;i<8;i++)
- {
- dat|=ADDO;//收數(shù)據(jù) (或)
- ADCLK=1;
- _nop_();
- _nop_();
- ADCLK=0;//形成一次時(shí)鐘脈沖
- _nop_();
- _nop_();
- dat<<=1; //左移一位
- if(i==7)dat|=ADDO; //將輸出數(shù)據(jù)DO通過或運(yùn)算儲存在dat最低位
- }
-
-
- for(i=0;i<8;i++) //驗(yàn)證
- {
- j=0;
- j=j|ADDO; //收數(shù)據(jù)
- ADCLK=1;
- _nop_();
- _nop_();
- ADCLK=0;//形成一次時(shí)鐘脈沖
- _nop_();
- _nop_();
- j=j<<7; //從 ADD0開始
- ndat=ndat|j;
- if(i<7)ndat>>=1;
- }
-
-
- ADCS=1;//拉低CS端
- ADCLK=0;//拉低CLK端
- ADDO=1;//拉高數(shù)據(jù)端,回到初始狀態(tài)
- dat<<=8;
- dat|=ndat;
- return(dat); //return ad data
- }
- void Conut(void)
- {
- circuit=shidu/256; // 數(shù)字量
-
- u=(float)circuit;
- k=(float)circuit;
- u=u*0.5977;
- u=u*10; //提取一位小數(shù)
- k=k*0.5977;
-
- cp=(int)k; // 警報(bào)值
-
- ppm=(int)u;
- aa=ppm/1000;
- bb=ppm%1000/100;
- cc=ppm%100/10;
- dd=ppm%10;
-
- setv1 = set_value/10;
- setv2 = set_value%10;
-
-
- voltage[0] = (char)('0'+ aa);
- voltage[1] = (char)('0'+ bb);
- voltage[2] = (char)('0'+ cc);
- voltage[4] = (char)('0'+ dd);
-
- }
- /***********************************
- 函數(shù)名: delayms()
- 功能: 延時(shí) ms 毫秒
- ***********************************/
- void DelayMs(uint time)
- {
- uint i,j;
- for(i=0;i<time;i++)
- for(j=0;j<112;j++);
- }
- /***********************************
- 函數(shù)名: LcdDisplay()
- ***********************************/
- void LcdDisplay(void)
- { LCD1602_write_com(0x80+3);
- LCD1602_write_word("KPM12-150mm");
-
- LCD1602_write_com(0x80+0+0x40);
- LCD1602_write_word(" ");
-
- LCD1602_write_com(0x80+2+0x40);
- LCD1602_write_word("X=");
- LCD1602_write_com(0x80+4+0x40);
- LCD1602_write_data(0x30+aa);
- LCD1602_write_com(0x80+5+0x40);
- LCD1602_write_data(0x30+bb);
- LCD1602_write_com(0x80+6+0x40);
- LCD1602_write_data(0x30+cc);
- LCD1602_write_com(0x80+7+0x40);
- LCD1602_write_word(".");
-
- LCD1602_write_com(0x80+8+0x40);
- LCD1602_write_data(0x30+dd);
- LCD1602_write_com(0x80+9+0x40);
- LCD1602_write_word("mm");
-
- LCD1602_write_com(0x80+12+0x40);
- LCD1602_write_word("!=");
- LCD1602_write_com(0x80+14+0x40);
- LCD1602_write_data(0x30+setv1);
- LCD1602_write_com(0x80+15+0x40);
- LCD1602_write_data(0x30+setv2);
-
-
- }
- void LcdDisplay2(void)
- {
- LCD1602_write_com(0x80+3+0x40);
- LCD1602_write_word("cccc");
-
- LCD1602_write_com(0x80+3);
- LCD1602_write_word("aaa");
-
-
- }
- /***********************************
- 函數(shù)名:AlarmJudge
- 警報(bào)
- ***********************************/
- void AlarmJudge(void)
- {
- if(cp > set_value)
- {
-
- Buzzer_P=0;
- delayms(50);
- Buzzer_P=1;
- delayms(50);
-
-
- }
- else
- {
- Buzzer_P=1;
-
- }
- }
- /* UART字符發(fā)送函數(shù) */
- void SendData(unsigned char ch)
- {
- SBUF = ch; //啟動發(fā)送
- while(!TI); //等待結(jié)束
- TI = 0;
- }
- /* UART字符串發(fā)送函數(shù) */
- void SendString(unsigned char *s)
- {
- while(*s) //循環(huán)發(fā)送
- {
- SendData(*s++);
- }
- }
- void UartSend()
- {
- SendString("x=");
- SendString(voltage);
- SendString("mm \r\n");
- }
- /* 串口配置函數(shù),baud-通信波特率 */
- void ConfigUART(unsigned int baud)
- {
- SCON = 0x50; //配置串口為模式1
- TMOD &= 0x0F; //清零T1的控制位
- TMOD |= 0x20; //配置T1為模式2
- TH1 = 256 - (11059200/12/32)/baud; //計(jì)算T1重載值
- TL1 = TH1; //初值等于重載值
- ET1 = 0; //禁止T1中斷
- ES = 1; //使能串口中斷
- TR1 = 1; //啟動T1
- EA = 1; //打開總中斷
- }
- /* UART中斷服務(wù)函數(shù) */
- void InterruptUART() interrupt 4
- {
- if(RI) //接收到字節(jié)
- {
- RI = 0; //清零接收中斷標(biāo)志位
- }
- if(TI) //字節(jié)發(fā)送完畢
- {
- TI = 0; //清零發(fā)送中斷標(biāo)志位
- }
- }
- /***********************************
- 主函數(shù)
- ***********************************/
- void main()
- {
- Init_LCD1602();
-
- ConfigUART(9600); //配置串行口工作模式及參數(shù)
-
-
-
- while(1)
- {
-
-
- shidu=Adc0832(0); //獲取AD值
- Conut(); //計(jì)算
-
-
- if(KEY==0) //按鍵
- {
-
- DelayMs(30);
- if(KEY==0) //去抖
- while(!KEY);
- {
- LCD1602_write_com(0x01); //清屏指令
- key_count++; //菜單計(jì)數(shù)
- }
-
- if(key_count==3)
- key_count=1;
- LCD1602_write_com(0x01); //清屏指令
-
- }
- if(key_count==1) //界面1
- {
-
- LcdDisplay();
-
-
-
- if(KeyDown_P==0) //判斷按鍵2
- {
-
- DelayMs(30);
- if(KeyDown_P==0)
- while(!KeyDown_P);
- {
- set_value_count++;
- set_value = set_value+10; //按一次+10mm
-
-
- }
-
- if(set_value_count==7)
- {
- set_value = 30;
- set_value_count=0;
-
- }
-
-
- }
-
- }
-
-
- if(key_count==2) //界面2
- {
-
- LcdDisplay2();
-
- }
-
-
- UartSend(); //串口發(fā)送
-
- for(j=0;j<30000;j++); //延時(shí)讀取
-
-
-
-
- AlarmJudge();
- }
- }
復(fù)制代碼
Keil代碼與Proteus仿真51hei附件下載:
位移傳感器.zip
(85.9 KB, 下載次數(shù): 20)
2022-8-26 20:46 上傳
點(diǎn)擊文件名下載附件
|