当前位置:文档之家› 基于单片机的红外测距系统设计 - 副本

基于单片机的红外测距系统设计 - 副本

北京联合大学应用科技学院实训报告基于单片机的红外测距系统设计系别电子专业电子信息工程技术年级12级02班组长:张祎楠2012191294068组员:殷跃2012191294070 白雨童2012191294063目录第1章绪论 (1)1.1 本课题研究的目的 (1)1.2 本课题研究的内容 (1)13整个红外测距系统显示 (4)第2章红外测距的软件设计 (5)后记 (6)第1章绪论1.3 本课题研究的目的我们所进行的课题便是做一个简易的,精确的,近距离的距离检测仪,这也是对我们所学知识的一种考验方法,从中我们可以更系统的认识单片机,了解AD转换和红外收发模块。

1.4 本课题研究的内容红外传感器的测距基本原理为:红外发射电路的红外发光管发出红外光,红外接收电路的光敏接收管接收发射光,根据发射光的强弱判断出所测的距离。

由于接收管接收的光强度是随着发光管与测量物的距离变化而变化的,因而,与测量物的距离近则接收光强,距离远则接收光弱。

具体方法如图1所示,红外模块发出并接收到红外线信号;AD转换模块将接收到的模拟信号转换成数字信号再交给单片机, 启动单片机中断程序,此时单片机得到数字信号也就是电压值,再由软件进行判别、计算,得出距离数并送给LED/LCD显示。

红外模块电压距离公式AD模块单片机显示模块图1.1 反射能量法原理图3.7 protues中整体系统单片机AT89C52左端分别接了时钟电路和复位电路,这是单片机最小的系统。

XTAL1和XTAL2串连一个晶振,并且分别接上一个20p的电容,两个电容另一端都接地,构成时钟电路。

RST同时接上100p电容,4脚按键,1k电阻,4脚按键另一端接上一个1k电阻再与100p电容并联接VCC,1k电阻另一端则接地,构成复位电路。

单片机AT89C52右端P0端同时接LED的D1-D7端口和排阻,P2.0接CLK,P2.1接DO,P2.2接CS,P2.5接E,P2.6接RW,P2.7接RS。

MCP3001的VREF接vcc,IN+接红外距离传感器的Vo。

软件程序#include <reg51.h>#include <intrins.h>#define uchar unsigned char#define uint unsigned int#define ulong unsigned longsbit RS=P2^0; //LCD命令/数据端sbit RW=P2^1; //LCD读/写端sbit LCDE=P2^2; //LCD使能端sbit MCP_CS=P2^3; //MCP3001与AT89S52的管脚接线定义sbit MCP_DO=P2^4;sbit MCP_CLK=P2^5;uint measure;uchar flag; //Busy标志uchar code dis[]={"Measure Start"}; //显示uchar code dis1[] = {"V= . V,L= CM"};uchar code dis2[] = {"0123456789."}; //显示代码uchar code dis3[]={"Out Measure!"}; //显示uchar dis_buf[8]; //显示缓冲区void L_delay(void); //短延时void delay_ms(uint n); //延时函数uint read_MCP(void); //读MCP3001void init_1602(void); //1602初始化函数void busy(void); //LCD忙标志判断函数void dat_wrt(uchar dat); //写数据子函数void cmd_wrt(uchar cmd); //写命令子函数uint distance(void); //距离计算函数void lcd_start(uchar start); //设定显示位置函数void LCD_Clear(void); //LCD清屏函数uchar dat_adj(uint dat1); //显示数据调整函数void print(uchar *str); //字符串显示函数void disp(uint dat); //显示子函数uint average(void); //算术平均滤波程序/****************************主函数*******************************/main(){init_1602();print(dis); //显示测量开始delay_ms(1000);while(1){measure=distance();disp(measure); //显示高度delay_ms(100);}}/**************************延时函数**************************/ void delay_ms(uint n){uint j;while(n--){for(j=0;j<125;j++);}}/***************************短延时****************************/ void L_delay(void){uchar i;for(i=0;i<5;i++)_nop_();}/************************读MCP3001函数*************************/ uint read_MCP(void)////////////////////////// read_MCP 采集的数据并转换后的值//////////////////////////{uchar i;uint temp=0;MCP_CS=1;L_delay();MCP_CS=0; //CS置低,开始采样数据for(i=0;i<13;i++) //读转换的10位数据{MCP_CLK=0;L_delay();MCP_CLK=1;temp<<=1;if(MCP_DO==1)temp|=0x01;}MCP_CS=1;temp&=0x03ff; //获取有效转换值return(temp);}/************************LCD忙标志判断函数*******************/void busy(void){flag=0x80; //赋初值高位为1 禁止while (flag&0x80) //读写操作使能位禁止时等待继续检测{P0=0xff;RS=0; //指向地址计数器RW=1; //读LCDE=1; //信号下降沿有效flag=P0; //读状态位元高位为状态LCDE=0;}}/************************写数据子函数************************/void dat_wrt(uchar dat){busy(); //检测读写操作使能吗LCDE=0;RS=1; //指向数据寄存器RW=0; //写P0=dat; //写数据LCDE=1; //高电平有效LCDE=0;}/*************************写命令子函数************************/void cmd_wrt(uchar cmd){LCDE=0;busy(); //检测读写操作使能吗P0=cmd; //命令RS=0; //指向命令计数器RW=0; //写LCDE=1; //高电平有效LCDE=0;}/***********************距离计算函数***************************/ uint distance(void){uint temp1;temp1=average();/////////////////////////////////temp1 平均数据转换的距离//////////////////////////////////// if((temp1>60)&(temp1<960)) //在正常测量范围?{temp1=13569/(temp1+7)-4; //转换测量数据}else{temp1=0x00ff; //超出测量范围,返回错误标志}return(temp1);}/************************算术平均滤波程序**********************/ uint average(void){uchar i;uint av_dat;/////////////////////////////////av_dat 平均数据////////////////////////////////////////ulong ave=0;for(i=0;i<10;i++) //连续读取10个数据值{ave+=read_MCP(); //读转换数据L_delay();}av_dat=(uint)(ave/10); //求平均值return(av_dat);}/*************************1602初始化函数************************/void init_1602(void){cmd_wrt(0x01); //清屏cmd_wrt(0x0c); //开显示,不显示游标,不闪烁cmd_wrt(0x06); //完成一个字符码传送后,光标左移,显示不发生移位元cmd_wrt(0x38); //16×2显示,5×7点阵,8位数据接口}/************************设定显示位置函数************************/void lcd_start(uchar start){cmd_wrt(start|0x80);}/************************LCD清屏函数****************************/void LCD_Clear(void){cmd_wrt(0x01); //写入清屏指令delay_ms(1);}/************************显示数据调整函数************************/uchar dat_adj(uint dat1)/////////////////////////////////dat1 L距离////////////////////////////////////////{uchar i=0;uint date;date=average()/2;dis_buf[0]=(uchar)(dat1/100); //百位dis_buf[1]=(uchar)(dat1%100/10); //十位dis_buf[2]=(uchar)(dat1%100%10); //个位dis_buf[3]= date/100 ;dis_buf[4]= date%100/10;dis_buf[5]= date%100%10;if(dis_buf[0]==0)i=1;return(i);}/**************************字符串显示函数**************************/ void print(uchar *str){while(*str!='\0') //直到字符串结束{dat_wrt(*str);str++; //指向下一个字符}}/***************************显示子函数****************************/ void disp(uint dat){uchar temp,j;if(dat!=0x00ff){temp=dat_adj(dat);LCD_Clear();lcd_start(0x40);print(dis1);lcd_start(0x42);dat_wrt(dis2[dis_buf[3]]);print(".");for(j=4;j<6;j++)dat_wrt(dis2[dis_buf[j]]); //显示文字lcd_start(0x4B+temp); //确定显示起始位置for(j=temp;j<3;j++) //写显示数据dat_wrt(dis2[dis_buf[j]]);}else{LCD_Clear();lcd_start(0x42+temp); //确定显示起始位置print(dis3);}}后记在这次论文设计中我明白了理论和实际之间有着巨大的差距,理论成立但毕竟只是原理上,一旦做起来就会发现现实中有着各种各样的因素影响着你,只看理论是不会发现这些的,只有实践中你才会发现自己的不足。

相关主题