版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第八章
单片机应用系统设计目录CONTENTS01单片机应用系统设计基础基本组成、开发流程与一般性设计原则04智能巡航小车项目开发红外/超声波模块原理、导航策略与运动控制实现03I单片机测温系统设计传感器模块选型、硬件搭建与温度采集程序开发02简易数字时钟项目实践功能分析、方案设计、硬件电路与软件实现05综合项目复盘与知识点梳理系统设计流程总结、关键模块选型与程序优化学习目标01系统设计基础掌握理解单片机应用系统的基本组成,掌握从需求分析到软硬件设计的完整开发流程,能独立制定项目设计方案。02核心模块原理吃透理解红外光电反射、超声波测距等传感器工作原理,掌握HJ-IR2、HC-SR04等常用模块的接口电路与驱动编程方法。03工程实践能力提升能独立完成数字时钟、测温系统、巡航小车等综合项目的硬件电路搭建、程序编写与Proteus仿真调试,掌握模块化编程思想。04综合应用与问题解决掌握多传感器信息融合的智能导航策略,能根据项目需求完成元件选型、绘制硬件原理图与程序流程图,具备单片机项目从设计到实现的完整工程实践能力。8.1单片机应用系统设计与开发过程8.1.1单片机应用系统的基本组成
单片机应用系统通常由硬件和软件两部分组成,具体可分为以下模块。(1)硬件部分。
单片机:作为控制中心,包含CPU、存储器和I/O接口电路,负责数据处理和逻辑控制。
输入通道:包括传感器、按键等设备,将外部信号转换为单片机可处理的电信号。
输出通道:如LED、电动机、继电器等执行机构,将经单片机处理后的电信号转换为实际动作。
通信接口:支持UART、SPI、I2C等通信协议,实现与其他设备的数据交互。
人机交互模块:如键盘、显示屏、触摸屏等,提供用户操作与信息反馈的途径。
电源模块:为系统提供稳定供电,通常包含稳压电路和滤波电路。
时钟与复位电路:确保单片机时序同步和系统初始化。
部分单片机应用系统还可能扩展外部存储器(如EEPROM、Flash)或专用外设模块(如ADC)。8.1.2单片机应用系统设计的基本流程(2)软件部分。系统软件:如监控程序、中断服务程序等底层驱动代码。应用软件:包括控制算法、数据处理程序等实现特定功能的代码。部分单片机应用系统通过上位机进行界面显示与控制,常用的上位机软件有Qt、LabView等。((1)需求分析与总体方案设计。
明确系统要实现的功能和性能指标(如响应时间、精度)、环境约束(如温度、功耗),这是整个设计的基础。
通过需求分析厘清单片机应用系统的总体架构,进行总体方案设计,画出系统功能和原理框图。
总体方案设计就是根据任务需求,进行方案论证,通过技术调研确定软/硬件分工,优先选择成熟的技术方案,如选择兼容性强的单片机(如8051内核系列、STM32),实时性要求高的功能(如电动机控制)优先用硬件实现,复杂逻辑(如协议解析)采用软件实现,平衡性能与成本、可维护性。(2)硬件开发阶段。
单片机应用系统的硬件设计包括主器件选型、系统扩展和配置等。
首先完成核心器件选型,包括主控芯片与外设(如传感器、ADC)选型选择高集成度芯片(如系统级单片机),减少器件数量,以降低干扰和功耗,简化系统设计。
然后进行电路设计,需考虑存储资源分配、I/O口扩展与外设配置。绘制原理图,包括电源管理电路、时钟电路、复位电路、抗干扰设计(如地线分离、电容滤波)等。进行PCB布局时,需考虑电磁兼容性和散热问题,在关键器件旁安装去耦电容(0.1μF瓷片电容),数字地和模拟地分开布线,高频与低频模块分区布局。同时,准备单片机开发板,进行程序串口烧录调试,搭建测试电路。(3)软件开发阶段。
进行软件设计时,应根据软件的功能要求,将软件分成若干个相对独立的部分,并根据它们之间的联系和时间上的关系,设计出软件的总体结构,画出程序流程图。画程序流程图时,还要对系统资源进行具体分配和说明。
编程需要搭建软件开发环境,如使用KeilμVision、IAR或STM32CubeIDE配置编译器(如ARMCC)和调试接口(SWD/JTAG),还需要匹配目标芯片型号(如STC89C52),安装其他必要的设备驱动。
程序代码一般采用模块化和分层架构设计,分为驱动层(硬件抽象)、中间件层(封装通信协议)和应用层(业务逻辑)等。
在实时性处理时,通过中断优先级管理确保关键任务响应,如定时/计数器中断需配置为最高优先级。在进行数据采集时,注意采取双缓冲机制,确保A/D采样与处理不冲突。(4)系统集成与调试。
可以结合Proteus仿真验证硬件交互逻辑和系统理论设计的正确性。通过Proteus软件构建系统性仿真电路,并与Keil等程序开发平台进行联调。采用分块调试法,独立验证各模块功能(如按键识别、显示驱动、通信协议等),再进行系统性验证,在测试过程中反复调试、优化程序,最后完成系统集成的实物样机制作与脱机运行,在实际环境中测试系统运行的效果和稳定性,测试过程中同样需要进行反复调试及修改,优化系统性能。
整个设计开发过程还需要注意整理设计报告(包括电路图、过程文件、代码注释和测试记录等),硬件设计需预留调试接口(如JTAG/UART),软件代码应添加注释,便于后期维护。
单片机应用系统设计的关键性因素及评价指标如下。①
功能完备性:系统应满足预设的设计目标和性能指标。②
可靠性:采用看门狗定时器防止程序“跑飞”,确保复位信号可靠,合理设计电源滤波和去耦电路。③
操作简便性:人机交互界面应友好、直观。④
性价比:平衡成本与性能,避免过度设计。⑤
可维护性:预留调试接口,便于后期维护和升级。⑥
功耗:根据应用场景选择合适的低功耗设计。
通过以上步骤和注意事项,可以系统地进行单片机应用系统的设计。在实际项目操作中,建议从简单功能开始,逐步增加复杂度,并充分利用现有开发工具和参考案例。8.2简易单片机数字时钟8.2.1简易单片机数字时钟的基本功能简易单片机数字时钟的基本功能如下。(1)仅使用单片机本身的时钟资源。(2)使用数码管清晰显示时、分、秒。(3)具有调时、调分功能。(4)具有扩展功能,如休眠省电、定时报警等。8.2.2简易单片机数字时钟的设计方案
根据简易单片机数字时钟的基本功能可知,除了单片机和数码管等核心模块,还需要采用按键实现调时和调分功能,同时使用驱动电路驱动数码管高清显示。简易单片机数字时钟主要由单片机、晶振、独立按键、驱动电路、数码管及电源组成,如图8.2所示。单片机、晶振与电源构成单片机最小系统。8.2.3简易单片机数字时钟的主要模块
主要部件有三个,分别是单片机、数码管及驱动电路、独立按键。常用的51单片机型号主要有AT89C51/52、STC89C51/52等,为充分使用单片机资源,使用性价比更高的单片机AT89C2051。数码管有共阴极和共阳极两种类型。为了设计需要和方便,本设计使用2位共阳极数码管,并使用三极管驱动电路代替驱动芯片。独立按键使用四脚轻触开关。(1)AT89C2051。AT89C2051相较于AT89C51/52等芯片价格低廉,而且引脚数量比AT89C51/52等单片机少一半,节省了资源。其外形和引脚排列如图8.3所示。名称参数规格极性共阳性屏幕尺寸0.36英寸字位数2位外形尺寸15*14*7.2mm正常电流20mA工作温度-40~+80℃表8.2
数码管主要参数表表8.3
S9012主要参数表名称参数规格极性PNPPCN功率300mwIc电流300mA集电极-基极电压40V集电极-发射极电压25V发射极-基极电压5VhFE(min)120hFE(max)350(2)2位共阳极数码管及驱动电路。2位共阳极数码管采用小功率三极管S9012放大电路驱动,2位共阳极数码管及三极管S9012的外形如图8.4所示。(3)独立按键。
独立按键使用四脚轻触开关,这是一种常见的电子开关,也称之为按键开关,它的外观和引脚连接如图8.5所示,1、2、3、4分别表示四脚轻触开关的4个引脚,初始时1和2、3和4分别是导通的,因此,只要将四脚轻触开关作用的线路分别接在(1,3)、(1,4)、(2,3)、(2,4)四种组合中的一种上,均能达到开关效果。8.2.4简易单片机数字时钟的硬件电路。
单片机的P1口连接数码管的段选线,P3口分别接在三极管的基极使其处于导通或截止状态,通过三极管驱动电路实现位选功能。8.2.5简易单片机数字时钟的软件设计
(1)程序设计流程。本设计的核心是定时时间的控制。首先启动AT89C2051中的定时/计数器T0与T1,它们分别用于实现1s定时和判断按键的短按与长按。由于定时/计数器最多是16位,对于12MHz的晶振,最大定时时长是65.536ms,本设计采用定时50ms,计数20次实现1s定时。当按键短按(按下时长不大于500ms)时,系统处于省电模式,数码管处于休眠状态;当按键长按(按下时长大于500ms)时,进入调分和调时模式。程序设计流程如图8.6所示。为了确保方案的可行性及程序的有效性,采用Proteus软件进行电路仿真,如图8.7所示。#include<REG2051.H>codesenen_seg[20]={0x01,0x7c,0x42,0x44,0x2c,0x05,0x01,0x5c,0x00,0x04};unsignedinthour=10,minute=10,second=0,temp=0;unsignedinthour_s=0,hour_g=0,minute_s=0,minute_g=0,second_s=0,second_g=0;unsignedcharcount_time_0=0,count_time_1=0,digital_key=0;
voiddelay_ms(unsignedintt)//延时tms{unsignedinti,j;for(i=0;i<t;i++)for(j=0;j<100;j++);}voiddelay(unsignedintt){unsignedinti,j;for(i=0;i<t;i++)for(j=0;j<10;j++);}voidtime0_init(void){TMOD=0x11;TH0=(65535-50000)/256;//定时50msTL0=(65535-50000)%256;EA=1;ET0=1;TR0=1;}voidtime1_init(void){TMOD=0x11;TH1=(65535-50000)/256;//定时50msTL1=(65535-50000)%256;EA=1;ET1=1;TR1=1;}(2)程序代码。简易单片机数字时钟的参考例程mcu801.c的代码如下。voidtimer0()interrupt1{TH0=(65535-50000)/256;TL0=(65535-50000)%256;count_time_0++;if(count_time_0==20){count_time_0=0;second++;if(second>=60){second=0;minute++;if(minute>=60){minute=0;hour++;if(hour>=24)hour=0;}}}}voidtimer1()interrupt3//定时/计数器T1作用于数码管闪烁状态下{TH1=(65535-50000)/256;TL1=(65535-50000)%256;if(temp==0)//如果temp变量等于0,则进入调分模式,此时分钟数码管闪烁{hour_s=hour/10;hour_g=hour%10;minute_s=minute/10;minute_g=minute%10;second_s=second/10;second_g=second%10;P1=senen_seg[hour_s];P3_5=0;P3_4=1;P3_3=1;P3_2=1;P3_1=1;P3_0=1;delay(10);P1=senen_seg[hour_g];P3_5=1;P3_4=0;P3_3=1;P3_2=1;P3_1=1;P3_0=1;delay(10);P1=senen_seg[minute_s];P3_5=1;P3_4=1;P3_3=0;P3_2=1;P3_1=1;P3_0=1;delay_ms(20);P1=senen_seg[minute_g];P3_5=1;P3_4=1;P3_3=1;P3_2=0;P3_1=1;P3_0=1;delay_ms(20);P1=senen_seg[second_s];P3_5=1;P3_4=1;P3_3=1;P3_2=1;P3_1=0;P3_0=1;delay(10);P1=senen_seg[second_g];P3_5=1;P3_4=1;P3_3=1;P3_2=1;P3_1=1;P3_0=0;delay(10);}else//如果temp变量等于1,则进入调时模式,此时时钟数码管闪烁{hour_s=hour/10;hour_g=hour%10;minute_s=minute/10;minute_g=minute%10;second_s=second/10;second_g=second%10;P1=senen_seg[hour_s];P3_5=0;P3_4=1;P3_3=1;P3_2=1;P3_1=1;P3_0=1;delay_ms(20);P1=senen_seg[hour_g];P3_5=1;P3_4=0;P3_3=1;P3_2=1;P3_1=1;P3_0=1;delay_ms(20);P1=senen_seg[minute_s];P3_5=1;P3_4=1;P3_3=0;P3_2=1;P3_1=1;P3_0=1;delay(10);P1=senen_seg[minute_g];P3_5=1;P3_4=1;P3_3=1;P3_2=0;P3_1=1;P3_0=1;delay(10);P1=senen_seg[second_s];P3_5=1;P3_4=1;P3_3=1;P3_2=1;P3_1=0;P3_0=1;delay(10);P1=senen_seg[second_g];P3_5=1;P3_4=1;P3_3=1;P3_2=1;P3_1=1;P3_0=0;delay(10);}}}voidtime_display(void){hour_s=hour/10;hour_g=hour%10;minute_s=minute/10;minute_g=minute%10;second_s=second/10;second_g=second%10;P1=senen_seg[hour_s];P3_5=0;P3_4=1;P3_3=1;P3_2=1;P3_1=1;P3_0=1;delay(10);P1=senen_seg[hour_g];P3_5=1;P3_4=0;P3_3=1;P3_2=1;P3_1=1;P3_0=1;delay(10);P1=senen_seg[minute_s];P3_5=1;P3_4=1;P3_3=0;P3_2=1;P3_1=1;P3_0=1;delay(10);P1=senen_seg[minute_g];P3_5=1;P3_4=1;P3_3=1;P3_2=0;P3_1=1;P3_0=1;delay(10);P1=senen_seg[second_s];P3_5=1;P3_4=1;P3_3=1;P3_2=1;P3_1=0;P3_0=1;delay(10);P1=senen_seg[second_g];P3_5=1;P3_4=1;P3_3=1;P3_2=1;P3_1=1;P3_0=0;delay(10);}voidtime_min_twinkle(void){ET1=1;TR1=1;hour_s=hour/10;hour_g=hour%10;minute_s=minute/10;minute_g=minute%10;second_s=second/10;second_g=second%10;P1=senen_seg[hour_s];P3_5=0;P3_4=1;P3_3=1;P3_2=1;P3_1=1;P3_0=1;delay(10);P1=senen_seg[hour_g];P3_5=1;P3_4=0;P3_3=1;P3_2=1;P3_1=1;P3_0=1;delay(10);P1=senen_seg[second_s];P3_5=1;P3_4=1;P3_3=1;P3_2=1;P3_1=0;P3_0=1;delay(10);P1=senen_seg[second_g];P3_5=1;P3_4=1;P3_3=1;P3_2=1;P3_1=1;P3_0=0;delay(10);}voidtime_hour_twinkle(void){ET1=1;TR1=1;hour_s=hour/10;hour_g=hour%10;minute_s=minute/10;minute_g=minute%10;second_s=second/10;second_g=second%10;P1=senen_seg[minute_s];P3_5=1;P3_4=1;P3_3=0;P3_2=1;P3_1=1;P3_0=1;delay(10);P1=senen_seg[minute_g];P3_5=1;P3_4=1;P3_3=1;P3_2=0;P3_1=1;P3_0=1;delay(10);P1=senen_seg[second_s];P3_5=1;P3_4=1;P3_3=1;P3_2=1;P3_1=0;P3_0=1;delay(10);P1=senen_seg[second_g];P3_5=1;P3_4=1;P3_3=1;P3_2=1;P3_1=1;P3_0=0;delay(10);}intadjust_min(void){ET0=0;TR0=0;while(1){while(P3_7==1)//如果没有按键被按下,则分钟数码管一直闪烁{time_min_twinkle();}if(P3_7==0)//如果有按键被按下,则判断是长按还是短按{delay(10);//消抖if(P3_7==0){
delay_ms(500);if(P3_7==1)//如果是短按(按下时长不大于500ms),则进行分钟加1{minute++;if(minute==60){minute=0;}}else//如果是长按,则进入调时模式{return1;}}}}}intadjust_hour(void){ET0=0;TR0=0;{while(P3_7==1)//如果没有按键被按下,则时钟数码管一直闪烁{time_hour_twinkle();}if(P3_7==0)//如果有按键被按下,则判断是长按还是短按{delay(10);//消抖if(P3_7==0){delay_ms(500);if(P3_7==1)//如果是短按(按下时长不大于500ms),则进行时钟加1{hour++;if(hour==24){hour=0;}}else//如果是长按,则进入调分模式{return1;}}}}}//主函数voidmain(){P3_7=1;time0_init();time1_init();//初始化ET1=0;//先关闭定时/计数器T1,在数码管闪烁时开启TR1=0;while(1){if(digital_key==0)//判断是否是省电模式,若digital_key=0,则不是省电模式{time_display();if(P3_7==0){delay(10);//消抖if(P3_7==0){delay_ms(500);if(P3_7==1)//第一次为短按(按下时长不大于500ms),进入省电模式{digital_key=1;}else//第一次为长按(按下时长大于500ms),进入调分模式{temp=adjust_min();ET1=0;TR1=0;if(temp==1){adjust_hour();temp=0;ET0=1;TR0=1;ET1=0;TR1=0;}}}}}else{P1=0xff;P3_5=1;P3_4=1;P3_3=1;P3_2=1;P3_1=1;P3_0=1;if(P3_7==0){delay(10);//消抖if(P3_7==0){delay_ms(500);if(P3_7==1)//第一次为短按(按下时长小于500ms),进入省电模式{digital_key=0;}}}}}}8.3单片机测温系统
获取环境温度是常见的测量需求之一,如测量室温、体温、水温等。本设计通过一个简单的温度传感器来实时采集房间内的温度,然后通过显示模块显示当前温度。8.3.1单片机测温系统的基本功能8.3.2单片机测温系统的设计方案
单片机测温系统的基本功能如下。(1)能够测量房间内的温度。(2)温度的测量精度为0.1℃。(3)能够通过显示模块显示测得的温度。
根据系统的基本功能可知,除了单片机和温度传感器等核心模块外,还需要显示模块,由于数码管在显示信息较多时占用的资源较多且显示不稳定,因此,本设计中的显示模块采用LCD。单片机测温系统的总体结构图如图8.8所示。单片机、晶振与电源构成单片机最小系统。8.3.3单片机测温系统的主要模块
根据系统的设计方案可知,单片机测温系统的主要部件有三个,分别是单片机、温度传感器及LCD。常用的51单片机型号主要有AT89C51/52、STC89C51/52等,本设计采用资源丰富的STC89C52单片机,温度传感器选择DS18B20,LCD选择LCD1602。DS18B20进行温度采集时严格按照一定的时序执行读/写操作。
STC89C52基于经典8051内核,与工业80C51产品指令和引脚兼容,相较于AT89C52价格更低廉,内部集成了8KB在系统可编程Flash存储器,具备512BRAM、2个数据指针、3个16位定时器/计数器,软件可选节电模式。其外形及引脚排列如图8.9所示。8.3.4单片机测温系统的硬件电路8.3.5单片机测温系统的软件设计1.程序设计流程
软件设计以Keil为开发平台,显示温度的主程序流程如图8.12(a)所示。当温度为非负值时,直接获取温度的百位、十位、个位和小数位;当温度为负值时,先取出温度的负号,再获取十位、个位和小数位。获取温度主要分为三个步骤:首先启动DS18B20进行温度转换;然后等待DS18B20完成温度转换;最后复位初始化DS18B20,发送读温度转换值指令并读取温度转换值。温度获取程序流程如图8.12(b)所示。2.程序代码单片机测温系统的参考例程mcu802.c的代码如下。#include<reg52.h>#include<string.h>#include<intrins.h>#include<math.h>#defineucharunsignedchar#defineuintunsignedintsbitDQ=P3^6;//DS18B20的数据线接单片机的P3.6引脚sbitRS=P1^7;sbitRW=P1^6;sbitE=P1^5;ucharstr0[]={"Thetemperature"};//第1行显示内容ucharstr1[]={"is:000.0C"};//第2行显示内容voidinit(void);voidwc51r(uchari);voidwc51ddr(uchari);voidlcd1602wstr(ucharhang,ucharlie,ucharlength,uchar*str);voidfbusy(void);bitDS18B20_Init(void);shortDS18B20_Get_Temp(void);voidDelay_ms(uintDelay){uintL;for(;Delay>0;Delay--)for(L=0;L<110;L++);}//主函数voidmain(){ucharTEMP=0;DS18B20_Init();while(DS18B20_Get_Temp()==850);init();lcd1602wstr(0,1,strlen(str0),str0);//从第1行第2列开始显示lcd1602wstr(1,1,strlen(str1),str1);//从第2行第2列开始显示while(1){TEMP=DS18B20_Get_Temp();//获取温度if(TEMP>=0){str1[3]=TEMP/1000+0x30;//百位str1[4]=TEMP/100%10+0x30;//十位str1[5]=TEMP/10%10+0x30;//个位str1[7]=TEMP%100%10+0x30;//小数位}else{TEMP=abs(TEMP);str1[3]='-';//负号str1[4]=TEMP/100+0x30;//十位str1[5]=TEMP/10%10+0x30;//个位str1[7]=TEMP%100%10+0x30;//小数位}lcd1602wstr(1,1,strlen(str1),str1);//从第2行第2列开始显示温度Delay_ms(10);}/****************************LCD1602**************************************///初始化函数voidinit(){wc51r(0x38);//使用8位数据,显示两行,显示5×7点阵字符wc51r(0x0c);//显示器开,光标关,光标不闪烁wc51r(0x06);//字符不动,光标自动右移一格wc51r(0x01);//清屏}//检测忙标志函数voidfbusy(){P0=0Xff;RS=0;RW=1;E=0;E=1;while(P0&0x80){E=0;E=1;}//LCD1602忙,等待}//写指令函数voidwc51r(ucharj){fbusy();E=0;RS=0;RW=0;E=1;P0=j;E=0;}//写数据函数voidwc51ddr(ucharj){fbusy();E=0;RS=1;RW=0;E=1;P0=j;E=0;}/*字符串显示函数入口参数:hang为行号;lie为列号;length为字符串长度;*str为字符串*/voidlcd1602wstr(ucharhang,ucharlie,ucharlength,uchar*str){uchari;wc51r(0x80+0x40*hang+lie);for(i=0;i<length;i++){wc51ddr(*str);str++;}}/****************************DS18B20***************************************/voidDelay750us()//@11.0592MHz{unsignedchari,j;i=9;j=13;do{while(--j);}while(--i);}voidDelay15us()//@11.0592MHz{unsignedchari;_nop_();_nop_();i=38;while(--i);}//复位DS18B20voidDS18B20_Rst(void){DQ=0;//拉低数据线DQ的电平Delay750us();//延时750μsDQ=1;//DQ=1Delay15us();//延时15μs}voidDelay12us()//@11.0592MHz{unsignedchari;_nop_();i=30;while(--i);}voidDelay50us()//@11.0592MHz{unsignedchari,j;nop_();_nop_();_nop_();i=1;j=133;do{while(--j);}while(--i);}voidDelay2us()//@11.0592MHz{unsignedchari;_nop_();_nop_();i=2;while(--i);}voidDelay60us()//@11.0592MHz{unsignedchari,j;_nop_();_nop_();i=1;
j=161;do{while(--j);}while(--i);}//等待DS18B20的回应//返回1:DS18B20存在//返回0:DS18B20存在bitDS18B20_Check(void){ucharretry=0;while(DQ&&retry<200){retry++;_nop_();};if(retry>=200)return1;elseretry=0;while(!DQ&&retry<240){retry++;_nop_();};if(retry>=240)return1;return0;}//从DS18B20中读取一位数据//返回值:1或0bitDS18B20_Read_Bit(void){bitdat;DQ=0;_nop_();_nop_();DQ=1;Delay12us();if(DQ)dat=1;elsedat=0;Delay50us();returndat;}//从DS18B20读取一个字节数据//返回值:读取到的数据ucharDS18B20_Read_Byte(void){uchari,j,dat;dat=0;for(i=1;i<=8;i++){j=DS18B20_Read_Bit();dat=(j<<7)|(dat>>1);}returndat;}//写一个字节数据到DS18B20//dat:要写入的字节数据voidDS18B20_Write_Byte(uchardat){ucharj;uchartestb;for(j=1;j<=8;j++){testb=dat&0x01;dat=dat>>1;if(testb){DQ=0;Delay2us();DQ=1;Delay60us();}else{DQ=0;Delay60us();DQ=1;Delay2us();}}}//启动温度转换voidDS18B20_Start(void){DS18B20_Rst();DS18B20_Check();DS18B20_Write_Byte(0xcc);//跳过ROMDS18B20_Write_Byte(0x44);//进行温度转换}//初始化DS18B20数据线DQ的同时检测DS18B20的存在//返回1:DS18B20不存在//返回0:DS18B20存在
bitDS18B20_Init(void){DS18B20_Rst();returnDS18B20_Check();}//从DS18B20中得到温度//精度:0.1℃//返回值:温度(-550~1250)
shortDS18B20_Get_Temp(void){uchartemp;ucharTL,TH;shorttem;DS18B20_Start();//启动温度转换DS18B20_Rst();DS18B20_Check();DS18B20_Write_Byte(0xcc);//跳过ROMDS18B20_Write_Byte(0xbe);//读取温度TL=DS18B20_Read_Byte();//读取温度低8位TH=DS18B20_Read_Byte();//读取温度高8位if(TH>7){TH=~TH;TL=~TL;temp=0;//温度为负
}elsetemp=1;//温度为正
tem=TH;//获得高8位tem<<=8;tem+=TL;//获得低8位tem=(float)tem*0.625;//转换为10倍温度if(temp)returntem;//返回温度elsereturn-tem;}8.4单片机巡航小车8.4.1单片机巡航小车的基本功能
本设计通过多传感器收集外部环境信息并结合一定的运动控制策略,以实现单片机巡航小车在较为复杂环境下的自主巡航。单片机巡航小车主要有沿黑线自动循迹、自动避障及自动跟随功能。距离测量通过超声波传感器实现,自动循迹功能基于小车上两个红外光电传感器发出的红外光线会被深色物体表面吸收这一特性来实现,根据两个红外反射传感器发出的红外光线是否被反射来实现自动避障和自动跟随功能。
单片机巡航小车的基本功能如下。(1)能够沿由黑色绝缘带制作的引导路线(黑线)自动循迹行驶。(2)能够在巡航过程中实现障碍物检测、自动避障、自动跟随。(3)能够通过超声波传感器测距并显示厘米级的距离值。8.4.2单片机巡航小车的设计方案
根据单片机巡航小车的基本功能可知,单片机巡航小车的主要器件有STC89C52单片机和L293D直流电动机驱动模块,电源采用7.4V锂电池,2个直流电动机,4个红外传感器,1个超声波传感器,显示模块采用LCD1602。单片机巡航小车的总体结构图如图8.13所示,小车通过一对红外光电传感器识别地面上的黑线轨迹,控制小车沿特定路线行驶。另外一对红外反射传感器用于检测前方障碍物,当小车与障碍物之间的距离小于设定值时,小车转向避开,配置PWM信号调节直流电动机的速度。在图8.13中,独立按键用于切换小车的运动模式。8.4.3单片机巡航小车的主要模块
单片机巡航小车主要部件中的单片机STC89C52、显示模块LCD1602、直流电动机驱动模块L293D不在详细介绍。(1)红外反射传感器HJ-IR2。
红外传感器相当于机器人的眼睛,发射并检测反射回的红外线,内置光、电滤波器,只允许波长为980nm的红外线和频率约为38.5kHz的电信号通过。从而防止了其他光源对红外光谱的干涉。太阳光是直流干涉源(0Hz),而室内光依赖于所在区域的主电源,闪烁频率接近100~120Hz,该频率在电子滤波器的38.5kHz通带频率之外,因此被红外传感器忽略。红外反射传感器一般带有两个二极管,一个用来发射一定频率的红外信号,另一个用来接收这种频率的红外信号。
本设计使用图8.14所示的红外反射传感器HJ-IR2,该传感器相当于一个红外电子开关,采用漫反射式检测原理,红外发射管发出38.5kHz红外信号,遇到障碍物后反射,被红外接收管接收。内部芯片对信号进行放大和比较,最终输出数字信号(TTL电平),低电平表示检测到障碍物,高电平表示未检测到障碍物。HJ-IR2模块为三线制,VCC为+5V电源,OUT为信号输出端,GND接电源负极,工作电压为5V,工作电流为18~30mA,检测距离通常为1~30cm,受供电电压、环境光线等因素影响。
安装时,将两对红外传感器分别固定在小车车头的两侧,如图8.15所示。注意:用于循迹的一对红外光电传感器居中且彼此间距不能过窄,要比循迹路径宽1~2cm;对于用于避障的一对红外反射传感器,需要调节红外传感器的灵敏度来控制转向时与障碍物的距离,即需要根据实际情况调试红外传感器的灵敏度。红外传感器以下统称为IR探测器。
红外信号发送的持续时间为1ms,如果IR探测器的输出为低电平,其持续状态也不会超过1ms,因此发送完红外信号后必须立即将IR探测器的输出存储到变量中。这些存储的值会显示在串口调试终端或被巡航小车用于导航。#include<reg52.H>#include<delaytime.h>#include<uart51.h>intmain(void){intIRDetectLeft;uart_Init();printf("ProgramRunning!\n");while(1){IRDetectLeft=P1_2;printf("LeftIRDetected=%d\n",IRDetectLeft);delay_nms(100);}}通过上位机串口调试终端显示调试结果,如图8.16所示。IR探测器的OUT端可接单片机的任一I/O口,如将一个左侧IR探测器的输出端口接单片机的P1.2引脚,然后用整型变量IRDetectLeft存储连接到P1.2引脚的IR探测器的输出。IR探测器测试程序代码如下。
如果串口调试终端显示的不是预期值,则需要排查电路和程序问题。如果串口调试终端显示的总为0,可能是附近物体反射了红外线,需要调整IR探测器的角度;如果串口调试终端显示的总为1,偶尔为0,则可能是IR探测器受到了环境灯光的干扰。(2)超声波传感器HC-SR04。
超声波因其频率下限大于人的听觉上限而得名,是一种频率高于20000Hz的声波。它的方向性好,穿透能力强,易于获得较集中的声能,在水中传播的距离远,可用于测距、测速、清洗、焊接、碎石、杀菌消毒等,在医学、军事、工业、农业领域有很多的应用。
超声波发生器大体可以分为两类:一类采用电气方式产生超声波;另一类采用机械方式产生超声波。前者包括压电式超声波发生器、磁致伸缩式超声波发生器和电动式超声波发生器等,后者包括加尔统笛、液哨和气流旋笛等。它们所产生的超声波的频率、功率和声波特性各不相同,因而用途也各不相同,目前较为常用的是压电式超声波发生器。
HC-SR04模块可提供2~400cm的非接触式距离感测功能,测距精度可达3mm,工作电压为DC5V(部分型号支持3.3~5.5V宽电压),工作频率为40kHz,测量角度≤15°。引脚VCC接电源正极,GND接地,Trig为触发信号(持续时间大于10μs的高电平)输入端,Echo为回响信号输出端,其输出持续时间与检测距离成正比的高电平,HC-SR04模块的测距时序如图8.19所示。
压电式超声波发生器实际上是利用压电晶片的谐振来工作的。它有两个压电晶片和一个共振板,当它的两电极外加交变电压脉冲信号,且其频率等于压电晶片的固有振荡频率时,压电晶片将会发生共振,并带动共振板振动,产生超声波。压迫压电晶片振动,压电晶片的两个界面上产生交变电荷,交变电荷转换成电压经放大后送到测量电路,这时它就成为超声波接收器了。
超声波发生器向某一方向发射超声波,在发射超声波的同时开始计时,超声波在空气中传播,途中碰到障碍物就立即被反射回来,超声波接收器收到反射波就立即停止计时。根据时间差T和超声波的速度C(340m/s)可以估算出发射位置到障碍物所在位置的距离S,即S=C×T/2,这就是所谓的时间差测距法。
在本设计中,采用压电式超声波传感器HC-SR04模块(见图8.18)进行测距。while(Echo==0);TR1=1;//开始计时while(Echo);TR1=0;//停止计时t=TH1*256+TL1;TH1=0;TL1=0;distance=(t*0.034)/2;使用HC-SR04模块时需注意,测量周期建议大于60ms,以避免信号干扰;被测物体的面积需大于0.5m2且表面平整;被测距离小于2cm为盲区,即距离过近无法检测。
超声波传感器通过发射一组声音脉冲并记录下回响信号反射回来所需的时间来计算与物体的距离有多远。向Trig引脚输入持续时间大于10μs的高电平信号,启动测距,HC-SR04模块开始自动发送8个40kHz的脉冲,Echo引脚输出高电平,直至接收到反射声波为止,则Echo引脚高电平的持续时间就是超声波从发射到返回的时间。所以超声波测距就是测量Echo引脚高电平的时间,为了测量这个时间,需要在Echo引脚由低电平变为高电平时启动定时/计数器,然后等待反射声波。当接收到反射声波时,Echo引脚会由高电平变为低电平,此时关闭定时/计数器并计算定时/计数器的定时时间。测距参考代码如下。
8.4.4单片机巡航小车的硬件电路
单片机巡航小车的硬件电路中主要包括两个直流电动机及其驱动模块、电源稳压模块等。
LCD1602的数据线接入单片机的P0口,LCD1602的RS引脚接单片机的P3.5引脚,LCD1602的R/W引脚接单片机的P3.6引脚,LCD1602的E引脚接单片机的P3.7引脚。用于避障的IR探测器的信号输出端BZL接单片机的P2.7引脚,BZR接单片机的P2.6引脚;用于循迹的IR探测器的信号输出端XJL接单片机的P2.5引脚,XJR接单片机的P2.4引脚。超声波传感器的Trig引脚接单片机的P2.1引脚,Echo引脚接单片机的P2.0引脚。
由于电源采用的是总电压为7.4V的18650锂电池,因此需要用电源稳压模块7805(将7.4V降压到5V)和电源稳压模块7812(将7.4V升压到12V)分别对单片机和直流电动机供电。
直流电动机驱动模块L293D(图8.20中的L298)的IN1端和IN2端连接单片机的P1.5引脚和P1.4引脚,用于控制小车左轮的运动,同时通过单片机对使能端ENA的控制来调节左轮的速度。同理,IN3端和IN4端连接单片机的P1.3引脚和P1.2引脚,用于控制小车右轮的运动,同时通过单片机对使能端ENB的控制来调节右轮的速度。L293D的输出端OUT1和OUT2接小车的左侧电动机,输出端OUT3和OUT4接小车的右侧电动机。
8.4.5单片机巡航小车的软件设计1.主程序
当按键被按下之后,电源模块开始给巡航小车各部分供电,单片机程序开始运行,首先对单片机系统的各个端口进行初始化,之后HC-SR04模块开始测距,LCD1602显示距离,系统检测键值,巡航小车开启对应的运动模式,LCD1602实时显示巡航小车的运动状态。51单片机的P2.4~P2.7引脚连接IR探测器的信号输出端,具体如下。sbitBZL=P2^7;//避障IR探测器sbitBZR=P2^6;sbitXJL=P2^5;//循迹IR探测器sbitXJR=P2^4;
这里用sbit定义了特殊功能寄存器的位变量并赋值。其中,位变量BZL和BZR用于存储避障IR探测器的状态;位变量XJL和XJR用于存储循迹IR探测器的状态。循迹指的是IR探测器向下监测路况,探测“路线”,编写程序使单片机巡航小车跟随路线行驶。采用吸收红外光线的较粗的黑色绝缘带作为引导路线,即探测对象,黑色循迹路线图如图8.22所示。如果IR探测器没有检测到反射信号(输出信号为1),表示检测到黑色绝缘带。采用if-else语句,循迹程序控制逻辑如下。while(1){LCD_ShowString(1,1,"State:");if(XJL==0&&XJR==1){Right();LCD_ShowString(2,1,"Right");}if(XJL==1&&XJR==0){Left();LCD_ShowString(2,1,"Left");}if(XJL==0&&XJR==0){Forward();LCD_ShowString(2,1,"Forward");}if(XJL==1&&XJR==1){Forward();LCD_ShowString(2,1,"Forward");//左、右两边都检测到黑色绝缘带}}
//main.c#include<reg52.h>#include"motor.h"#include"ultrasonic.h"#include"Delay.h"#include"LCD1602.h"#include"Key.h"unsignedcharKeyNum,K;voidmain(){LCD_Init();Timer0_Init();US_Init();LCD_ShowString(1,1,"distance:");while(1){LCD_ShowNum(1,10,measure(),3);LCD_ShowString(1,13,"cm");LCD_ShowString(2,1,"Mode:");
注意:当左、右两侧循迹IR探测器XJL和XJR的值都是0时,表示并没有检测到黑色绝缘带,选择了前进的处理方式。但是,如果黑色绝缘带分段且段间有较大的间隔,就需要思考并设计一定的寻线控制策略。
为避免车头的左、右两侧与障碍物相撞,在放置避障IR探测器时可以分别向左、右两侧略微转一点角度,这样可以控制小车及时转向,同时可以通过调节IR探测器的灵敏度来控制小车转向时与障碍物之间的距离。如果IR探测器检测到反射信号,即输出信号为0,则表示检测到障碍物。
当两个IR探测器都检测到障碍物,小车会做出先停止后倒退,再转弯的运动控制处理。小车必须能察觉与运动目标之间距离的远近,远则加速,近则减速,因此需要有一个距离的阈值。跟随与避障使用同一探测信号,在程序控制逻辑上与避障正相反,而且当左、右两侧都检测不到物体时,小车会停止运动。
单片机巡航小车的主程序代码如下。KeyNum=Key();if(KeyNum==1){K++;K%=4;}LCD_ShowNum(2,6,K,1);if(K==1)//循迹{if(XJL==0&&XJR==1){Right();}if(XJL==1&&XJR==0){Left();}if(XJL==0&&XJR==0){Forward();}if(XJL==1&&XJR==1){Stop();}}if(K==2)//避障{if(BZL==0&&BZR==1){Right();}if(BZL==1&&BZR==0){Left();}if(BZL==0&&BZR==0){Stop();Delay(100);Back();Delay(500);Right();Delay(250);Forward();}if(BZL==1&&BZR==1){Forward();}}if(K==3)//跟随{if(BZL==0&&BZR==1){Left();}if(BZL==1&&BZR==0){Right();}if(BZL==0&&BZR==0){Forward();}if(BZL==1&&BZR==1){Stop();}}}}2.按键识别程序//Key.h#include<reg52.h>#include"Delay.h"unsignedcharKey(){unsignedcharKeyNumber=0;if(P3_2==0){Delay(20);while(P3_2==0);Delay(20);KeyNumber=1;}returnKeyNumber;}
本设计只使用了一个独立按键,机械开关的机械触点在接通和断开的瞬间会产生一个10ms左右的抖动,消除这个抖动只需要在按键被按下和断开时在程序中设置一个20ms左右的延时即可,这个操作称为软件消抖。按键识别程序的代码如下。
主程序所有功能的实现离不开按键识别、直流电动机驱动、液晶显示等模块程序,各模块子程序可以头文件的形式在主程序导入。
按键的键值为0~3,无按键被按下时返回值为0。按键每按下一次,键值加1,程序通过判断键值实现三种模式的切换。键值处理的相关代码如下。if(KeyNum==1){K++;K%=4;}3.运动控制程序voidPWM_Left()//左直流电动机的调速函数{PWML%=100;if(PWML<=Leftspeed){ENL=1;//左直流电动机使能}else{ENL=0;}}
当PWML≤Leftspeed(0≤Leftspeed≤100)时,使直流电动机使能引脚为1;当PWML>Leftspeed时,使直流电动机使能引脚为0,可见Leftspeed即占空比D。
对于单片机STC89C52来说,由于其内部没有PWM模块,所以使用其内部定时/计数器(如T0)来实现PWM调速。PWM调速函数的两个重要参数为周期T和占空比D,t为定时/计数器T0产生的基准延时100µs,n为T0溢出次数,则PWM信号的高电平时间为D×T=n×t。设计一个周期T为10ms(频率为10kHz)的PWM信号,T0基准延时为100µs。
以左直流电动机的调速函数为例,相关代码如下运动控制程序的代码如下。//motor.h#ifndef__MOTOR_H__#define__MOTOR_H__#include"Delay.h"sbitR1=P1^5;//右直流电动机控制引脚sbitR2=P1^4;sbitL1=P1^3;//左直流电动机控制引脚sbitL2=P1^2;sbitENR=P1^7;//右直流电动机使能引脚sbitENL=P1^6;//左直流电动机使能引脚#defineLeft_stopL1=0,L2=0#defineRight_stopR1=0,R2=0#defineLeft_goL1=1,L2=0#defineLeft_backL1=0,L2=1#defineRight_goR1=1,R2=0#defineRight_backR1=0,R2=1unsignedcharPWML=0;unsignedcharPWMR=0;unsignedcharLeftspeed=0;unsignedcharRightspeed=0;voidForward(){Rightspeed=50;//占空比数值仅供参考,以实际调试为准
Leftspeed=25;Right_go;Left_go;}voidBack(){Rightspeed=50;Leftspeed=25;Right_back;Left_back;}voidLeft(){Rightspeed=70;Leftspeed=15;Right_go;Left_go;}voidRight(){Rightspeed=20;Leftspeed=30;Right_go;Left_go;}voidStop(){Right_stop;Left_stop;}voidPWM_Left()//左直流电动机调速{PWML%=100;if(PWML<=Leftspeed){ENL=1;//运行中}else{ENL=0;}}voidPWM_Right()//右直流电动机调速{PWMR%=100;if(PWMR<=Rightspeed){ENR=1;}else{ENR=0;}}voidTimer0_Init(void){TMOD&=0xF0;//低4位清0,高4位不变TMOD|=0x01;//最低位置1,高4位不变TL0=0x9c;//ff9c是65436,相当于每100µs计数一次TH0=0xff;TF0=0;TR0=1;ET0=1;EA=1;PT0=0;}voidTimer0_Routine()interrupt1{TR0=0;TL0=0x9c;TH0=0xff;PWML++;PWMR++;PWM_Left();PWM_Right();TR0=1;}#endif4.超声波测距程序
//ultrasonic.hvoidTimer1_Init(void){TMOD&=0x0F;TMOD|=0x10;//工作模式1TL1=0;TH1=0;}voidUS_Init()//超声波传感器初始化函数{Echo=0;Trig=0;Timer1_Init();}voidUS_triggr()//超声波传感器触发函数{Trig=1;Delay20us();
Trig=0;}unsignedintmeasure()//测距{US_triggr();while(Echo==0);TR1=1;//开始计时while(Echo);TR1=0;//停止计时t=TH1*256+TL1;TH1=0;TL1=0;distance=(t*0.034)/2;returndistance;}
在Echo引脚由低电平变为高电平时启动定时/计数器,当有回波信号产生时,Echo引脚会由高电平变为低电平,此时关闭定时/计数器并获取该段时间t,将其代入公式s=(t×0.034)/2(cm),从而计算出距离s。超声波测距程序的代码如下。5.液晶显示程序
启动超声波传感器时,需要给Trig引脚发送至少10μs的高电平信号以触发测距,如果采用传统循环计数的软件方式进行延时,在实际调用过程中可能产生过长的延时。因为在函数调用时,CPU指令的操作是需要时间的(至少几微秒),而现在所要求的延时是微秒级,这就造成了延时的不精确性。为此,在触发函数US_triggr()调用的延时函数Delay20us()中使用了实际工程中广泛应用的空函数_nop_(void),该函数包含在头文件“INTRINS.H”中,如果晶振频率为12MHz,调用一次空函数能延时一个机器周期(1μs)。
单片机巡航小车除了需要在指定位置显示巡航模式、运动状态等字符信息,还要显示超声波传感器测得的距离值十进制数据信息,因此需调用LCD_ShowString()和LCD_ShowNum()函数。液晶显示程序的代码如下。//LCD1602.h#include<reg52.h>sbitLCD_RS=P3^5;sbitLCD_RW=P3^6;sbitLCD_E=
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2014年西藏中考英语真题及解析
- 2026年中考语文会考试题及答案
- 2026年物理前两章试题及答案
- 深度解析(2026)《GBT 29887-2013染色棉》:解码标准精髓前瞻产业未来
- 深度解析(2026)《GBT 29858-2013分子光谱多元校正定量分析通则》
- 《HG 2001-1991301-G30阻燃增强聚对苯二甲酸丁二醇酯(PBT)工程塑料》专题研究报告
- 《GBT 5269-2008传动与输送用双节距精密滚子链、附件和链轮》(2026年)合规红线与避坑实操手册
- 《DL/T 2604-2023高压并联电抗器现场局部放电试验装置通 用技术条件》(2026年)合规红线与避坑实操手册
- 2026年时间旅行科技开发合同协议
- 数学 如何甩掉粗心 小技巧
- 2026年合肥东部新中心建设投资有限公司招聘4名笔试模拟试题及答案解析
- 村卫生监督协管工作制度
- 2026年高考上海卷文综地理真题试卷+参考答案
- 2026年希望杯IHC六年级数学竞赛试卷(B卷)(含答案)
- 2026年广东深圳市高三一模高考英语试卷试题(答案详解)
- T-BECS 0008-2025 室外盲道规划设计标准
- 水电安装施工方案
- 【基于两级AO工艺的食品企业生产废水处理工程设计19000字】
- 2025年智能音箱市场预测可行性研究报告
- (2025版)骨质疏松性椎体骨折不愈合临床诊疗指南解读课件
- 2024年黑龙江辅警招聘考试真题完整参考答案详解
评论
0/150
提交评论