『壹』 51單片機控制的超聲波測距儀程序
希望對你有幫助
//超聲波模塊顯示程序
#include <reg52.h> //包括一個52標准內核的頭文件
#define uchar unsigned char //定義一下方便使用
#define uint unsigned int
#define ulong unsigned long
sbit Tx = P3^3; //產生脈沖引腳
sbit Rx = P3^2; //回波引腳
uchar code SEG7[10]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};//數碼管0-9
uint distance[4]; //測距接收緩沖區
uchar ge,shi,,temp,flag,outcomeH,outcomeL,i; //自定義寄存器
bit succeed_flag; //測量成功標志
//********函數聲明
void conversion(uint temp_data);
void delay_20us();
void pai_xu();
void main(void) // 主程序
{ uint distance_data,a,b;
uchar CONT_1;
i=0;
flag=0;
Tx=0; //首先拉低脈沖輸入引腳
TMOD=0x11; //定時器0,定時器1,16位工作方式
TR0=1; //啟動定時器0
IT0=0; //由高電平變低電平,觸發外部中斷
ET0=1; //打開定時器0中斷
EX0=0; //關閉外部中斷
EA=1; //打開總中斷0
while(1) //程序循環
{
EA=0;
Tx=1;
delay_20us();
Tx=0; //產生一個20us的脈沖,在Tx引腳
while(Rx==0); //等待Rx回波引腳變高電平
succeed_flag=0; //清測量成功標志
EX0=1; //打開外部中斷
TH1=0; //定時器1清零
TL1=0; //定時器1清零
TF1=0; //
TR1=1; //啟動定時器1
EA=1;
while(TH1 < 30);//等待測量的結果,周期65.535毫秒(可用中斷實現)
TR1=0; //關閉定時器1
EX0=0; //關閉外部中斷
if(succeed_flag==1)
{
distance_data=outcomeH; //測量結果的高8位
distance_data<<=8; //放入16位的高8位
distance_data=distance_data|outcomeL;//與低8位合並成為16位結果數據
distance_data*=12; //因為定時器默認為12分頻
distance_data/=58; //微秒的單位除以58等於厘米
} //為什麼除以58等於厘米, Y米=(X秒*344)/2
// X秒=( 2*Y米)/344 ==》X秒=0.0058*Y米 ==》厘米=微秒/58
if(succeed_flag==0)
{
distance_data=0; //沒有回波則清零
}
distance[i]=distance_data; //將測量結果的數據放入緩沖區
i++;
if(i==3)
{
distance_data=(distance[0]+distance[1]+distance[2]+distance[3])/4;
pai_xu();
distance_data=distance[1];
a=distance_data;
if(b==a) CONT_1=0;
if(b!=a) CONT_1++;
if(CONT_1>=3)
{ CONT_1=0;
b=a;
conversion(b);
}
i=0;
}
}
}
//***************************************************************
//外部中斷0,用做判斷回波電平
INTO_() interrupt 0 // 外部中斷是0號
{
outcomeH =TH1; //取出定時器的值
outcomeL =TL1; //取出定時器的值
succeed_flag=1; //至成功測量的標志
EX0=0; //關閉外部中斷
}
//****************************************************************
//定時器0中斷,用做顯示
timer0() interrupt 1 // 定時器0中斷是1號
{
TH0=0xfd; //寫入定時器0初始值
TL0=0x77;
switch(flag)
{case 0x00:P0=ge; P2=0x7f;flag++;break;
case 0x01:P0=shi;P2=0xbf;flag++;break;
case 0x02:P0=;P2=0xdf;flag=0;break;
}
}
//顯示數據轉換程序
void conversion(uint temp_data)
{
uchar ge_data,shi_data,_data ;
_data=temp_data/100 ;
temp_data=temp_data%100; //取余運算
shi_data=temp_data/10 ;
temp_data=temp_data%10; //取余運算
ge_data=temp_data;
_data=SEG7[_data];
shi_data=SEG7[shi_data]&0x7f;
ge_data =SEG7[ge_data];
EA=0;
= _data;
shi = shi_data;
ge = ge_data ;
EA=1;
}
//******************************************************************
void delay_20us()
{ uchar bt ;
for(bt=0;bt<60;bt++);
}
void pai_xu()
{ uint t;
if (distance[0]>distance[1])
{t=distance[0];distance[0]=distance[1];distance[1]=t;}
if(distance[0]>distance[2])
{t=distance[2];distance[2]=distance[0];distance[0]=t;}
if(distance[1]>distance[2])
{t=distance[1];distance[1]=distance[2];distance[2]=t;}
}
『貳』 求大神幫我用C語音寫一個51單片機超聲波的程序
#包括:QUOT;為reg51.h&QUOT;
SBIT P10 = P1 ^ 0;
無效initTimer(無效)
TMOD =為0x10; TH1 = 0X0B;
TL1 = 0xE0指令;
定時器無效(無效)中斷3
TH1 = 0X0B;
TL1 = 0xE0指令;
P10 =10頁;
無效的主要(無效)
initTimer();
TR1 = 1;
ET1 = 1;
EA = 1;
而(1);
}
『叄』 求C51單片機程序,關於超聲波測距儀
看下這個
原文http://www.elecfans.com/article/87/82/2009/20091219139294.html
基於單片機的倒車防撞預警系統設計和實現
0 引 言
汽車倒車防撞預警系統即是俗稱的倒車雷達,是汽車泊車輔助裝置。在汽車倒車時,倒車雷達採用超聲波測距原理探測汽車尾部離障礙物的距離,當汽車尾部離障礙物的距離達到探測范圍時,倒車雷達通過數碼管實時動態顯示距離。當汽車尾部離障礙物的距離達到設定的安全警告值時,倒車雷達發出報警聲,以警示駕駛員,輔助駕駛員安全倒車。現在生產的中高檔小轎車大多數都配置有倒車雷達,而出於節省成本等方面的考慮,經濟型小轎車、大客車等其他車輛都沒有配置倒車雷達。有市場需求的產品,必然會帶動產品的開發設計。倒車雷達電路種類較多,本文介紹基於單片機控制的倒車雷達系統,該系統採用通用型單片機作為控制電路,方便系統功能擴展。系統電路主要採用集成器件構成,外圍元件少,電路簡潔、調試方便、成本低,利於商品化生產。
1 系統組成及工作原理
倒車防撞預警系統由四路收發一體封閉(防水)型超聲波感測器及其超聲波發射與回波接收電路、超聲波電信號放大電路、單片機控制電路、LED數碼管顯示電路和蜂鳴器聲音報警電路組成。系統組成框圖如圖1所示。
當汽車倒車時由倒車換擋裝置自動接通系統電源,系統上電復位,進入工作狀態。單片機編程產生一串40 kHz的矩形脈沖電壓,經四選一模擬開關加到超聲波發射與回波接收電路,經放大驅動超聲波感測器發射出超聲波,同時單片機開始計時。發射出的超聲波碰到障礙物後形成反射波,部分反射波返回作用於超聲波感測器,經超聲波感測器的聲/電轉換,變成微弱的電信號,該微弱的電信號經放大、整形產生負跳變電壓,向單片機發出中斷申請。單片機收到中斷申請的信號後,立即響應中斷,執行外部中斷服務程序,停止計時,得到超聲波發送和返回的時間T,計算出發射點離障礙物的距離S,即:S=(C·T)/2。C是超聲波在空氣中的傳播速度,在常溫25℃時,C約為346 m/s。若發射出的超聲波在測距范圍內未遇到障礙物,直到單片機定時中斷產生,執行定時中斷服務程序,選擇下一路,依次按後左路、後左中路、後右中路、後右路的順序繼續發射和接收超聲波,並經過計算處理。四路探測處理完畢,選擇四路中測出的最小距離值通過LED數碼管顯示出來。當最小距離值小於預先設定的報警距離時,單片機接通蜂鳴器的電源,蜂鳴器發出報警聲。若四路探測無回波中斷申請,則顯示「-.--」,表明在安全距離內沒有障礙物,再繼續下一輪的循環探測處理。
2 系統硬體電路的設計
2.1 超聲波發射與回波接收電路
超聲波發射與回波接收電路的主要作用是提高驅動超聲波感測器的脈沖電壓幅值,有效地進行電/聲轉換,增大超聲波的發射距離,並通過收發一體的超聲波感測器將返回的超聲波轉變成微弱的電信號。超聲波發射與回波接收電路如圖2所示(畫出一路,其他三路與該路一樣)。
EFR40RS是收發一體封閉(防水)型超聲波感測器,其中心頻率f0=(40.0±1.0)kHz,-3 dB帶寬1 kHz。驅動電壓峰一峰值要求60~150 V。CD4052是雙路四選一模擬開關,單片機的P3.4和P3.5埠輸出選通信號,單片機的P3.3埠輸出一串40 kHz的脈沖電壓,通過CD4052的X路加到選通的開關三極體Q1基極,經脈沖變壓器T1升壓至100 VP-P左右,驅動超聲波感測器EFR40RS發射超聲波。發射時的脈沖電壓幅值大小直接影響測距的遠近,應採用超聲波專用的脈沖變壓器。反射回的超聲波經原收發一體封閉型超聲波感測器變成毫伏級的一串脈沖電信號。由於回波電信號的幅值小,VD3和VD4二極體截止,該信號不會通過T1變壓器副邊線圈形成短路。VD1和VD2二極體也截止,所以回波電信號經R1和C1,通過CD4052的Y路送到超聲波電信號放大與整形電路。R1和VD1,VD2組成雙向限幅電路,避免發射時的大信號造成超聲波放大與整形電路阻塞,甚至損壞電路。
2.2 超聲波電信號放大電路
超聲波電信號放大電路採用集成電路CX20106A構成。CX20106A是日本索尼公司生產的紅外遙控信號接收集成電路。通過外部所接電阻,將其內部帶通濾波電路的中心頻率f0設置為40 kHz,就可以接收放大超聲波電信號,並整形輸出負脈沖電壓。
應用電路如圖3所示。1腳是超聲波電信號輸入端,2腳與地之間連接RC串聯網路,是內部前置放大電路負反饋網路的組成部分。電阻R5的數值確定前置放大電路的增益。R5電阻值減小,負反饋減弱,放大倍數增大;反之,則放大倍數減小。3腳與地之間連接檢波電容C3,適當改變電容C3的大小,可以改變超聲波電信號放大和整形電路的靈敏度和抗干擾能力。C3電容量大,靈敏度低,抗干擾能力強;C3容量小,靈敏度高,抗干擾能力弱,易造成誤動作。5腳與電源間接入一個電阻,用以設置內部帶通濾波電路的中心頻率f0。
當R6=200 kΩ時,f0=40 kHz。6腳與地之間接一個積分電容,標准值為330 pF。如果該電容值取得太大,會使探測距離變短。7腳是電路集電極開路輸出端,R7是該引腳的上拉電阻。集成電路CX20106A無信號輸入時,7腳輸出高電平,當輸入的超聲波電信號經放大、整形後,7腳輸出一個負脈沖電壓。
2.3 單片機控制電路和顯示、報警電路
電路如圖4所示。由於系統用到單片機的輸入/輸出埠不多,在不考慮功能擴展時,從功能夠用和低成本的角度考慮,採用AT89C2051單片機作為控制電路的核心器件。AT89C2051單片機共有20個引腳,其中有15個I/O埠(P3.6無引出腳)。兩個16位定時器/計數器,其體積小、價格低。採用12 MHz高精度的晶振,以獲得較穩定的時鍾頻率,減小測量誤差。單片機的P3.3埠周期性的輸出一串40 kHz的矩形脈沖,通過雙路四選一模擬開關CD4052周期性地加到四路超聲波發射與回波接收電路。單片機的P3.4和P3.5埠輸出雙路四選一模擬開關CD4052的選通信號。單片機的P3.2埠為外部中斷0中斷申請信號輸入端。三位LED數碼管採用動態掃描顯示。U4的小數點常亮,U4的單位為m,U5的單位為dm,U6的單位為cm。採用有源蜂鳴器作為報警發音器件,一是器件成本低,二是便於動態掃描顯示的軟體編程。
3 系統軟體的設計
系統軟體採用模塊化設計,方便擴展移植。採用匯編語言編程。主要有主程序、T0中斷服務程序、外部中斷0服務程序、超聲波發生子程序。
3.1 主程序
本系統有四路測距通道,採用分時工作,按後左一後左中一後右中一後右順序循環測距。每一路發射超聲波後的等待外部中斷時間應大於超聲波在最大有效探測距離內往返時間。所以按最大有效探測距離可以估算出最短的循環間隔時間。因為超聲波在空氣中傳播能量會不斷衰減,所以超聲波測距存在最大有效探測距離。這最大有效探測距離與多種因數有關:
與超聲波感測器性能的好壞、與驅動超聲波感測器的脈沖電壓幅值(功率)的大小、障礙物大小和形狀、障礙物吸波特性以及反射波與入射波之間的夾角、與超聲波放大和整形電路的靈敏度等有關。設定最大有效探測距離為8 m(收發一體封閉型超聲波感測器比較難達到,實際上也沒有必要探測很遠的障礙物,只是設計留有裕量。由於顯示位數有限,也必須對最大探測距離做限制),則循環工作的間隔時間Tm=2S/C=2×8/346A46 ms,加上避免接收超聲波感測器余振的延時和程序執行時間,留足裕量,設定Tm△56 ms。
主程序流程圖如圖5所示。首先是對系統初始化。埠p1.0、P3.3置0;設置堆棧,中斷允許總控制位EA允許中斷(EA=1);允許外部中斷0中斷(EX0=1),採用邊沿觸發方式(IT0=1);設置定時器T0允許中斷(ET0=1),以16位工作方式定時約56 ms;設置定時器T1以16位工作方式定時/計數,計數初值0000H,然後啟動T0定時。設置顯示數據初值為三位BCD碼999(cm),對應字形段碼顯示「---」。四路探測處理完畢後,將四組數據中的最小值送入顯示緩沖區,通過LED數碼管顯示。同時該值與設定的100 cm值比較,若四組數據中的最小值小於100 cm,P3.7埠置0,Q2三極體導通,有源蜂鳴器得電發出報警聲。
由於單片機採用12 MHz的晶振,1個機器周期為1μs,所以計數器每計一個數就是1μs,定時器T1工作模式設置為16位定時/計數器模式,則其最大定時65.536 ms。由於定時器T0每56 ms產生中斷,執行T0中斷服務程序時停止T1計時,所以T1計時不會產生溢出中斷。一輪四路探測處理完畢所用時間大約是56 ms×4=224 ms,用時很短,而倒車速度又比較慢,所以可以做到實時動態顯示。
3.2 T0中斷服務程序
T0中斷服務程序流程圖如圖6所示。每隔56 ms分別按後左→後左中→後右中→後右順序選通下一路超聲波發射與回波接收電路,調用超聲波發生子程序,送出16個40 kHz的超聲波脈沖電壓,定時器T1開始計時,定時器T0開始定時56 ms,使每路工作56 ms。
為了避免接收到超聲波感測器余振的直射波產生的中斷申請,延時2.8 ms後,才允許外部中斷0中斷,等待接收返回的超聲波信號。所以,最小探測距離(盲區)Smin=Ct/2=346×0.002 8/2△0.48 m。四路探測處理完畢,將四路中最小值送入顯示緩沖區。若在四路探測中有些路在有效探測范圍內發射的超聲波未遇障礙物,無返回波,外部中斷0不產生中斷申請信號,或者是進入探測盲區,外部中斷0產生的中斷申請不被受理,則定時器T1計時到定時器T0產生中斷,在T0中斷服務程序中,用三位BCD碼999(三位十進制數最大值999 cm)置夠四組數據。若顯示緩沖區的四組數據都是999時,則對應字形段碼顯示「---」。倒車伊始,LED數碼顯示器就顯示「-.--」,表明在安全距離內沒有障礙物;若發出報警聲後,又顯示「-.--」,表明進入了探測盲區。
3.3 外部中斷0服務程序
外部中斷O服務程序流程圖如圖7所示。單片機一旦接收到返回超聲波信號(即INT0引腳由高電平跳變為低電平),立即進入外部中斷0服務程序。首先停止定時器T1計時,禁止外部中斷0中斷。然後將定時器T1中的數N,也即將超聲波往返所用的時間N(單位:μs),按式S=CT/2=(346 x N×10-6)/2=173×N÷10 000計算,即得被測物的距離(單位:cm),將計算結果以百位、十位、個位BCD碼方式送入比較大小的緩沖區,以備比較大小使用。然後等待定時器T0定時56 ms中斷的產生,繼續下一路的探測處理。
3.4 超聲波發生子程序
超聲波發生子程序通過P3.3埠發送16個周期是25μs(即頻率40 kHz,1個周期內高電平持續13μs、低電平持續12 μs)的矩形脈沖電壓。脈沖串個數在10~20個比較合適。脈沖個數太少,發射強度小,探測距離短;脈沖個數太多,發射持續時間長,在離障礙物距離近時,脈沖串尚未發射完畢,先發射出去的脈沖產生的回波就到達接收端,影響測距結果,造成測距盲區增大。
4 實現應用分析
本系統在實驗室條件下進行了可行性的研究設計,要實際應用中就必須考慮測量精度和工作穩定性的問題。因此,本系統可採取幾項措施來提高測量精度和工作穩定性。
(1)超聲波的傳播速度與溫度有關。為了適應不同環境溫度下的測距需要,提高測量精度,硬體電路上可增加檢測車外環境溫度的環節。單片機根據實測的溫度值,再計算確定超聲波的傳播速度,即C=331.4+0.6lt。t是環境溫度。或者在不增加硬體成本情況下,可考慮通過實驗數據分析,找到測量值與實際值偏差特點和規律,通過軟體編程對測量數據進行校正處理。
(2)軟體設計中採用數字濾波中的算術平均濾波程序對每個測距點進行連續多次測量,取平均值作為該測距點的測量數據,以提高數據采樣的可靠性。要盡量減小探測盲區,所設定的延時時間可根據實際所用超聲波感測器余振時間而定,可在實際調試中確定最小延時時間。
(3)倒車雷達安裝在車上,倒車雷達的工作環境非常惡劣,汽車倒車工作時,高壓點火產生很強的電磁輻射,會影響電路正常工作。所以在硬體及軟體方面要考慮採取抗干擾措施,提高系統工作的可靠性。如用金屬殼屏蔽電路,採用屏蔽線連接超聲波感測器;在滿足測量距離的情況下,可適當調大超聲波電信號放大和整形電路中檢波電容C3的容量。硬體上可增加「看門狗」電路,軟體設計添加指令冗餘、軟體陷阱、或設置軟體「看門狗」,防止程序「跑飛」或者進入死循環。對於駕駛員來說,倒車時主要關心的是車後方有無障礙物、以及障礙物離車大約有多遠等問題。由於車子制動時存在慣性,倒車遇到障礙物時,駕駛員總要提前制動。考慮性價比,倒車雷達測量精度不必很高。但從倒車安全考慮,此時的測量顯示值寧大勿小。
5 結 語
本系統充分利用了單片機的內部資源,用軟體編程產生超聲波矩形脈沖,代替硬體的超聲波發生電路,節省了硬體成本。採用一塊集成器件實現超聲波接收放大和整形,避免了採用多級集成運放組成高增益放大電路易產生自激等問題。實驗表明設計可行。在不增加硬體成本時,通過完善軟體設計,可提高系統測量精度和工作的可靠性,能夠滿足使用要求。在考慮功能擴展時,可以採用帶「看門狗」的AT89S52單片機,以增加擴展埠。在超聲波測距的基礎上,如可增加防盜報警功能、車載蓄電池電壓檢測功能等,若增加微型攝像頭和小型液晶顯示器,便成為可直接觀察車後方的可視倒車雷達。本系統實用性強,性價比高。
『肆』 求超聲波發生器的單片機源代碼
//設計:ch314156
//模塊使用方法:一個控制口發一個10US以上的高電平,就可以在接收口等待高電平輸出.
//一有輸出就可以開定時器計時,當此口變為低電平時就可以讀定時器的值,此時就為此次測
//距的時間,方可算出距離.如此不斷的周期測,就可以達到你移動測量的值了
//波特率9600(晶振12M)
#include <reg52.h>
#include <intrins.h> //調用 _nop_(); 延時函數
#define uchar unsigned char
#define uint unsigned int
sbit trigger=P2^0; //觸發引腳
sbit rx=P2^1; //接收引腳
sbit key=P3^6; //按鍵
unsigned char key_scan(void);
uchar chaoshengbo(void);
void uart_init(void);
void uart(uchar distance);
void chaoshengbo_init(void);
uchar distance; //距離
void main()
{
uart_init(); //串口初始化
chaoshengbo_init(); //超聲波初始化
uart('A') ; //串口發送'A'
while(1)
{
if (key_scan() == 1) //按鍵按下
{
distance = chaoshengbo(); //超聲波測距
uart(distance); //串口發送距離 單位厘米
}
}
}
unsigned char key_scan(void) //按鍵查詢
{
unsigned char on = 0,i;
while(1)
{
if(key==0) //判斷是否按下
{
for(i=0;i<100;i++); //軟體延時
if(key==0) //再次判斷是否按下
{
on = 1;
break; //跳出循環
}
}
}
while(key==0);
return 1;
}
void uart_init(void) //串口初始化,用的是T1
{
TMOD=TMOD & 0x0f | 0x20;
TH1=0Xfd; //波特率9600(晶振12M)
TL1=0Xfd;
TR1=1;
REN=1;
SM0=0;
SM1=1;
}
void uart(uchar distance) //發送一個位元組
{
SBUF = distance;
while(!TI);
TI = 0;
}
void chaoshengbo_init(void) //超聲波初始化
{
trigger = 0;
}
uchar chaoshengbo(void) //超聲波測距,返回厘米值
{
trigger=1; //給至少10us的高電平信號
_nop_();
_nop_();
_nop_(); //延時
_nop_();
_nop_();
_nop_();
TMOD=TMOD & 0xf0 |0x01; //T0初始化
TH0=0X0;
TL0=0X0;
trigger=0;
while(!rx); //等待上升沿
EA = 0; //關中斷
TR0=1; //開啟T0定時器
while(rx); //等待下降沿
TR0=0; //關閉T0定時器
EA = 1; //開中斷
return (TH0*256+TL0)*0.034/2; //計算距離 單位厘米
}
『伍』 急需「基於cx20106的超聲波測距的源程序",用1602顯示,51單片機C語言編程!!! 謝謝
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
//===============================LCD1602介面定義=====================
//定義引腳
#define LCM_Data P0 //數據介面
#define Busy 0x80 //用於檢測LCM狀態字中的Busy標識
sbit LCM_RW = P2^1; //讀寫控制輸入端
sbit LCM_RS = P2^0; //寄存器選擇輸入端
sbit LCM_E = P2^2; //使能信號輸入端
void WritEDAtaLCM (uchar WDLCM);
void WriteCommandLCM (uchar WCLCM,BuysC);
uchar ReadDataLCM (void);
uchar ReadStatusLCM (void);
void DisplayOneChar (uchar X,uchar Y,uchar ASCII);
void DisplayListChar (uchar X,uchar Y,uchar delayms,uchar code *DData);
void DisplayCursorPos (uchar X, uchar Y);
void LCMInit (void);
void DisplayIntData (uchar X, uchar Y,int ZhengShu,uchar Digit,uchar XiaoShu);
void DisplayCharData (uchar X, uchar Y,uchar ZiFu);
//===============================超聲波模塊定義========================
sbit RemPin = P3^2;// 接收端(這個不能修改,因為是外部中斷(INT0)的引腳)
sbit TxPin = P3^5;// 發射端
uint length = 0; // 測距的長度0.00M
uchar flag = 0; // 測距的標志 有信號接收=1;
void DelayUs(uint us)
{
while(us--);
}
void DelayMs(uint Ms)
{
uint i,TempCyc;
for(i=0;i<Ms;i++)
{
TempCyc = 250;
while(TempCyc--);
}
}
//==============================LCD1602顯示子程序================================================
void WritEDAtaLCM(unsigned char WDLCM)
{
ReadStatusLCM(); //檢測忙
LCM_Data = WDLCM;
LCM_RS = 1;
LCM_RW = 0;
LCM_E = 0; //若晶振速度太高可以在這後加小的延時
LCM_E = 0; //延時
LCM_E = 1;
}
void WriteCommandLCM(unsigned char WCLCM,BuysC) //BuysC為0時忽略忙檢測
{
if (BuysC) ReadStatusLCM(); //根據需要檢測忙
LCM_Data = WCLCM;
LCM_RS = 0;
LCM_RW = 0;
LCM_E = 0;
LCM_E = 0;
LCM_E = 1;
}
unsigned char ReadDataLCM(void)
{
LCM_RS = 1;
LCM_RW = 1;
LCM_E = 0;
LCM_E = 0;
LCM_E = 1;
return(LCM_Data);
}
unsigned char ReadStatusLCM(void)
{
LCM_Data = 0xFF;
LCM_RS = 0;
LCM_RW = 1;
LCM_E = 0;
LCM_E = 0;
LCM_E = 1;
while (LCM_Data & Busy); //檢測忙信號
return(LCM_Data);
}
void DisplayOneChar( unsigned char X, unsigned char Y, unsigned char ASCII)
{
X &= 0x1;
Y &= 0xF; //限制Y不能大於15,X不能大於1
if (X) Y |= 0x40; //當要顯示第二行時地址碼+0x40;
Y |= 0x80; // 算出指令碼
WriteCommandLCM(Y, 0); //這里不檢測忙信號,發送地址碼
WritEDAtaLCM(ASCII);
}
void DisplayListChar(uchar X,uchar Y,uchar delayms, uchar code *DData)
{
unsigned char ListLength;
ListLength = 0;
X &= 0x1;
Y &= 0xF; //限制X不能大於15,Y不能大於1
while (DData[ListLength]!='\0') //若到達字串尾則退出
{
if (Y <= 0xF) //X坐標應小於0xF
{
DisplayOneChar(X, Y, DData[ListLength]); //顯示單個字元
ListLength++;
Y++;
DelayMs(delayms);//延時顯示字元串
}
else
break;//跳出循環體
}
}
void DisplayCursorPos( unsigned char X, unsigned char Y)
{
X &= 0x1;
Y &= 0xF; //限制Y不能大於15,X不能大於1
if (X) Y |= 0x40; //當要顯示第二行時地址碼+0x40;
Y |= 0x80; // 算出指令碼
WriteCommandLCM(Y, 1); //這里不檢測忙信號,發送地址碼
}
void LCMInit(void)
{
LCM_Data = 0;
WriteCommandLCM(0x38,0); //三次顯示模式設置,不檢測忙信號
DelayMs(5);
WriteCommandLCM(0x38,0);
DelayMs(5);
WriteCommandLCM(0x38,0);
DelayMs(5);
WriteCommandLCM(0x38,1); //顯示模式設置,開始要求每次檢測忙信號
WriteCommandLCM(0x08,1); //關閉顯示
WriteCommandLCM(0x01,1); //顯示清屏
WriteCommandLCM(0x06,1); // 顯示游標移動設置
WriteCommandLCM(0x0C,1); // 顯示開及游標設置
DelayMs(100);
}
void DisplayIntData(uchar X, uchar Y,int ZhengShu,uchar Digit,uchar XiaoShu)
{
uchar i=0,k=0, BCD[5]={0};
if(Digit>5) Digit=5;
if(ZhengShu<0)
{
k=1;//負數示志位
ZhengShu=-ZhengShu;
}
BCD[4] = ZhengShu / 10000; //求出萬位數據
ZhengShu = ZhengShu % 10000;
BCD[3] = ZhengShu / 1000; //求出千位數據
ZhengShu = ZhengShu % 1000;
BCD[2] = ZhengShu / 100; //求出百位數據
ZhengShu = ZhengShu % 100;
BCD[1] = ZhengShu / 10; //求出十位數據
BCD[0] = ZhengShu % 10; //求出個位數據
for(i=0;i<Digit;i++)//輸出顯示的數值
{
if((i==XiaoShu)&&(0!=XiaoShu))
{
DisplayOneChar(X,Y-i,'.');//輸出小數點
Y= Y-1;
}
DisplayOneChar(X,Y-i,BCD[i]+0x30); //顯示一個字元
}
if(k==1)
DisplayOneChar(X,Y-1,'-');//輸出負符
}
void DisplayCharData(uchar X, uchar Y,uchar ZiFu)
{
uchar i=0;
uchar ValueBCD[3];
ValueBCD[0] = ZiFu / 100; //求出百位數據
ZiFu = ZiFu % 100;
ValueBCD[1] = ZiFu / 10; //求出十位數據
ValueBCD[2] = ZiFu % 10; //求出個位數據
for(i=0;i<3;i++)//輸出顯示的數值
{
DisplayOneChar(X,Y+i,ValueBCD[i]+0x30); //顯示一個字元
}
}
//==============================超聲波模塊測試子程序================================================
void delay25us_40KHz(unsigned char us)
{
while(us--)
{
TxPin = 0;
_nop_();_nop_();
_nop_();_nop_();
_nop_();_nop_();
_nop_();_nop_();
_nop_();_nop_();
_nop_();
TxPin = 1;
_nop_();_nop_();
_nop_();_nop_();
}
TxPin = 1;
}
void init0int() interrupt 0
{
uint timer_us = 0;
TR0=0; //關閉定時器0
timer_us = TH0*256+TL0;
if(timer_us>190)timer_us=timer_us-180; //修正測距的距離
length = ((unsigned long)(340)*timer_us)/2000;//計算長度,是擴大100倍
flag = 0;
EA = 0; //禁止所有中斷
}
void timer0int (void) interrupt 1
{
TR0=0; //關閉定時器0
length = 0; //超出測量時間顯示示0
flag = 1; //
EA = 0; //禁止所有中斷
}
void main(void)
{
LCMInit(); //1602初始化
EX0 = 1; //允許總中斷中斷,使能 INT0 外部中斷
ET0 = 1;
TMOD=0x11; //設定T0為16位時器,設定T1為16位時器
DisplayOneChar( 1, 11, 'M');
DisplayListChar(0,2,0, "Range Finder "); //顯示字元串
while(1)
{
DisplayIntData(1, 10,length,5,3);//顯示測量距離
TH0=0x00;
TL0=0x00;
TR0=1; //啟動定時器0
EA = 1; //允許所有中斷
delay25us_40KHz(15); //發出脈沖信號
DelayMs(200);
}
}
『陸』 51單片機超聲波測距代碼是多少
1602液晶顯示 的超聲波模塊程序
介面程序里邊都有、、
#include<reg52.h>
//#include<delay.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit lcdrs=P2^3;
sbit lcden=P2^2;
sbit trig=P2^0; //超聲波發送
//sbit echo=P3^2; //超聲波接受
//P0____________DB0-DB7
uchar dis[]="Disp_HC-SR04";
uchar num[]="0123456789";
uint distance;
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=121;y>0;y--);
}
void HC_init()
{
TMOD=0x09;
TR0=1;
TH0=0;TL0=0;
}
uint HC_jisuan()
{
uint dist,timer;
timer=TH0;
timer<<=8;
timer=timer|TL0;
dist=timer/53; //晶振11.0592MHz 距離cm=微秒us/58
return dist; //1個機器周期是12個時鍾周期 timer*12/(58*11.0592)=timer/53
}
void HC_run()
{
uint tempH=0x00,tempL=0x00;
TH0=0;TL0=0;
trig=0;
trig=1;
delay(1);
trig=0;
while((TH0-tempH!=0||TL0-tempL!=0)||(TH0==0&&TL0==0))
{
tempH=TH0;
tempL=TL0;
}
delay(1);
}
void lcd_write_com(uchar com) //LCD寫指令
{
lcdrs=0;
P0=com;
delay(1);
lcden=1;
delay(1);
lcden=0;
}
void lcd_write_data(uchar date) //LCD寫數據
{
lcdrs=1;
P0=date;
delay(1);
lcden=1;
delay(1);
lcden=0;
}
void lcd_init() //LCD初始化
{
lcden=0;
lcd_write_com(0x38);
lcd_write_com(0x0c);
lcd_write_com(0x06);
lcd_write_com(0x01);
}
void lcd_display(uchar temp)
{
uint i;
lcd_write_com(0x82);
for(i=0;i<12;i++)
{
lcd_write_data(dis[i]);
}
lcd_write_com(0x80+0x41);
lcd_write_data('D');
lcd_write_data('i');
lcd_write_data('s');
lcd_write_data('t');
lcd_write_data('a');
lcd_write_data('n');
lcd_write_data('c');
lcd_write_data('e');
lcd_write_data(':');
lcd_write_data(num[temp/100]);
lcd_write_data(num[temp/10%10]);
lcd_write_data(num[temp%10]);
lcd_write_data('c');
lcd_write_data('m');
}
void main()
{
lcd_init();
HC_init();
while(1)
{
HC_run();
distance=HC_jisuan();
lcd_display(distance);
delay(200);
}
}
『柒』 51單片機 HC-SR04超聲波測距 我寫的C語言代碼,請問
1、HC-SR04使用方法:給觸發端子trig一個10us以上的高電平即可觸發,觸發後echo端子將接受到高電平,高電平的持續時間就是測距的往返時間。
2、常式:
#include<reg52.h>
#defineucharunsignedchar
#defineuintunsignedint
/*位定義*/
sbitCHUFA=P0^1;//位定義超聲波觸發端(10us以上高電平觸發)
sbitJIESHOU=P0^3;//接收端(接受高電平)
sbitBEEP=P2^0;//蜂鳴器
sbitOUT0=P3^2;//外部中斷0
ucharJS_FLAG;//接收標志
uintCF_TIME,t0,t1,shu;
/*函數聲明*/
voidtimer0();
voidint0();
voiddisplay(uint);
main(){
CHUFA=0;//初始化拉低觸發端和接收端電平
JIESHOU=0;
JS_FLAG=0;
CF_TIME=15;//初始化觸發時間(大於10us)
TMOD=0x11;//定時器方式選擇
EA=1;//開總中斷
ET0=1;//開定時器0中斷
EX0=1;//開外部中斷0
IT0=0;//外部中斷選擇下降沿觸發
//JIESHOU=1;
while(1){
OUT0=JIESHOU;//外部中斷0被賦值為接收端信號,當出現下降沿是觸發外部中斷0
if(JS_FLAG==0){//如果沒有接收到高電平則觸發
CHUFA=1;
while(CF_TIME--);//10us以上高電平觸發感測器
}
if(JIESHOU==1){
TR0=1;//如果接收端收到高電平則啟動定時器
JS_FLAG=1;//並且標志位置1
BEEP=0;//蜂鳴器響
}
display(t1);//顯示測量時間(秒)
}
}
/*定時器0中斷程序*/
voidtimer0()interrupt1{
TH0=(65536-10000)/256;//裝初值10ms
TL0=(65536-10000)%256;
t0++;//每進入一次中斷t0加1
}
/*外部中斷0中斷程序*/
voidint0()interrupt0{
TR0=0;//一旦進入外部中斷0,說明接收端收到下降沿信號。關閉定時器0
JS_FLAG=0;//接收標志位置0
BEEP=1;//關閉蜂鳴器
t1=t0*10/1000;//測量時間為進入定時器中斷次數t0乘以每次時間10ms,除以1000化為秒為單位
t0=0;//t0清零
}
/*數碼管顯數函數*/
voiddisplay(uintshu){
//數碼管顯示函數
}
『捌』 51單片機如何控制超聲波感測器 求C語言程序(一定要能用)100追加
//超聲波模塊ME007顯示程序
//晶振=8M
//MCU=STC10F04XE
//P0.0-P0.6共陽數碼管引腳
//Trig = P1^0
//Echo = P3^2
#include <reg52.h> //包括一個52標准內核的頭文件
#define uchar unsigned char //定義一下方便使用
#define uint unsigned int
#define ulong unsigned long
//***********************************************
sfr CLK_DIV = 0x97; //為STC單片機定義,系統時鍾分頻
//為STC單片機的IO口設置地址定義
sfr P0M1 = 0X93;
sfr P0M0 = 0X94;
sfr P1M1 = 0X91;
sfr P1M0 = 0X92;
sfr P2M1 = 0X95;
sfr P2M0 = 0X96;
//***********************************************
sbit Trig = P1^0; //產生脈沖引腳
sbit Echo = P3^2; //回波引腳
sbit test = P1^1; //測試用引腳
uchar code SEG7[10]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};//數碼管0-9
uint distance[4]; //測距接收緩沖區
uchar ge,shi,,temp,flag,outcomeH,outcomeL,i; //自定義寄存器
bit succeed_flag; //測量成功標志
//********函數聲明
void conversion(uint temp_data);
void delay_20us();
//void pai_xu();
void main(void) // 主程序
{ uint distance_data,a,b;
uchar CONT_1;
CLK_DIV=0X03; //系統時鍾為1/8晶振(pdf-45頁)
P0M1 = 0; //將io口設置為推挽輸出
P1M1 = 0;
P2M1 = 0;
P0M0 = 0XFF;
P1M0 = 0XFF;
P2M0 = 0XFF;
i=0;
flag=0;
test =0;
Trig=0; //首先拉低脈沖輸入引腳
TMOD=0x11; //定時器0,定時器1,16位工作方式
TR0=1; //啟動定時器0
IT0=0; //由高電平變低電平,觸發外部中斷
ET0=1; //打開定時器0中斷
//ET1=1; //打開定時器1中斷
EX0=0; //關閉外部中斷
EA=1; //打開總中斷0
while(1) //程序循環
{
EA=0;
Trig=1;
delay_20us();
Trig=0; //產生一個20us的脈沖,在Trig引腳
while(Echo==0); //等待Echo回波引腳變高電平
succeed_flag=0; //清測量成功標志
EX0=1; //打開外部中斷
TH1=0; //定時器1清零
TL1=0; //定時器1清零
TF1=0; //
TR1=1; //啟動定時器1
EA=1;
while(TH1 < 30);//等待測量的結果,周期65.535毫秒(可用中斷實現)
TR1=0; //關閉定時器1
EX0=0; //關閉外部中斷
if(succeed_flag==1)
{
distance_data=outcomeH; //測量結果的高8位
distance_data<<=8; //放入16位的高8位
distance_data=distance_data|outcomeL;//與低8位合並成為16位結果數據
distance_data*=12; //因為定時器默認為12分頻
distance_data/=58; //微秒的單位除以58等於厘米
} //為什麼除以58等於厘米, Y米=(X秒*344)/2
// X秒=( 2*Y米)/344 ==》X秒=0.0058*Y米 ==》厘米=微秒/58
if(succeed_flag==0)
{
distance_data=0; //沒有回波則清零
test = !test; //測試燈變化
}
/// distance[i]=distance_data; //將測量結果的數據放入緩沖區
/// i++;
/// if(i==3)
/// {
/// distance_data=(distance[0]+distance[1]+distance[2]+distance[3])/4;
/// pai_xu();
/// distance_data=distance[1];
a=distance_data;
if(b==a) CONT_1=0;
if(b!=a) CONT_1++;
if(CONT_1>=3)
{ CONT_1=0;
b=a;
conversion(b);
}
/// i=0;
/// }
}
}
//***************************************************************
//外部中斷0,用做判斷回波電平
INTO_() interrupt 0 // 外部中斷是0號
{
outcomeH =TH1; //取出定時器的值
outcomeL =TL1; //取出定時器的值
succeed_flag=1; //至成功測量的標志
EX0=0; //關閉外部中斷
}
//****************************************************************
//定時器0中斷,用做顯示
timer0() interrupt 1 // 定時器0中斷是1號
{
TH0=0xfd; //寫入定時器0初始值
TL0=0x77;
switch(flag)
{case 0x00:P0=ge; P2=0xfd;flag++;break;
case 0x01:P0=shi;P2=0xfe;flag++;break;
case 0x02:P0=;P2=0xfb;flag=0;break;
}
}
//*****************************************************************
/*
//定時器1中斷,用做超聲波測距計時
timer1() interrupt 3 // 定時器0中斷是1號
{
TH1=0;
TL1=0;
}
*/
//******************************************************************
//顯示數據轉換程序
void conversion(uint temp_data)
{
uchar ge_data,shi_data,_data ;
_data=temp_data/100 ;
temp_data=temp_data%100; //取余運算
shi_data=temp_data/10 ;
temp_data=temp_data%10; //取余運算
ge_data=temp_data;
_data=SEG7[_data];
shi_data=SEG7[shi_data];
ge_data =SEG7[ge_data];
EA=0;
= _data;
shi = shi_data;
ge = ge_data ;
EA=1;
}
//******************************************************************
void delay_20us()
{ uchar bt ;
for(bt=0;bt<100;bt++);
}
/*
void pai_xu()
{ uint t;
if (distance[0]>distance[1])
{t=distance[0];distance[0]=distance[1];distance[1]=t;} /*交換值
if(distance[0]>distance[2])
{t=distance[2];distance[2]=distance[0];distance[0]=t;} /*交換值
if(distance[1]>distance[2])
{t=distance[1];distance[1]=distance[2];distance[2]=t;} /*交換值
}
*/
我的一個超聲波程序
有問題,請問~~
//超聲波模塊顯示程序
#include <reg52.h> //包括一個52標准內核的頭文件
#include<intrins.h> //包含_nop_()函數定義的頭文件
#define uchar unsigned char //定義一下方便使用
#define uint unsigned int
#define ulong unsigned long
sbit Tx = P3^3; //產生脈沖引腳
sbit Rx = P3^2; //回波引腳
sbit RS=P2^0; //寄存器選擇位,將RS位定義為P2.0引腳
sbit RW=P2^1; //讀寫選擇位,將RW位定義為P2.1引腳
sbit E=P2^2; //使能信號位,將E位定義為P2.2引腳
sbit BF=P0^7; //忙碌標志位,,將BF位定義為P0.7引腳
unsigned char code string[ ]= {"CHAO SHENG BO"};
//unsigned char code string1[ ]={"QUICK STUDY MCU"};
unsigned char code digit[ ]={"0123456789"}; //定義字元數組顯示數字
//uchar code SEG7[10]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};//數碼管0-9
uint distance[4]; //測距接收緩沖區
uchar ge,shi,,temp,flag,outcomeH,outcomeL,i; //自定義寄存器
bit succeed_flag; //測量成功標志
//********函數聲明
void conversion(uint temp_data);
void delay_20us();
void pai_xu();
/*****************************************************
函數功能:延時1ms
(3j+2)*i=(3×33+2)×10=1010(微秒),可以認為是1毫秒
***************************************************/
void delay1ms()
{
unsigned char i,j;
for(i=0;i<10;i++)
for(j=0;j<33;j++)
;
}
/*****************************************************
函數功能:延時若干毫秒
入口參數:n
***************************************************/
void delay(unsigned char n)
{
unsigned char i;
for(i=0;i<n;i++)
delay1ms();
}
/*****************************************************
函數功能:判斷液晶模塊的忙碌狀態
返回值:result。result=1,忙碌;result=0,不忙
***************************************************/
unsigned char BusyTest(void)
{
bit result;
RS=0; //根據規定,RS為低電平,RW為高電平時,可以讀狀態
RW=1;
E=1; //E=1,才允許讀寫
_nop_(); //空操作
_nop_();
_nop_();
_nop_(); //空操作四個機器周期,給硬體反應時間
result=BF; //將忙碌標志電平賦給result
E=0; //將E恢復低電平
return result;
}
/*****************************************************
函數功能:將模式設置指令或顯示地址寫入液晶模塊
入口參數:dictate
***************************************************/
void WriteInstruction (unsigned char dictate)
{
while(BusyTest()==1); //如果忙就等待
RS=0; //根據規定,RS和R/W同時為低電平時,可以寫入指令
RW=0;
E=0; //E置低電平(根據表8-6,寫指令時,E為高脈沖,
// 就是讓E從0到1發生正跳變,所以應先置"0"
_nop_();
_nop_(); //空操作兩個機器周期,給硬體反應時間
P0=dictate; //將數據送入P0口,即寫入指令或地址
_nop_();
_nop_();
_nop_();
_nop_(); //空操作四個機器周期,給硬體反應時間
E=1; //E置高電平
_nop_();
_nop_();
_nop_();
_nop_(); //空操作四個機器周期,給硬體反應時間
E=0; //當E由高電平跳變成低電平時,液晶模塊開始執行命令
}
/*****************************************************
函數功能:指定字元顯示的實際地址
入口參數:x
***************************************************/
void WriteAddress(unsigned char x)
{
WriteInstruction(x|0x80); //顯示位置的確定方法規定為"80H+地址碼x"
}
/*****************************************************
函數功能:將數據(字元的標准ASCII碼)寫入液晶模塊
入口參數:y(為字元常量)
***************************************************/
void WriteData(unsigned char y)
{
while(BusyTest()==1);
RS=1; //RS為高電平,RW為低電平時,可以寫入數據
RW=0;
E=0; //E置低電平(根據表8-6,寫指令時,E為高脈沖,
// 就是讓E從0到1發生正跳變,所以應先置"0"
P0=y; //將數據送入P0口,即將數據寫入液晶模塊
_nop_();
_nop_();
_nop_();
_nop_(); //空操作四個機器周期,給硬體反應時間
E=1; //E置高電平
_nop_();
_nop_();
_nop_();
_nop_(); //空操作四個機器周期,給硬體反應時間
E=0; //當E由高電平跳變成低電平時,液晶模塊開始執行命令
}
/*****************************************************
函數功能:對LCD的顯示模式進行初始化設置
***************************************************/
void LcdInitiate(void)
{
delay(15); //延時15ms,首次寫指令時應給LCD一段較長的反應時間
WriteInstruction(0x38); //顯示模式設置:16×2顯示,5×7點陣,8位數據介面
delay(5); //延時5ms,給硬體一點反應時間
WriteInstruction(0x38);
delay(5);
WriteInstruction(0x38); //連續三次,確保初始化成功
delay(5);
WriteInstruction(0x0c); //顯示模式設置:顯示開,無游標,游標不閃爍
delay(5);
WriteInstruction(0x06); //顯示模式設置:游標右移,字元不移
delay(5);
WriteInstruction(0x01); //清屏幕指令,將以前的顯示內容清除
delay(5);
}
void main(void) // 主程序
{ uint distance_data,a,b;
uchar CONT_1;
uchar k; //定義變數i指向字元串數組元素
LcdInitiate(); //調用LCD初始化函數
delay(10); //延時10ms,給硬體一點反應時間
WriteAddress(0x01); // 從第1行第3列開始顯示
k = 0; //指向字元數組的第1個元素
while(string[k] != '\0')
{
WriteData(string[k]);
k++; //指向下字元數組一個元素
}
i=0;
flag=0;
Tx=0; //首先拉低脈沖輸入引腳
TMOD=0x10; //定時器0,定時器1,16位工作方式
// TR0=1; //啟動定時器0
IT0=0; //由高電平變低電平,觸發外部中斷
//ET0=1; //打開定時器0中斷
EX0=0; //關閉外部中斷
EA=1; //打開總中斷0
while(1) //程序循環
{
WriteAddress(0x41); // 從第2行第6列開始顯示
WriteData('J'); //將萬位數字的字元常量寫入LCD
WriteData('U'); //將萬位數字的字元常量寫入LCD
WriteData('L'); //將萬位數字的字元常量寫入LCD
WriteData('I'); //將萬位數字的字元常量寫入LCD
WriteData(':'); //將萬位數字的字元常量寫入LCD
WriteData(digit[]); //將萬位數字的字元常量寫入LCD
WriteData(digit[shi]); //將千位數字的字元常量寫入LCD
WriteData('.'); //將萬位數字的字元常量寫入LCD
WriteData(digit[ge]); //將百位數字的字元常量寫入LCD
WriteData(' '); //將百位數字的字元常量寫入LCD
WriteData('C'); //將萬位數字的字元常量寫入LCD
WriteData('M'); //將萬位數字的字元常量寫入LCD
EA=0;
Tx=1;
delay_20us();
Tx=0; //產生一個20us的脈沖,在Tx引腳
while(Rx==0); //等待Rx回波引腳變高電平
succeed_flag=0; //清測量成功標志
EX0=1; //打開外部中斷
TH1=0; //定時器1清零
TL1=0; //定時器1清零
TF1=0; //
TR1=1; //啟動定時器1
EA=1;
while(TH1 < 30);//等待測量的結果,周期65.535毫秒(可用中斷實現)
TR1=0; //關閉定時器1
EX0=0; //關閉外部中斷
if(succeed_flag==1)
{
distance_data=outcomeH; //測量結果的高8位
distance_data<<=8; //放入16位的高8位
distance_data=distance_data|outcomeL;//與低8位合並成為16位結果數據
distance_data*=12; //因為定時器默認為12分頻
distance_data/=58; //微秒的單位除以58等於厘米
} //為什麼除以58等於厘米, Y米=(X秒*344)/2
// X秒=( 2*Y米)/344 ==》X秒=0.0058*Y米 ==》厘米=微秒/58
if(succeed_flag==0)
{
distance_data=0; //沒有回波則清零
}
distance[i]=distance_data; //將測量結果的數據放入緩沖區
i++;
if(i==3)
{
distance_data=(distance[0]+distance[1]+distance[2]+distance[3])/4;
pai_xu();
distance_data=distance[1];
a=distance_data;
if(b==a) CONT_1=0;
if(b!=a) CONT_1++;
if(CONT_1>=3)
{ CONT_1=0;
b=a;
conversion(b);
}
i=0;
}
}
}
//***************************************************************
//外部中斷0,用做判斷回波電平
INTO_() interrupt 0 // 外部中斷是0號
{
outcomeH =TH1; //取出定時器的值
outcomeL =TL1; //取出定時器的值
succeed_flag=1; //至成功測量的標志
EX0=0; //關閉外部中斷
}
//****************************************************************
//定時器0中斷,用做顯示
timer0() interrupt 1 // 定時器0中斷是1號
{
// TH0=0xfd; //寫入定時器0初始值
// TL0=0x77;
}
//顯示數據轉換程序
void conversion(uint temp_data)
{
uchar ge_data,shi_data,_data ;
_data=temp_data/100 ;
temp_data=temp_data%100; //取余運算
shi_data=temp_data/10 ;
temp_data=temp_data%10; //取余運算
ge_data=temp_data;
//_data=SEG7[_data];
//shi_data=SEG7[shi_data]&0x7f;
//ge_data =SEG7[ge_data];
EA=0;
= _data;
shi = shi_data;
ge = ge_data ;
EA=1;
}
//******************************************************************
void delay_20us()
{ uchar bt ;
for(bt=0;bt<60;bt++);
}
void pai_xu()
{ uint t;
if (distance[0]>distance[1])
{t=distance[0];distance[0]=distance[1];distance[1]=t;}
if(distance[0]>distance[2])
{t=distance[2];distance[2]=distance[0];distance[0]=t;}
if(distance[1]>distance[2])
{t=distance[1];distance[1]=distance[2];distance[2]=t;}
}
第一個需要修改,你還是試試這個吧!這個你先理解下,修改引腳……顯示為1602
『玖』 51單片機超聲波測距代碼
1602液晶顯示 的超聲波模塊程序
介面程序里邊都有、、
#include
//#include
#include
#define uchar unsigned char
#define uint unsigned int
sbit lcdrs=P2^3;
sbit lcden=P2^2;
sbit trig=P2^0; //超聲波發送
//sbit echo=P3^2; //超聲波接受
//P0____________DB0-DB7
uchar dis[]="Disp_HC-SR04";
uchar num[]="0123456789";
uint distance;
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=121;y>0;y--);
}
void HC_init()
{
TMOD=0x09;
TR0=1;
TH0=0;TL0=0;
}
uint HC_jisuan()
{
uint dist,timer;
timer=TH0;
timer<<=8;
timer=timer|TL0;
dist=timer/53; //晶振11.0592MHz 距離cm=微秒us/58
return dist; //1個機器周期是12個時鍾周期 timer*12/(58*11.0592)=timer/53
}
void HC_run()
{
uint tempH=0x00,tempL=0x00;
TH0=0;TL0=0;
trig=0;
trig=1;
delay(1);
trig=0;
while((TH0-tempH!=0||TL0-tempL!=0)||(TH0==0&&TL0==0))
{
tempH=TH0;
tempL=TL0;
}
delay(1);
}
void lcd_write_com(uchar com) //LCD寫指令
{
lcdrs=0;
P0=com;
delay(1);
lcden=1;
delay(1);
lcden=0;
}
void lcd_write_data(uchar date) //LCD寫數據
{
lcdrs=1;
P0=date;
delay(1);
lcden=1;
delay(1);
lcden=0;
}
void lcd_init() //LCD初始化
{
lcden=0;
lcd_write_com(0x38);
lcd_write_com(0x0c);
lcd_write_com(0x06);
lcd_write_com(0x01);
}
void lcd_display(uchar temp)
{
uint i;
lcd_write_com(0x82);
for(i=0;i<12;i++)
{
lcd_write_data(dis[i]);
}
lcd_write_com(0x80+0x41);
lcd_write_data('D');
lcd_write_data('i');
lcd_write_data('s');
lcd_write_data('t');
lcd_write_data('a');
lcd_write_data('n');
lcd_write_data('c');
lcd_write_data('e');
lcd_write_data(':');
lcd_write_data(num[temp/100]);
lcd_write_data(num[temp/10%10]);
lcd_write_data(num[temp%10]);
lcd_write_data('c');
lcd_write_data('m');
}
void main()
{
lcd_init();
HC_init();
while(1)
{
HC_run();
distance=HC_jisuan();
lcd_display(distance);
delay(200);
}
}
『拾』 求一段匯編程序,利用51單片機控制超聲波感測器測距的程序。
; 基於AT89C2051單片機超聲波測距系統
; 測量范圍35-300厘米
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 中斷入口程序 ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ORG 0000H
AJMP START
ORG 000BH
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 主 程 序 ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
START : MOV R0,#70H ;立即數70H送寄存器R0中
MOV R7,#0BH ;立即數0BH送寄存器R7中
MOV 20H,#00H ;立即數00H送20H單元中
CLEARDISP: MOV @R0,#00H ;立即數立即數00H送R0中的地址單元中
INC R0 ;寄存器R0加1
DJNZ R7,CLEARDISP;寄存器中的數值減1非零時轉移
MOV TMOD,#01H ;置定時器T0工作方式樣3,對內部機器周期計數
CJZCX:MOV TL0,#00H ;裝入定時器初值
MOV TH0,#00H
MOV R0,#0FH
MOV R1,#5bH
puzel:MOV 14H,#08H ;超聲波發射持續200us
Here:CPL P3.5 ;輸出40kHz方波
NOP ;
NOP ;
NOP ;
DJNZ 14H,Here ;
SETB TR0
SETB P3.2
MOV R6,#53H ;延時1.5ms
DL0: MOV R5,#03H
DJNZ R5,$
DJNZ R6,DL0
QBA:JNB P3.7,QBC
DJNZ R1,QBA
DJNZ R0,QBA
QBC:CLR P3.2
CLR TR0
MOV 70H,tl0
MOV 71H,tH0
MOV R2,71H
MOV R3,70H
MOV R6,#22H
MOV R7,#0H
LCALL MULD
MOV R6,#64H
MOV R7,#0H
LCALL DIVD
MOV 73H,R2
MOV 74H,R3
MOV R3,#0H
MOV R4,#0H
MOV R5,#0H
MOV R6,73H
MOV R7,74H
LCALL HB2
MOV A,R4 ;分離BCD
MOV B,#10H
DIV AB
MOV 78H,A
MOV 77H,B
MOV A,R5
MOV B,#10H
DIV AB
MOV 76H,A
MOV 75H,B
MOV 7AH,#0EFH
XXX:LCALL DISPLAY
DJNZ 7AH,XXX
AJMP CJZCX
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 乘34程序(乘聲速) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MULD: MOV A,R3 ;計算R3乘R7
MOV B,R7
MUL AB
MOV R4,B ;暫存部分積
MOV R5,A
MOV A,R3 ;計算R3乘R6
MOV B,R6
MUL AB
ADD A,R4 ;累加部分積
MOV R4,A
CLR A
ADDC A,B
MOV R3,A
MOV A,R2 ;計算R2乘R7
MOV B,R7
MUL AB
ADD A,R4 ;累加部分積
MOV R4,A
MOV A,R3
ADDC A,B
MOV R3,A
CLR A
RLC A
XCH A,R2 ;計算R2乘R6
MOV B,R6
MUL AB
ADD A,R3 ;累加部分積
MOV R3,A
MOV A,R2
ADDC A,B
MOV R2,A
RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 除100程序(除法) ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DIVD: CLR C ;比較被除數和除數
MOV A,R3
SUBB A,R7
MOV A,R2
SUBB A,R6
JC DVD1
SETB OV ;溢出
RET
DVD1: MOV B,#10H ;計算雙位元組商
DVD2: CLR C ;部分商和余數同時左移一位
MOV A,R5
RLC A
MOV R5,A
MOV A,R4
RLC A
MOV R4,A
MOV A,R3
RLC A
MOV R3,A
XCH A,R2
RLC A
XCH A,R2
MOV F0,C ;保存溢出位
CLR C
SUBB A,R7 ;計算(R2R3-R6R7)
MOV R1,A
MOV A,R2
SUBB A,R6
ANL C,/F0 ;結果判斷
JC DVD3
MOV R2,A ;夠減,存放新的余數
MOV A,R1
MOV R3,A
INC R5 ;商的低位置一
DVD3: DJNZ B,DVD2 ;計算完十六位商(R4R5)
MOV A,R4 ;將商移到R2R3中
MOV R2,A
MOV A,R5
MOV R3,A
CLR OV ;設立成功標志
RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; BCD轉換 ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
HB2: CLR A ;BCD碼初始化
MOV R3,A
MOV R4,A
MOV R5,A
MOV R2,#10H ;轉換雙位元組十六進制整數
HB3: MOV A,R7 ;從高端移出待轉換數的一位到CY中
RLC A
MOV R7,A
MOV A,R6
RLC A
MOV R6,A
MOV A,R5 ;BCD碼帶進位自身相加,相當於乘2
ADDC A,R5
DA A ;十進制調整
MOV R5,A
MOV A,R4
ADDC A,R4
DA A
MOV R4,A
MOV A,R3
ADDC A,R3
MOV R3,A ;雙位元組十六進制數的萬位數不超過6,不用調整
DJNZ R2,HB3 ;處理完16bit
RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 顯示程序 ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DISPLAY: MOV R1,#76H ;立即數76H送寄存器中
MOV R5,#0FEH ;立即數FEH送寄存器R5中
PLAY: MOV A,R5 ;寄存器R5中的數值送累加器A中
MOV P3,A ;累加器A中的數值送P3口
MOV A,@R1 ;以寄存器R1中的數為地址單元的數值送累加器中
MOV DPTR,#TAB ;16位地址送地址寄存器中
MOVC A,@A+DPTR ;以中的地址為基地變址定址單元中的數送累加器
MOV P1,A ;累加器A中的數值送P1口
MOV R6,#14H ;立即數據14送寄存器R6中
DL1:MOV R7,#19H ;立即數據19送寄存器R7中
DL2:DJNZ R7,DL2 ;寄存器中的數據減1,不為零時則轉移
DJNZ R6,DL1 ;寄存器中的數據減1,不為零時則轉移
INC R1 ;寄存器R1中的數值加1
MOV A,R5 ;寄存器R5中的數值送累加器A中
JNB ACC.2,ENDOUT ;地址位為0則轉到ENDOUT
RL A ;累加器循環右移
MOV R5,A ;累加器A中的數值送寄存器R5中
AJMP PLAY ;絕對短轉移
ENDOUT: SETB P3.5 ;置P3.5口
MOV P1,#0FFH ;立即數0FEH送P1口
RET ;返回
TAB: DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H,0FFH
END ;結束
我見過一款製作容易免調試的超聲波測距板,你可到「谷歌」上搜索一下《一款製作容易免調試的超聲波測距板》,該超聲波測距板結構簡單、製作容易不需要調試、測量精度高,比較適合單片機初學都使用,同時也是單片機課程設計比較好的實訓課題。該超聲波測距系統,提供套件,及組裝好的板件,含原理圖、源程序、設計說明等。