㈠ 幫忙詳細解答一下基於單片機的超聲波測距儀的匯編源程序(急求啊)
我可以負責的告訴你,用C吧,完全可以勝任。
2003年的時候我們為了確保MCU的效率(時效性),強制使用匯編寫的超聲波程序,結果程序寫不大,匯編你也知道,寫百八十行可以,代碼多了,這程序就沒法看了,更談不上程序升級和維護了。因此,那一代超聲波產品的功能很弱。
2006年,我們要重新設計第二代超聲波產品,要求可靠性好、功能強大,自然的代碼量也要多了,當時我們仍然固執的使用匯編、絕不用C,可匯編的代碼仍然寫不長,為了方便技術人員管理和後續的產品升級,我把這一套復雜的系統代碼分成了4級,也就是4套匯編代碼,分別在32個MCU里運行(同一個設備里),這4套代碼分別交給4個人來編寫和維護,這4個人中若有人跳槽走了,由於他掌握的代碼量小,功能又單一,接替他的人也很容易接手。(否則,這4套匯編程序,集中在一個冗長的代碼里,那麼這套代碼將很難維護,而且幾乎只能有1個人才能完全看懂它,一旦這個人走了,別人很難接手這套『爛』程序,這對於產品的持續改進非常不利)
2008年,我們試探性的,在DSP(TMS320F28335)上用C完成了所有的功能,而且程序量比匯編要少得多,可讀性、可維護性也要好得多。後來,我們在單片機上,也用C完成了絕大部分功能,原來擔心的時效性問題從沒有發生,這才領悟:2003-2008這5年,我們繞了一個大圈。
從此以後,我們就不再用匯編了,用C寫超聲波程序一直至今(偶爾嵌入匯編代碼),算一下也有5年了,從沒覺得C有任何局限性。
那麼,你是還覺得必須要用匯編么?
㈡ 1602顯示超聲波測距的C語言程序和Proteus模擬圖
#include"reg52.h"
#include"intrins.h"
#define uchar unsigned char //無符號8位
#define uint unsigned int //無符號16位
#define ulong unsigned long //無符號32位
sbit K1=P1^0; //按下K1後,開始測距
sbit LEDRed=P1^1; //測距指示燈,亮表示正在測距,滅表示測距完成
//sbit BEEP=P1^2; //報警測量超出范圍
sbit Trig=P2^5; //HC-SR04觸發信號輸入
sbit Echo=P2^6; //HC-SR04回響信號輸出
float xdata DistanceValue=0.0; //測量的距離值
float xdata SPEEDSOUND; //聲速
float xdata XTALTIME; //單片機計數周期
uchar xdata stringBuf[6]; //數值轉字元串緩沖
//LCD1602提示信息
uchar code Prompts[][16]=
{
{"Measure Distance"}, //測量距離
{"- Out of Range -"}, //超出測量范圍
{"MAX range 400cm "}, //測距最大值400cm
{"MIN range 2cm "}, //測距最小值2cm
{" "}, //清屏
{" Press K1 Start "} //按鍵開始測量
};
uchar xdata DistanceText[]="Range: "; //測量結果字元串
uchar xdata TemperatureText[]="Temperature: ";//測量溫度值
extern void LCD_Initialize(); //LCD初始化
extern void LCD_Display_String(uchar *, uchar); //字元串顯示
extern void ReadTemperatureFromDS18B20(); //從DS18B20讀取溫度值
extern int xdata CurTempInteger;
//毫秒延時函數
void DelayMS(uint ms);
//20微秒延時函數
void Delay20us();
//HCSR04初始化
void HCSR04_Initialize();
//測量距離
float MeasuringDistance();
//測距的數值排序求平均
float DistanceStatistics();
//輸出距離值到LCD1602上
void DisplayDistanceValue(float dat);
//將無符號的整數轉成字元串,返回字元串長度,不包括'\0'結束符
uchar UnsigedIntToString(uint value);
//蜂鳴器
//void Beep(uchar time);
//顯示溫度值
void DisplayTemperatureValue();
void main()
{
LCD_Initialize();//LCD1602初始化
LCD_Display_String(Prompts[0],0x00);
LCD_Display_String(Prompts[5],0x40);
ReadTemperatureFromDS18B20(); //測溫度
HCSR04_Initialize(); //HC-SR04初始化
while(1)
{
if(K1==0)
{
DelayMS(5);
if(K1==0)
{
//Beep(1);
while(K1==0);
LEDRed=0;
ReadTemperatureFromDS18B20();//測溫度
DisplayTemperatureValue();
if(CurTempInteger<14)
CurTempInteger=14;
else if(CurTempInteger>26)
CurTempInteger=26;
SPEEDSOUND=334.1+CurTempInteger*0.61;//計算聲速
DistanceValue=DistanceStatistics(); //測距並返回距離值
DisplayDistanceValue(DistanceValue); //顯示距離值
LEDRed=1;
}
}
}
}
//測距的數值排序求平均
float DistanceStatistics()
{
uchar i,j;
float disData[7],t;
//連續測距
for(i=0;i<7;i++)
{
disData=MeasuringDistance();
DelayMS(80);
}
//排序
for(j=0;j<=6;j++)
{
for(i=0;i<7-j;i++)
{
if(disData>disData[i+1])
{
t=disData;
disData=disData[i+1];
disData[i+1]=t;
}
}
}
return (disData[2]+disData[3]+disData[4])/3;
}
//測量距離
float MeasuringDistance()
{
//最大定時時間約65ms
TH0=0;
TL0=0;
//生成20us的脈沖寬度的觸發信號
Trig=1;
Delay20us();
Trig=0;
//等待回響信號變高電平
while(!Echo);
TR0=1; //啟動定時器0
//等待回響信號變低電平
while(Echo);
TR0=0; //關閉定時器0
//返回距離值(mm)
return (SPEEDSOUND*XTALTIME*((float)TH0*256+(float)TL0))/2000;
}
//HCSR04初始化
void HCSR04_Initialize()
{
//計算單片機計數周期 晶振=11.953M 單位us
XTALTIME=12/11.953;
//溫度25度時聲速的值
SPEEDSOUND=334.1+25*0.61;
Trig=0;
Echo=0;
TMOD=0x01;
}
//輸出距離值到LCD1602上
void DisplayDistanceValue(float dat)
{
uchar i=0,j=0,len;
uint value;
value=(uint)dat;
//范圍檢查大於4000mm和小於20mm都為超出測量范圍
if(value>4000)
{
LCD_Display_String(Prompts[1],0x00);
LCD_Display_String(Prompts[2],0x40);
//Beep(2);
}
else if(value<20)
{
LCD_Display_String(Prompts[1],0x00);
LCD_Display_String(Prompts[3],0x40);
//Beep(2);
}
else
{
//將數值轉換成字元串
len=UnsigedIntToString(value);
//保留1位小數
while(stringBuf!='\0')
{
if(len-j==1)
{
DistanceText[6+j]='.';
j++;
}else
{
DistanceText[6+j]=stringBuf;
i++;
j++;
}
}
DistanceText[6+j]='c';
j++;
DistanceText[6+j]='m';
i=7+j;
//剩餘位置補空格
while(i<16)
{
DistanceText=' ';
i++;
}
//LCD_Display_String(Prompts[0],0x00);
LCD_Display_String(DistanceText,0x40);
}
}
//顯示溫度值
void DisplayTemperatureValue()
{
TemperatureText[13]=CurTempInteger/10+'0';
TemperatureText[14]=CurTempInteger+'0';
TemperatureText[15]='C';
LCD_Display_String(TemperatureText,0x00);
}
//將無符號的整數轉成字元串,返回字元串長度
uchar UnsigedIntToString(uint value)
{
uchar i=0,t,length;
//從個位開始轉換
do
{
stringBuf='0'+value;
value=value/10;
i++;
}while(value!=0);
length=i;
//將字元串顛倒順序
for(i=0;i<(length/2);i++)
{
t=stringBuf;
stringBuf=stringBuf[length-i-1];
stringBuf[length-i-1]=t;
}
stringBuf[length]='\0';
return length;
}
//蜂鳴器
//延時函數 毫秒 @12.000MHz
void DelayMS(uint ms)
{
uchar i, j;
while(ms--)
{
_nop_();
i = 2;
j = 239;
do
{
while (--j);
}while (--i);
}
}
//延時函數 20微秒 @12.000MHz
void Delay20us()
{
uchar i;
_nop_();
i = 7;
while (--i);
}
//定時器0中斷
void Timer0() interrupt 1
{
}
//DS18B20代碼:
#include
#include
#define uchar unsigned char //無符號8位
#define uint unsigned int //無符號16位
//定義DS18B20埠DS18B20_DQ
sbit DS18B20_DQ = P2^7;
//當前採集的溫度值整數部分
int xdata CurTempInteger;
//當前採集的溫度值小數部分
int xdata CurTempDecimal;
void Delayus(uint count)
{
while (--count);
}
uchar Reset_DS18B20()
{
uchar status;
DS18B20_DQ=1;
Delayus(1);
//開始復位過程
DS18B20_DQ=0; //數據線拉低
Delayus(100); //延時480us-960us
DS18B20_DQ=1; //數據線拉高
Delayus(10); //延時15us-60us
status=DS18B20_DQ; //讀取數據線上的狀態
Delayus(120);
return status;
}
void WriteByteToDS18B20(uchar dat)
{
uchar i;
for(i=0;i<8;i++)
{
DS18B20_DQ=0;
DS18B20_DQ=dat&0x01; //發送1位數據
Delayus(15); //延時60us以上
DS18B20_DQ=1; //釋放匯流排,等待匯流排恢復
dat>>=1; //准備下一位數據
}
}
uchar ReadByteFromDS18B20()
{
uchar i,dat=0;
for(i=0;i<8;i++)
{
DS18B20_DQ=0; //拉低匯流排,產生讀信號
dat>>=1;
DS18B20_DQ=1; //釋放匯流排,准備讀1位數據
Delayus(2); //延時4us
if(DS18B20_DQ) dat|=0x80; //合並每位數據
Delayus(15); //延時60us
DS18B20_DQ=1; //拉高匯流排,准備讀下1位數據
}
return dat;
}
void ReadTemperatureFromDS18B20()
{
uchar flag=0;//正負符號標志
//存儲當前採集的溫度值
uchar TempValue[]={0,0};
if(Reset_DS18B20())
{
CurTempInteger=255;
CurTempDecimal=0;
}
else
{
WriteByteToDS18B20(0xCC);//跳過ROM命令
WriteByteToDS18B20(0x44);//溫度轉換命令
Reset_DS18B20();//復位
WriteByteToDS18B20(0xCC);//跳過ROM命令
WriteByteToDS18B20(0xBE);//讀取溫度暫存器命令
TempValue[0]=ReadByteFromDS18B20();//先讀低位元組溫度值
TempValue[1]=ReadByteFromDS18B20();//後讀高位元組溫度值
Reset_DS18B20();//復位
//計算溫度值
//先進行正溫度與負溫度判斷,高5位全為1(0xF8)則為負數
if((TempValue[1]&0xF8)==0xF8)
{
//負溫度計算:取反加1,低位元組為0時,高位元組取反加1,否則不需要。
TempValue[1]=~TempValue[1];
TempValue[0]=~TempValue[0]+1;
if(TempValue[0]==0x00) TempValue[1]++;
flag=1;//負數標志
}
//將溫度值分為整數和小數兩部分存儲(默認為12位精度)
CurTempInteger=((TempValue[1]&0x07)<<4)|((TempValue[0]&0xF0)>>4); if(flag) CurTempInteger=-CurTempInteger;
CurTempDecimal=(TempValue[0]&0x0F)*625;
}
}
//LCD1602程序代碼:
#include
#include
#define uchar unsigned char
#define uint unsigned int
#define Delay4us(){_nop_();_nop_();_nop_();_nop_();}
sbit LCD_RS=P2^0;
sbit LCD_RW=P2^1;
sbit LCD_EN=P2^2;
void LCDDelay(uint ms)
{
uchar i, j;
while(ms--)
{
_nop_();
i = 2;
j = 239;
do
{
while (--j);
}while (--i);
}
}
bit LCD_Busy_Check()
{
bit result;
LCD_RS=0; LCD_RW=1; LCD_EN=1;
Delay4us();
result=(bit)(P0&0x80);
LCD_EN=0;
return result;
}
void Write_LCD_Command(uchar cmd)
{
while(LCD_Busy_Check());
LCD_RS=0; LCD_RW=0; LCD_EN=0; _nop_(); _nop_();
P0=cmd; Delay4us();
LCD_EN=1; Delay4us(); LCD_EN=0;
}
void Write_LCD_Data(uchar dat)
{
while(LCD_Busy_Check());
LCD_RS=1;LCD_RW=0;LCD_EN=0;
P0=dat;Delay4us();
LCD_EN=1;Delay4us();LCD_EN=0;
}
void LCD_Set_POS(uchar pos)
{
Write_LCD_Command(pos|0x80);
}
void LCD_Initialize()
{
Write_LCD_Command(0x01); LCDDelay(5);
Write_LCD_Command(0x38); LCDDelay(5);
Write_LCD_Command(0x0C); LCDDelay(5);
Write_LCD_Command(0x06); LCDDelay(5);
}
void LCD_Display_String(uchar *str, uchar LineNo)
{
uchar k;
LCD_Set_POS(LineNo);
for(k=0;k<16;k++)
{
Write_LCD_Data(str[k]);
}
}
void LCD_Display_OneChar(uchar Dat, uchar X, uchar Y)
{
Y &= 0x01; //限制Y不能大於1(2行,0-1)
X &= 0x0F; //限制X不能大於15(16個字元,0-15)
if(Y) {X |= 0x40;} //當要在第二行顯示時地址碼+0x40;
X |= 0x80; //算出指令碼
Write_LCD_Command(X);
Write_LCD_Data(Dat);
}
㈢ 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);
}
}
㈣ 基於單片機超聲波測距c語言程序求解釋
//上面這段什麼意思?
//上下面這段什麼意思? 沒有code為什麼也可以存16進制?
uchar dis_smg[8] ={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8};
有code和沒有code的區別在於 dis_smg變數的存儲的存儲方式上
我記得有code的適合 dis_smg的數組元素不能改變的吧 記得不清楚了
你可以網路去
//下面是不是數碼管引腳和單片機引腳對應?
//數碼管位選定義
sbit smg_we1 = P3^4; //數碼管位選定義
答案: 是
㈤ 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);
}
}
㈥ 單片機匯編語言程序解讀(超聲波測距)越詳細越好
這是幾個子程序被 堆砌到一起了 ,沒有主程序不能實現功能
㈦ 單片機超聲波雷達測距的C語言程序設計,具體要求看問題補充
你到網路文庫中找找,會找到很多的。你也可到淘寶網上找一下:「單片機超聲波測距模塊電子設計製作C程序」這是一款比較好的程序,附的資料比較多,有Protel格式原理圖、PCB圖,有源程序、設計論文報告、元件清單等,製作非常容易,只要按圖焊接好元件,基本不需要調試,最遠可測量到6.99米,報警距離還可調節。 這里還有製作調試好的實物,你找找看。