制作出來的實物圖如下:
Altium Designer畫的原理圖和PCB圖如下:(51hei附件中可下載工程文件)
單片機源程序如下:
- #include<reg52.h>
- #define uint unsigned int
- #define uchar unsigned char
- #define ulong unsigned long
- sbit we0=P2^0; // 數碼管位定義
- sbit we1=P2^1; //
- sbit we2=P2^2; //
- sbit we3=P2^3;
- sbit fasong=P1^0; //超生波發送接口
- sbit jieshou=P3^2; //超聲波接受接口
- sbit k1=P3^6; //開關鍵
- sbit k2=P3^7; //溫度距離顯示切換鍵
- sbit ds=P1^4; //溫度傳感數據接口
- uchar timers,mi,fenmi,limi,num2,num1,shi,ge,shifen,shengsu;
- bit flag,kaiflag,temflag; //定義各種標志位
- ulong t,s; //接收時間和距離
- uint temp,num;
- float n; //18b20讀取數據時用
- uchar code table[]= //數碼管顯示編碼(不帶小數點and帶)
- {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
- 0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
- void init(); //聲明初始化函數
- void delay100us() //超聲波避盲區延時函數
- {
- uchar i,j;
- for(i=40;i>0;i--)
- for(j=248;j>0;j--);
- }
- void delay(uchar a) //短暫延時函數(用于18B20)
- {
- while(a>0)
- a--;
- }
- void shijian(uint x) //一毫秒延時函數
- {
- uint i,j;
- for(i=x;i>0;i--)
- for(j=110;j>0;j--);
- }
- void reset() //18B20復位
- {
- ds=0;
- delay(103);
- ds=1;
- delay(4);
- }
- void write(uchar date) //18B20寫一字節數據
- {
- uchar temp,i;
- uint j;
- temp=date;
- for(i=0;i<8;i++)
- {
- temp=temp>>1;
- if(CY) //寫1
- {
- ds=0;
- j++;j++;
- ds=1;
- delay(8);
- }
- else
- {
- ds=0;
- delay(8);
- ds=1;
- j++;j++;
- }
- }
- }
- uchar read() //18B20讀一字節數據
- {
- uchar j,dat;
- for(j=0;j<8;j++)
- {
- ds=0;
- dat>>=1;
- ds=1;
- delay(1);
- if(ds)
- dat|=0x80;
- delay(8);
- }
- return(dat);
- }
- uint get() //從溫度傳感器獲取數值
- {
- uchar gao,di;
- reset();
- shijian(1);
- write(0xcc);
- write(0x44);
- reset();
- shijian(1);
- write(0xcc);
- write(0xbe);
- di=read();
- gao=read();
- temp=gao<<8;
- temp=temp|di;
- n=temp*0.065+0.5;
- temp=n*10;
- return(temp);
- }
- void send() //超聲波發送函數
- {
- uchar i;
- while(TF0==0)
- { we0=0;
- timers++;
- fasong=~fasong;
- for(i=12;i>0;i--); //40hz延時
- if(timers==4) //連續發送兩個超聲波脈沖
- break;
- }
- we0=1;
- timers=0; //將發送次數歸零
- TH0=0X00; //定時器裝初值
- TL0=0X32; //裝0x32是因為發送時也占用了時間
- TR0=1; //打開計時器
- EX0=1; //打開外部中斷等待接收返回聲波
- delay100us(); //避盲延時
- delay100us();
- delay100us();
- // delay100us();
- // delay100us();
- }
- void keyscan() //鍵盤掃描
- {
- if(k1==0) //開關鍵按下
- {
- shijian(10);
- if(k1==0)
- kaiflag=~kaiflag; //開關標志位取反
- while(k1==0); //等待按鍵釋放
- }
- if(k2==0) //k2按下
- {
- shijian(10);
- if(k2==0)
- temflag=~temflag; //溫度距離標志位取反
- while(k2==0); //等待按鍵釋放
- }
- }
- void temdisplay() //溫度顯示函數
- {
- num=get(); //讀取當前溫度值
- shi=num/100; //分離出十位值
- ge=num%100/10; //分離出個位值
- shifen=num%10; //分離出十分位值
- P0=table[shi]; //十位顯示
- we1=0;
- we0=1;
- we2=1;
- we3=1;
- shijian(6);
- P0=table[ge+10]; //個位顯示
- we1=1;
- we0=1;
- we2=0;
- we3=1;
- shijian(6);
- P0=table[shifen]; //十分位顯示
- we3=0;
- we1=1;
- we0=1;
- we2=1;
- shijian(1);
- }
- void init() //初始化函數
- {
- TMOD=0x21; //定時器1為8位自動重裝模式,
- //定時器0為十六位計數器
- TH0=0X00; //定時器0裝初值
- TL0=0X32;
- TH1=0x00; //定時器裝空值
- TL1=0x00;
- TR1=0; //關閉顯示定時
- TR0=0; //關閉定時器0計時
- EA=1; //打開總中斷
- ET0=1; //打開計時中斷
- ET1=1; //打開定時器1中斷
- EX0=1; //打開外部中斷
- IT0=1; //外部中斷選擇下降沿觸發
- P2=0xff;
- P0=0xff; //關閉數碼管段選
- kaiflag=0; //開標志位置0
- temflag=0; //溫度距離標志位置0
- }
- void main() //主函數
- {
- init(); //進行初始化
- while(1)
- {
- keyscan(); //鍵盤掃描
- if((kaiflag==1)&&(temflag==1))//如果打開并且選擇測溫
- {
- temdisplay(); //進行溫度顯示
- TR1=0; //將定時器都關閉
- TR0=0;
- EX0=0;
- }
- if((kaiflag==1)&&(temflag==0)) //如果打開并選擇測距
- {
- send(); //發送脈沖
- num=get(); //讀取溫度值
- TR1=1; //打開測距顯示中斷
- }
- if(kaiflag==0) //如果處于關閉狀態
- {
- TR1=0;
- TR0=0; //測距顯示關閉
- init(); //進行初始化
- }
- }
- }
- /*******************對下面用到的中斷的解釋************
- 1.外部中斷0用來接收返回的脈沖,當接收到以后進行中斷處理,優先級最高;
- 2.定時器0用來計時,選擇的是十六位定時模式;用來計算超聲波脈沖
- 從發射到接受所用的時間。
- 3.定時器1用來作為測試距離的顯示定時。每中斷一次就掃描一位數碼管
- *********************************************************/
- void IN0() interrupt 0 //超聲波接收中斷(外部)
- {
- TR0=0; //關閉設計時器
- EX0=0; //停止接收返回脈沖
- if(num<=50) //根據當前溫度值來調整聲速
- {
- shengsu=165;
- }
- else if(num<=100)
- {
- shengsu=169;
- }
- else if(num<=200)
- {
- shengsu=172;
- }
- else if(num<=300)
- {
- shengsu=175;
- }
- else if(num<=500)
- {
- shengsu=180;
- }
- t=TH0*256+TL0; //計算從發射到接收用時(單位us)
- s=t*shengsu/10000; //根據時間計算距離
- mi=s/100; //分離出米
- fenmi=s%100/10; //……分米
- limi=s%10; //……厘米
- EX0=1; //計算完畢允許接收下個脈沖
- }
- void timer0() interrupt 1
- {
- TR0=0;
- TH0=0;
- TL0=0;
- }
- void timer1() interrupt 3 //顯示測距距離中斷
- {
- TH1=0x00; //裝初值
- TL1=0x00;
- num1++;
- if(num1==5) //如果經過1250us,顯示一位
- {
- num1=0;
- shijian(2);
- num2++;
- if(num2==4)
- num2=0;
- }
- if(temflag==0)
- {
- if(num2==0)
- {
- P0=table[mi+10];
- we1=0;
- we0=1;
- we2=1;
- we3=1;
- }
- if(num2==2)
- {
- P0=table[fenmi];
- we1=1;
- we0=1;
- we2=0;
- we3=1;
- }
- if(num2==3)
- {
- P0=table[limi];
- we3=0;
- we1=1;
- we0=1;
- we2=1;
- }
- }
- }
復制代碼
所有資料51hei附件下載:
原理圖和pcb.7z
(156.28 KB, 下載次數: 95)
2021-10-18 22:11 上傳
點擊文件名下載附件
|