单片机原理及应用课程设计报告题目二十七:超声波测距系统设计学生姓名专业学号同组同学指导教师学院二〇一六年七月2015-2016学年第二学期成绩:一、设计要求1.搭建单片机的最小系统;(基本项)2.选用超声波模块,设计模块与单片机的接口;(基本项)3.采用LCD显示器显示测量结果;(基本项)4.编写相应的程序;(基本项)5.提高测量精度的方法。
(创新项)二、设计题目介绍及分析使用MCS-51 系列单片机作为控制器,选用超声波模块,组建测距系统并显示结果。
三、设计方案论证通过循环来时时的对目标进行测距。
四、具体硬件设计说明蜂鸣器:通过PNP三极管驱动。
接到P3^2引脚。
按键:有键按下时IO口变为低电平。
开始按键连接到P3^1,P3^2的按键控制中断。
超声波模块:选用HC-SR04。
提供一个10uS以上脉冲触发信号,该模块内部将发出8个40kHz周期电平并检测回波。
一旦检测到有回波信号则输出回响信号。
回响信号的脉冲宽度与所测的距离成正比。
由此通过发射信号到收到的回响信号时间间隔可以计算得到距离。
超声波TRIG连接到P1^0,ECHO连接到P1^1。
LCD的E,RW,RS引脚分别接到单片机P2^7,P2^5,P2^6,P0口作为数据输出、五、软件设计说明发出超声波信号时开启定时器0,通过定时器计算回波信号持续时间进而计算出距离。
/******************************************************************************** 单片机课程设计* 题号: 27题,超声波测距* 组员:马铭阳,程岩,孔维士* 学号?30222204 130222206 130222207* 日期:2016年6月30日* 说明 KEY_START按下,程序执行,KEY1按下显示题号,持续10秒*******************************************************************************/#include<reg51.h>#include<intrins.h>#include<lcd.h>sbit Trig = P1^0; //超声波发送sbit Echo = P1^1; //超声波接收sbit key_start=P3^1; //开始按键sbit key1=P3^2; //中断按键sbit buzzer=P1^5; //蜂鸣器按键unsigned char code TABLE[] = " DISTANCE: ";unsigned char code ASCII[] ={'0','1','2','3','4','5','6','7','8','9','.','-','C','M',' '};unsigned char code CLASS[] = " NO.27 ";static unsigned char DisNum = 0; // unsigned int time=0;unsigned int i=0;unsigned int key_flag=0;long S=0;bit flag =0; //成功标志位unsigned char disbuff[4] ={ 0,0,0,0,};/********************************************************************* ************************************************************************************ *********///延时函数void delayms(unsigned int ms){unsigned char i=100,j;for(;ms;ms--){while(--i){j=10;while(--j);}}}//计算距离void Conut(void){time=TH0*256+TL0;TH0=0;TL0=0;S=(long)(time*0.17);if((S>=700)||flag==1){flag=0;LcdWriteData( ASCII[11]);LcdWriteData( ASCII[10]);LcdWriteData(ASCII[11]);LcdWriteData( ASCII[11]);LcdWriteData( ASCII[12]);buzzer=0;delayms(50);buzzer=1;}else{disbuff[3]=S%10000/1000;disbuff[2]=S%1000/100;disbuff[1]=S%100/10;disbuff[0]=S%10/1;LcdWriteData( ASCII[disbuff[3]]);LcdWriteData( ASCII[disbuff[2]]);LcdWriteData( ASCII[disbuff[1]]);LcdWriteData( ASCII[10]);LcdWriteData( ASCII[disbuff[0]]);LcdWriteData( ASCII[12]);LcdWriteData( ASCII[13]);}}//定时器0void zd0() interrupt 1 //触发时说明超出范围 {flag=1; //成功标志位置1}void inter() interrupt 0 //外部中断{LcdWriteCom(0x01);LcdWriteCom(0x80);for (i=0;i<7;i++){LcdWriteData(CLASS[i]);delayms(5);}delayms(100);LcdWriteCom(0x80);for (i=0;i<11;i++){LcdWriteData(TABLE[i]);delayms(5);}LcdWriteCom(0x80+0x46);}//超声波发射void StartModule(){Trig=1; //发脉冲_nop_(); //用NOP函数时间更精准 _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();Trig=0;}void key_board0(void) //按键扫描程序{while(1){if(key_start==0){delayms(10);if(key_start==0){while(!key_start);key_flag=1;break;}}else if(key1==0){delayms(10);if(key1==0){while(!key1);key_flag=2;break;}}}void key_board1(void){if(key_start==0){delayms(10);if(key_start==0){while(!key_start);key_flag=1;}}if(key1==0){delayms(10);if(key1==0){while(!key1);key_flag=2;}}}void main(void){P1 = 0xF0; //低位拉低 TMOD=0x01;TH0=0;TL0=0;ET0=1; //定时器0中断IT0=1; //外部中断0EX0=1;EA=1;LcdInit();key_board0();//key_board1();//if(key_flag==1)//{LcdWriteCom(0x80);for (i=0;i<11;i++) //显示DISTANCE{LcdWriteData(TABLE[i]);delayms(5);}LcdWriteCom(0x80+0x46);while(1){StartModule();while(!Echo); //判断是否收到回波信号TR0=1; //收到时,开启定时器while(Echo); //回波信号结束后关闭定时器TR0=0; //关闭定时器Conut(); //计算距离LcdWriteCom(0x80+0x46); //设置数据指针起点,第二排第一个delayms(80);}}以下是LCD显示程序#include"lcd.h"/********************************************************************* *********** 函数名 : Lcd1602_Delay1ms* 函数功能 : 延时函数,延时1ms* 输入 : c* 输出 : 无* 说名 : 该函数是在12MHZ晶振下,12分频单片机的延时。
********************************************************************** *********/void Lcd1602_Delay1ms(uint c) //误差 0us{uchar a,b;for (; c>0; c--){for (b=199;b>0;b--){for(a=1;a>0;a--);}}}/********************************************************************* *********** 函数名 : LcdWriteCom* 函数功能 : 向LCD写入一个字节的命令* 输入 : com* 输出 : 无********************************************************************** *********/#ifndef LCD1602_4PINS //当没有定义这个LCD1602_4PINS时void LcdWriteCom(uchar com) //写入命令{LCD1602_E = 0; //使能LCD1602_RS = 0; //选择发送命令LCD1602_RW = 0; //选择写入LCD1602_DATAPINS = com; //放入命令Lcd1602_Delay1ms(1); //等待数据稳定LCD1602_E = 1; //写入时序Lcd1602_Delay1ms(5); //保持时间LCD1602_E = 0;}#elsevoid LcdWriteCom(uchar com) //写入命令{LCD1602_E = 0; //使能清零LCD1602_RS = 0; //选择写入命令LCD1602_RW = 0; //选择写入LCD1602_DATAPINS = com; //由于4位的接线是接到P0口的高四位,所以传送高四位不用改Lcd1602_Delay1ms(1);LCD1602_E = 1; //写入时序Lcd1602_Delay1ms(5);LCD1602_E = 0;// Lcd1602_Delay1ms(1);LCD1602_DATAPINS = com << 4; //发送低四位Lcd1602_Delay1ms(1);LCD1602_E = 1; //写入时序Lcd1602_Delay1ms(5);LCD1602_E = 0;}#endif/********************************************************************* *********** 函数名 : LcdWriteData* 函数功能 : 向LCD写入一个字节的数据* 输入 : dat* 输出 : 无********************************************************************** *********/#ifndef LCD1602_4PINSvoid LcdWriteData(uchar dat) //写入数据{LCD1602_E = 0; //使能清零LCD1602_RS = 1; //选择输入数据LCD1602_RW = 0; //选择写入LCD1602_DATAPINS = dat; //写入数据Lcd1602_Delay1ms(1);LCD1602_E = 1; //写入时序Lcd1602_Delay1ms(5); //保持时间LCD1602_E = 0;}#elsevoid LcdWriteData(uchar dat) //写入数据{LCD1602_E = 0; //使能清零LCD1602_RS = 1; //选择写入数据LCD1602_RW = 0; //选择写入LCD1602_DATAPINS = dat; //由于4位的接线是接到P0口的高四位,所以传送高四位不用改Lcd1602_Delay1ms(1);LCD1602_E = 1; //写入时序Lcd1602_Delay1ms(5);LCD1602_E = 0;LCD1602_DATAPINS = dat << 4; //写入低四位Lcd1602_Delay1ms(1);LCD1602_E = 1; //写入时序Lcd1602_Delay1ms(5);LCD1602_E = 0;}#endif/********************************************************************* *********** 函数名 : LcdInit()* 函数功能 : 初始化LCD屏* 输入 : 无* 输出 : 无********************************************************************** *********/#ifndef LCD1602_4PINSvoid LcdInit() //LCD初始化子程序{LcdWriteCom(0x38); //开显示LcdWriteCom(0x0c); //开显示不显示光标LcdWriteCom(0x06); //写一个指针加1LcdWriteCom(0x01); //清屏LcdWriteCom(0x80); //设置数据指针起点}#elsevoid LcdInit() //LCD初始化子程序{LcdWriteCom(0x32); //将8位总线转为4位总线LcdWriteCom(0x28); //在四位线下的初始化LcdWriteCom(0x0c); //开显示不显示光标LcdWriteCom(0x06); //写一个指针加1LcdWriteCom(0x01); //清屏LcdWriteCom(0x80); //设置数据指针起点}#endif六、测试及调试硬件调试:焊接前用恒流源供电测量每个元件是否工作正常。