51hei.png (67.36 KB, 下載次數: 85)
下載附件
2021-10-15 22:51 上傳
單片機源程序如下:
- #include <AT89X52.H>
- #define uint unsigned int
- #define uchar unsigned char
- uchar dispbuf[4]={0,0,0,0};
- unsigned long L;
- uchar code table0[]={0xA0,0xBB,0x62,0x2A,0x39,0x2C,0x24,0xBA,
- 0x20,0x28,0x30,0x25,0xE4,0x23,0x64,0x74};
- /*超聲波定義*/
- sbit FS=P1^0; //發射端口
- uchar t,comkou;
- uint display;
- /**************************************************
- //延時子函數
- **************************************************/
- void delay100us(void) //延時子函數
- {
- uchar i,j;
- for(i=40;i>0;i--)
- for(j=248;j>0;j--);
- }
- void csfs(void) //超聲波發送
- {
- uchar times=0;
- while(TF0==0) // TF1定時器1 溢出標志位 使用查詢法
- {
- uchar j;
- for(j=12;j>0;j--); //延時
- FS=~FS;
- times++; //翻轉20次,發送10個脈沖信號的超聲波
- TF0=0;
- if(times==10) break;
- }
- times=0;
- TH0=0x00;
- TL0=0x00;
- EX0=1; //外部中斷0允許中斷位
- TR0=1; //開定時器1
- ET0=1; //定時器T1中斷允許位
- delay100us();
- }
- /*
- 發送的數據以厘米為單位,測量的距離為1000CM所以一個八位的二進制不夠的,
- 在此使用的是兩個16進制的數,但是發送一個數據要有起始位,如果使用BCD碼
- 則可以把起始位為0xff,之后的數據分別傳送個位,十位,百位,這樣的話標志
- 位一個就可以了。但是由于數據比較少,標志位定義為兩個oxff,和0xf0,只要
- 上位機檢測到起始的兩個16進制的數為0xfff0,則后面的兩個為則是傳送的數據,
- 因為傳送的值十進制最大為1000 ,則數據為不可能出現0xfff0;所以在發送數據
- 之前先發送0xfff0作為起始標志
- */
- void fasong(uint juli)
- {
- SBUF=0xff; //標志位
- while(TI==0);
- TI=0;
- SBUF=0xf0; //標志位
- while(TI==0);
- TI=0;
- SBUF=juli/255; //數據的高八位
- while(TI==0);
- TI=0;
- SBUF=juli%255; //數據的低八位
- while(TI==0);
- TI=0;
- }
- /***********************************************
- //初始化程序
- ***********************************************/
- void init()
- {
- TMOD=0x21; //設置定時器0和1為工作方式1(及16位定時器/計數器)
- T2MOD=0x00; /*定時器2為工作模式 */
- T2CON=0x04; /*定時器2為16位自動重裝定時工作模式, TR2=1 */
- SCON = 0x50;//
- PCON=0x80; //波特率加倍
- TH1 = 0xF4; //波特率:4800 11.0592MHz
- IE |= 0x90; //開中斷
- TR1 = 1; //啟動T1
- RCAP2L=(65536-4000)%256;//給定時器T2裝初值,計滿后把RCAP2L和RCAP2H自動裝入TH0,,TL0;;;;
- RCAP2H=(65536-4000)/256;
- TH0=0x00;
- TL0=0x00;
- IT1=1; //邊沿觸發方式
-
- ET0=1; //開定時器1中斷
- ET2=1; //開定時器2中斷
- EX0=1;
- TR0=1; //啟動定時器1
- TR2=1; //定時器2,啟動定時器2,過了
- EA=1; //開總中斷
- }
- /***************************************************
- //主函數
- ***************************************************/
- void main(void)
- {
- init(); //初始化
- while(1) //程序在這里不停地掃描同時等待中斷發生
- {
- csfs(); //超聲波發送
- dispbuf[0]=display/1000;//更新數碼管顯示緩沖區
- dispbuf[1]=display%1000/100;
- dispbuf[2]=display%1000%100/10;
- dispbuf[3]=display%1000%100%10;
- }
-
- }
- void int0(void) interrupt 0 using 0 //超聲波接收中斷程序
- {
- // float v;
- unsigned long time;
- EX0=0; //關閉超聲波接收
- TR0=0;//關定時器T0
- ET0=0;//中斷關閉
- time=TH0*256+TL0; //算出t的值,t的單位為us
- time=(int)time*0.9216;
- L=(time+240)*345; //計算出距離,240是發射超聲波所用的時間
- L=L/10000; //將距離轉化為以厘米為單位
- TH0=0x00; //定時器清零
- TL0=0x00;
- }
- void t0(void) interrupt 1 using 0 //超時中斷程序//
- {
- EX0=0;
- TR0=0;//關定時器//
- ET0=0;// 中斷關閉
- TH0=0x00;
- TL0=0x00;
- }
- void t2(void) interrupt 5
- {
- uchar i;
- uint a[3];
- RCAP2L=(65536-4000)%256; //給定時器T2裝初值,計滿后把RCAP2L和RCAP2H自動裝入TH2,TL2
- RCAP2H=(65536-4000)/256;
- TF2=0; //T2定時器必須用軟件清0
- t++;
- comkou++;
- if(comkou==20)
- {
- a[i]=L; //距離賦a[i]
- comkou=0;
- i++;
- if(i==4)
- {
- i=0;
- display=(a[0]+a[1]+a[2])/3; //數字平均濾波
- fasong(display); //測量距離發送上位機
- }
- }
- if(t==5) t=1;//數碼管顯示一遍,重新開始
- switch(t) //數碼管顯示
- {
- case 1: P0=table0[dispbuf[0]]; P2=0xfe; break; //分離出距離的千位,并在第一位數碼管上顯示
- case 2: P0=table0[dispbuf[1]]; P2=0xfb; break; //分離出距離的百位,并在第二位數碼管上顯示
- case 3: P0=table0[dispbuf[2]]; P2=0xf7; break; //分離出距離的十位,并在第三位數碼管上顯示
- case 4: P0=table0[dispbuf[3]]; P2=0xfd; break; //分離出距離的個位,并在第四位數碼管上顯示
- }
- }
復制代碼
51hei.png (23.21 KB, 下載次數: 58)
下載附件
2021-10-15 22:50 上傳
上圖PCB還未完成
下面是代碼和原理圖下載,大家一起完善:
資料.7z
(475.17 KB, 下載次數: 26)
2021-10-15 22:53 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|