找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 49850|回复: 7
收起左侧

基于安卓手机蓝牙控制的智能小车设计论文,带源程序

  [复制链接]
ID:310862 发表于 2018-4-18 14:48 | 显示全部楼层 |阅读模式
一个基于安卓手机蓝牙控制的智能小车,带源程序哦。喜欢的可以下载来看下。

设计(论文)题目:
基于安卓手机蓝牙控制的智能小车设计

随着物联网的兴起,Android手机以其独有的开放性优势正在为我们提供更多优质便捷的技术成果。本课题研究的是基于安卓手机蓝牙控制的智能小车设计,基于手机平台,借助于蓝牙技术,设计和实现了一种无线遥控小车新的解决方案。设计以手机控制平台、蓝牙通讯模块、电机驱动模块等硬件模块组成的遥控小车。实现小车的前进、后退、前左转弯、前右转弯、后左转弯、后右转弯等实时控制功能。为遥控玩具小车的设计提出了一种新的思路,同时可以为将来智能家居的遥控设计提供一定的参考意义。
阐述一种通过手机蓝牙遥控小车行走的软、硬件设计。手机蓝牙作为客户端,小车上的蓝牙模块HC-06作为服务端。客户端采用Eclipse开发环境,JAVA编程,服务端采用单片机控制。双方通过串口进行通信,单片机驱动直流电机控制小车行动。实验结果表明,小车可以接收手机遥控信号并灵活地进行前行、倒退、左转、右转和停止等功能。
本文介绍了基于安卓手机的蓝牙智能小车控制要实现的功能,接着阐述该系统电路的设计及原理的说明,包括了方案的设计、重要元器件的介绍、电路设计的说明(包括单片机控制电路、电机驱动电路)安卓手机软件界面设计、软件设计流程以及系统的调试。最后总结了基于安卓的蓝牙智能小车控制设计完成的任务,分析系统出现的不足。

目  录

前  言 1
第一章 绪论2
  第一节 国内外研究现状2
  第二节 发展趋势分析4
第三节 本章小结4
第二章 设计方案分析5
  第一节 设计方案分析确定5
第二节 本章小结8
第三章   安卓操作系统概述 9
第一节 安卓操作系统发展历史及趋势  9
第二节 Android开发环境搭建 9
一、 Android的基本介绍 9
二、 Android系统构架10
三、 Android开发包及其工具的安装和配置11
第三节 本章小结13
第四章  系统硬件电路设计 14
第一节 单片机最小系统14
第二节 电机驱动模块17
第三节 蓝牙模块21
第四节 本章小结22
第五章  系统软件程序设计 23
  第一节 主程序设计23
第二节 手机端程序设计25
手机界面程序设计27
手机监听程序设计28
第三节 本章小结29
第六章  系统整体的调试31
  第一节  调试的方案31
第二节  硬件电路调试31
    一、 独立元件的检测31
    二、 单片机最小系统的调试33
三、 电源电路的测试34
    四、 驱动电路的调试34
第三节  软件调试37
  第四节  系统整体调试38
第五节  本章小结40
结    论 41
致    谢43
参考文献 44
附    录 46
  一、英文原文46
  二、英文翻译54
三、源程序60

前  言


遥控小车是玩具市场一种很常见的玩具,但是每个小车都有自己特定的遥控器,原装遥控器坏了很难与其它型号的进行匹配。现在手机使用十分普遍,如果利用手机这个平台,通过软件编程,可以很方便的在一个硬件平台实现多种小车的遥控器。蓝牙,是一种支持短距离通信的无线电技术。则可以通过手机蓝牙来控制我们的玩具小车[1、2]。
随着家用电器的越来越普及和人们生活节奏的加快,人们对电器的依赖性进一步提高,对电器的功能要求也进一步增大。现有每个普通家庭中的遥控器包括空调遥控器、电视遥控器、DVD遥控器、汽车遥控器、门窗遥控器等,门类繁多且不通用,而另一方面,手机已成为人人必备的工具,如果可以用我们必备的手机去遥控所有这些家用电器,可摆脱将来对专用红外遥控面板的依赖,一机在手,万物尽在掌握之中。因此,本论文先设计一种手机对智能遥控车的控制方案,利用本系统的控制模块可扩展至对所有家电的控制[2]。
Andriod是一个完全开放的标准平台,在2007年11月5日这天,谷歌公司正式向外界展示了这款名为Android的操作系统,并且在这天谷歌宣布建立一个全球性的联盟组织,该组织由34家手机制造商、软件开发商、电信运营商以及芯片制造商共同组成。这一联盟将支持谷歌发布的手机操作系统以及应用软件,将共同开发Android系统的开放源代码。本程序是基于Android 2.1系统,所用开发工具为Eclipse集成开发环境,Eclipse是著名的跨平台的自由集成开发环境(IDE)。最初主要用来Java语言开发,但是目前亦有人通过插件使其作为其他计算机语言比如C++、Python和Android的开发工具,在此开发环境下开发软件非常的方便。

章  绪论

第一节  国内外研究现状
一、国外研究现状
1984年,世界上第一幢智能建筑在美国康涅迪格州落成,这栋意义非凡的建筑只是对一座旧式大楼的一定程度的改造而完成的。它只是采用计算机系统对大楼的空调、电梯、照明等设备进行监控,并提供语音通信、电子邮件、情报资料等方面的信息服务。2000年,新加坡有近30个社区的约5000户家庭采用了这种家庭智能化系统,而美国的安装住户高达4万户。2003年,网络化家居的建设带来了高达4500亿美元的市场价值,这其中有3700亿美元是智能家电硬件产品的价值,剩余的部分则是软件和技术支持服务的费用。现在,国外的智能家居系统技术己日趋成熟,预计今年,50%以上的新房将具有一定的“智能型家居”功能。于此同时,由于技术的日益标准化,这些新型智能家居系统将比比尔.盖茨耗资6000万美元的高端别墅便宜得多。
在智能家居系统研发方面,美国及一些欧洲国家一直处于领先地位。近年来,以美国微软公司及摩托罗拉公司等为首的一批国外知名企业,先后挤身于智能家居的研发中。例如:微软公司开发的“梦幻之家”、摩托罗拉公司开发的“居所之门”、IBM公司开发的“家庭主任”等均已日趋成稳得技术强占家居市场。此外,日韩新等国的龙头企业纷纷致力于家居智能化的开发,对家居市场更是跃跃欲试。
目前市场上出现得智能家居控制系统主要有:
(1)X-10系统(美国),该系统是利用电力线作为网络平台,采用集中控制方式实现。这套系统的功能较为强大,与其它家居控制系统如ABB、C_BUS等比起来更容易接收,使用也相对简单。因为实现同样的功能,X-10家居控制系统是利用220v电力线将发射器发出的X-10信号传送给接收器从而实现智能化的控制,因此采用这套系统不需要额外的布线,这也是这套系统的最大的一个优势,因为其它系统基本上都需要布低压线,在墙上或地面开槽、钻孔,施工难度大、费用高、工期长。但由于缺乏在国内市场推广的条件且价格昂贵,该系统在国内应用极少。
(2)EIB系统(德国),该系统采用预埋总线及中央控制方式实现控制功能。但由于其工程要求复杂严苛,并且价格较高,因此一直无法打开国内市场[3]。
(3)8X系统(新加坡),该系统采用预处理总线跟集中控制方式来实现功能。它的优点在于利用的产品对系统进行扩展,系统较为成熟,比较适合中国国情。但是由于系统架构、灵活性及产品价格等方面还难以达到要求,所以目前在国内还较少应用。
二、国内研究现状
20世纪90年代后期,我国的智能小区日益兴起。众所周知,我国的智能化住宅建设最早起于上海、广州和深圳等沿海城市,并逐渐向内陆发展。在97香港回归之际,在建设部“97跨世纪住宅小区案竞赛活动”中,上海中皇广场被建设部科技委员会列为全国首家“智能住宅示范工程”,揭开了全国智能小区发展的序幕。1999年,建设部勘察设计司、建设部住宅产业化办公室联合组织实施全国住宅小区智能化技术示范工程,标志着我国住宅小区智能化进入了一个新阶段。随着信息化走进了千家万户,由国家经贸委牵头成立了家庭信息网络技术委员会,而信息网络技术体系研究及产品开发已经被列为了国家技术创新的重点专项计划。据建设部要求,截止今年,我国将有70%以上的家庭拥有Internet入网设备,大中城市中50%的住宅要实现智能化。
我国的智能家居相对于国外起步较晚, 尚未形成一定的国家标准。目前,主要采用国外的一些技术产品,但也有一些企业推出了自己的产品,主要有:
(1)e家庭(海尔),该系列产品以海尔电脑作为控制中心,各种网络家电作为终端设备,海尔移动电话作为移动数字控制中心。海尔在技术上同微软合作,利用微软的Windows Me技术和海尔的网络家电,使“e家庭”已具雏形,已推出了网络洗衣机、网络冰箱、网络空调、网络微波炉等一系列网络家电。
(2)e-home数字家园(清华同方),该智能家居控制系统是专门针对中国家庭设计的,遵循国际技术标准,采用嵌入式软、硬件技术,提供网络、网络节点及末端设备。产品以功能模块开发为主,基于国外成熟的智能家居标准之上。其智能家居控制系统主要有以下三个部分:
A系列:遵循EIB协议的家庭控制产品,适用于中高档住宅区。
B系列:遵循X-10协议的家庭控制产品,适用于中档住宅区。
易家三代:配电箱集中安装式家庭控制产品。
国内各大软、硬件机构正在积极的研制、开发更为符合市场的智能化家居设备,以解决当前智能化产品实用性差、使用复杂及产品价格昂贵等缺点,而技术创新性也逐步向国际先进水平靠拢,这样的未来值得期待[4]。


  • 发展趋势
智能家居的发展分为三个阶段:
首先是家庭电子化(Home Electronics)阶段,这个时期主要是面向单个的电器,家庭电器之间并没有形成网络,亦没有大的联系。
其次是住宅自动化(Home Automation)阶段,这个时期是面向功能的阶段,一部分的家庭电器之间形成了简单的网络,主要是为了实现某个特定单一的功能,例如单一的自动抄表功能。
最后是家居智能化(欧洲称为Smart Home,美国称为 Wise House)阶段,这个时期是面向系统设计的阶段,系统通过家庭分布总线把住宅内各种与信息相关的通信设备、家用电器、报警装置并到网络节点中进行集中的监控、管理,保持家电与环境的协调,提供生活、工作、学习以及娱乐的各种优质服务,营造一种温馨舒适的家庭氛围。
智能家居控制系统提供高效、舒适的家居环境,确保住户的生命财产安全;集中或远程调节家居环境的温度、湿度以及风的速度等,同时检查空气成分,提高空气质量;调节音响,电视等娱乐设施,愉悦心情;合理利用太阳能活周遭环境的变化,尽可能的节约能耗,达到合理利用资源;提供现代化的通信、信息服务。
节  本章小结
Internet和移动通信的迅速发展,使人们对各种数据和移动服务的需求快速增长。蓝牙技术作为一个全球开放性无线标准,通过把各种语言和数据设备用无线链路连接起来,使人们能够随时随地实现个人区域内语言和数据的交换与传输,随着技术的发展和完善,蓝牙必将对人们的生活和工作产生重大的影响。
章  设计方案分析
节  设计方案分析
  • 设计要求
本次设计要求实现一个手机可以远程通过蓝牙控制小车的前进、后退、左转和右转。要求学生对单片机和安卓手机开发有一定程度的理解,熟悉单片机定时器/计数器以及中断的使用,会基本的C语言和java,熟练掌握keil 51软件的使用与程序下载以及安卓手机软件开发环境。

  • 设计构思
通过查找资料进行方案论证和选择,可以确定出该系统的整体构成。本设计是以AT89C52单片机为核心,以设置手机界面来设置前进、后退、左转、右转、停止等功能。单片机控制电机驱动来控制电机的正反转以实现小车的前进、后退、左转、右转、停止。HC-06为蓝牙接收模块,通过与手机端的蓝牙进行连接配对,从而接收从手机端发送过来的动作指令。接收到的指令再传递给单片机,单片机通过分析传递过来的指令不同,而跳转到不同的子程序来控制电机驱动,从而实现小车的前进、后退、左转、右转、停止等不同的动作。电源提供给单片机5V直流电,L298需要从外部接两个电压,一个是给电机的,另一个给L298芯片的[5]。

、系统框图
通过查找资料进行方案论证和选择,可以确定出该系统的整体构成,本系统的系统框图如图2.1所示。
图2.1 系统框图

单片机的选择

单片机芯片选型时,总的原则是:
(1)芯片含有功能或数量略大于设计需求,设计需求尽可能用芯片完成,少用外围器件。
(2)技术性:要从单片机的技术指标角度,对单片机芯片进行选择,以保证单片机应用系统在一定的技术指标下可靠运行;
(3)实用性:要从单片机的供货渠道、信誉程序等角度,对单片机的生产厂家进行选择以保证单片机应用系统在能长期、可靠运行;
(4)可开发性:选用的单片机要有可靠的可以开发手段,如程序开发工具、仿真调试手段等。
单片机仅用于控制电机驱动,用51结构的有Atmel的AT89CXX系列、AT89SXX系列、AT89C20系列(20引脚)或STC的所有单片机都可以实现。根据在学校比较流行的学习单片机是AT89CXX系列,而且AT89C52单片机便宜,购买方便,故单片机选用AT89C52单片机[6]。

电机驱动的选择
底盘和最小系统确定好了后,小车还是跑不起来——缺少电机驱动。单片机的I/O是驱动不了电机的,因此我选用的是L298N电机专用驱动芯片。L298N通过单片机的I/O输入改变芯片控制端的电平,即可以对电机进行正反转,停止的操作,输入引脚与输出引脚的逻辑关系图如表2.1所示。

表2.1 L298N模块逻辑关系图

EnA

Ln1

Ln2

运转状态

0

X

X

停止

1

1

0

正传

1

0

1

反转

1

1

1

立停

1

0

0

停止


L298N电机驱动模块性能特点:
1、可实现电机正反转及调速。
2、启动性能好,启动转矩大。
3、工作电压可达到36V,4A。
4、可同时驱动两台直流电机。
5、适合应用于机器人设计及智能小车的设计[7]。
蓝牙模块的选择
本模块分主机和从机,主机能和从机配对通信,从机与从机之间或主机与主机之间不能通信,从机能和电脑、手机等的蓝牙配对通信,购买时默认为从机。我们在做智能小车控制时,蓝牙模块主要是实现接收从手机端发送过来的指令,所以我们需要的是从机模块。蓝牙串口在模块功能上,偶数命名的互相兼容,从机命名的也互相兼容,也就是说,HC-04与HC-06,HC-03与HC-05在功能上是兼容的。HC-04与HC-06是比较早的版本,用户不可以自己切换主机或者从机,AT指令集很少,包括修改蓝牙名(限于从机),修改密码,修改波特率,询问版本号等几个基本功能。在本次设计中我们只需实现简单的通信,因此选用HC-06模块。HC-06模块只记忆最后一次配对过的从机,并只与该从机配对,直到KEY(26脚)高电平触发时放弃记忆,26脚默认应该为低电平。
电源的选择
电源给单片机及电机驱动等使用5V直流电的器件提供电源,供系统正常工作。
方案一:使用开关电源将220V交流电转为5V直流电给系统供电。开关电源的体积小,重量轻。但由于需要耐压不小于220V的电容等特殊的元器件,日常生活中较难找全器件,开关电源的散热比较差,不适宜长时间工作。故此方案不适宜。
方案二:用变压器降压经整流桥整流和7805稳压后给系统供电。变压器相对比较重,但他的电路稳定,适宜长时间供电。能做到交流电供电正常时就能给系统正常供电。但在交流电失电时系统会停止工作,这时的时钟也会停止走时。在重新供电时系统会重启,从而造成原先设置的数据丢失。故此方案存在漏洞,不适宜使用。
方案三:使用交流电和干电池混合给系统供电。在交流电不失效的情况下由交流电转5V直流电供电,在交流电失效情况下由干电池供电。这样就能解决运行成本过高或者在交流电失效时丢失原先设置数据的问题。
方案四:使用干电池给系统供电。干电池供电能让系统稳定的工作,时钟的走时不受交流电的影响。干电池的价格相对交流电而言较贵,用干电池单独供电会造成使用成本提高的问题。但综合情况考虑到小车要前进、后退、左转、右转等问题,因此不可能采用交流电源来供电,最终决定两个电源都采用干电池供电比较合理,因此采用方案四提供电源。


节  本章小结
通过查找相关资料,首先确定要完成该设计需要到的硬件有单片机最小系统、蓝牙模块(只需实现接收数据,不用发送数据的从机模块HC-06)、电机驱动模块。通过分析该设计需要实现的功能,而选择适合的芯片型号及供电的方式。最后综合分析后绘制了该系统的硬件接线图。


章  安卓操作系统概述

第一节  安卓操作系统的发展历史及趋势
Android系统一开始并不是由谷歌研发出来的,Android系统原来的公司名字就叫做Android,谷歌公司在2005收购了这个仅成立22月的高科技企业。Android系统也开始由谷歌接手研发,Android系统的负责人以及Android公司的CEO安迪·鲁宾成为谷歌公司的工程部副总裁,继续负责Android项目的研发工作。在2007年11月5日这天,谷歌公司正式向外界展示了这款名为Android的操作系统,并且在这天谷歌宣布建立一个全球性的联盟组织,该组织由34家手机制造商、软件开发商、电信运营商以及芯片制造商共同组成。这一联盟将支持谷歌发布的手机操作系统以及应用软件,将共同开发Android系统的开放源代码[8]。

第二节Android开发环境搭建

  • Android的基本介绍
Android是一种基于Linux的自由及开放源代码的操作系统,主要使用于移动设备,如智能手机平板电脑,由Google公司和开放手机联盟领导及开发。尚未有统一中文名称,中国大陆地区较多人使用“安卓”或“安致”。Android操作系统最初由Andy Rubin开发,主要支持手机。2005年8月由Google收购注资。2007年11月,Google与84家硬件制造商、软件开发商及电信营运商组建开放手机联盟共同研发改良Android系统。随后Google以Apache开源许可证的授权方式,发布了Android的源代码。第一部Android智能手机发布于2008年10月。Android逐渐扩展到平板电脑及其他领域上,如电视数码相机游戏机等。2011年第一季度,Android在全球的市场份额首次超过塞班系统,跃居全球第一。 2012年11月数据显示,Android占据全球智能手机操作系统市场76%的份额,中国市场占有率为90%。其具有以下特点:
①开放性:在优势方面,Android平台首先就是其开发性,开发的平台允许任何移动终端厂商加入到Android联盟中来。显著的开放性可以使其拥有更多的开发者,随着用户和应用的日益丰富,一个崭新的平台也将很快走向成熟。开发性对于Android的发展而言,有利于积累人气,这里的人气包括消费者和厂商,而对于消费者来讲,最大的受益正是丰富的软件资源。开放的平台也会带来更大竞争,如此一来,消费者将可以用更低的价位购得心仪的手机。
②不受束缚:在过去很长的一段时间,特别是在欧美地区,手机应用往往受到运营商制约,使用什么功能接入什么网络,几乎都受到运营商的控制。自从2007年iPhone上市后,用户可以更加方便地连接网络,运营商的制约减少。随着EDGE、HSDPA这些2G至3G移动网络的逐步过渡和提升,手机随意接入网络已不是运营商口中的笑谈。
③丰富的硬件这一点还是与Android平台的开放性相关,由于Android的开放性,众多的厂商会推出千奇百怪,功能特色各具的多种产品。功能上的差异和特色,却不会影响到数据同步、甚至软件的兼容,如同从诺基亚Symbian风格手机一下改用苹果iPhone,同时还可将Symbian中优秀的软件带到iPhone上使用、联系人等资料更是可以方便地转移。
④方便开发:Android平台提供给第三方开发商一个十分宽泛、自由的环境,不会受到各种条条框框的阻扰,可想而知,会有多少新颖别致的软件会诞生。
⑤Google应用:在互联网的Google已经走过10年度历史,从搜索巨人到全面的互联网渗透,Google服务如地图、邮件、搜索等已经成为连接用户和互联网的重要纽带,而Android平台手机将无缝结合这些优秀的Google服务。

二、Android系统构架
Android的系统架构和其操作系统一样,采用了分层的架构。从架构图3.1看,Androi d分为四个层,从高层到低层分别是应用程序层、应用程序框架层、系统运行库层和Linux内核层[9]。
图3.1 Android结构图

1、应用程序
Android会同一系列核心应用程序包一起发布,该应用程序包包括客户端,SMS短消息程序,日历,地图,浏览器,联系人管理程序等。所有的应用程序都是使用JAVA语言编写的。
2应用程序框架
开发人员也可以完全访问核心应用程序所使用的API框架。该应用程序的架构设计简化了组件的重用,任何一个应用程序都可以发布它的功能块并且任何其它的应用程序都可以使用其所发布的功能块(不过得遵循框架的安全性)。同样,该应用程序重用机制也使用户可以方便的替换程序组件。
3系统运行库
Android 包含一些C/C++库,这些库能被Android系统中不同的组件使用。它们通过 Android 应用程序框架为开发者提供服务。
4系统内核
Android 是运行于Linux kernel之上,但并不是GNU/Linux。因为在一般GNU/Linux 里支持的功能,Android 大都没有支持,包括Cairo、X11、Alsa、FFmpeg、GTK、Pango及Glibc等都被移除掉了。Android又以Bionic 取代Glibc、以Skia 取代Cairo、再以opencore取代FFmpeg等等。
Android开发包及其工具的安装和配置
Android的开发是可以在windows XP及其以版本、MACOS、Linux等系统上进行开发的;首先呢,我们要进入Google的官方网站下载windows XP版本的java开发包JDK,我们选择的版本是JDK1.6.0以上的版本。在应用开发平台方面,我们采用的是eclipse,因为google提供了基于eclipse的android开发插件ADT,在随时更新的插件帮助下,可以很快帮助我们完成android手机终端的相关应用开发。
1安装JDK和配置java开发环境
首先,安装JDK时,安装包中有JDK和JRE两部分,点击安装程序,指定安装目录,然后点击下一步,等待安装完成即可。安装完成之后,点击“我的电脑”,选择“属性”里面的“高级”选项,选择环境变量,找到path变量,如果没有,就自己添加一个,按后命名path就行,完成之后,点击编辑,添加JDK安装目录的“lib”文件路径;之后点击确定,然后再找到CLASSPATH变量,在路径输入“.”,然后点击确定。
2检测安装
安装配置完成之后,需要测试是否安装成功。点击开始——运行输入“cmd”,打开命令模式。输入“java—version”,检测JDK安装是否成功,如果现实结果,则安装成功。
3安装eclipse
打开安装包,点击安装,弹出workspace对话框,确定创建项目的保存路径。
4SDK和ADT的安装和配置
首先,解压安装包,运行“SDK Setup.exe”。其次,在“Android SDK and Avd manager”的窗口左侧选择“setting”,选中“Force https://......”然后返回“Installed packges”,点击“Update all”。点击“Available Packges”,选择要安装的API版本以及USB驱动和SDK文档,我们都选择了。
这个过程很漫长,一定要保证网速快的情况下来安装,要不会出现安装不了的情况,最少安装这个也要一天的时间,所以要耐心等待。下载完成之后,选择所有选项,然后全部安装,安装完成之后,配置SDK,SDK的配置更JDK是一样的。
5ADT的安装和配置
启动eclipse,点击“Help”菜单,选择“Install New Software”之后,点击“Add”按钮,点击Archive指向下载的ADT压缩包,然后点击“ok”,选中所需要安装的插件即可。
6Android虚拟机的搭建
打开菜单“windows”,一次选择“Android SDK and AVD Manager”,打开界面;然后点击NEW新建模拟机,弹出选项卡,根据选项卡填写自己所需要的内容,即可创建。
7建立好项目名后,即可启动虚拟机


  本章小结

本章主要介绍了安卓系统的概述和安卓开发环境的一个搭建过程。Androi d分为四个层,从高层到低层分别是应用程序层、应用程序框架层、系统运行库层和Linux内核层。Android系统的主要优点有:开放性、不受束缚、丰富的硬件、方便开发、Google应用。在搭建安卓开发环境的时候,耗时相对比较漫长[10、11]。

  • 系统硬件电路设计

整个系统的硬件设计可以分为四个模块:电源电路、单片机最小系统、电机驱动模块、蓝牙模块、。电源电路为整个系统供电,包括单片机AT89C52、电机驱动、蓝牙模块、及其他外围电路。电源电路分两个部分:(1)接外部电源给电机供电;(2)由4节干电池作为电源,给系统供电,以确保单片机、电机驱动、蓝牙模块的正常运行。在电源电路给系统供电时,绿色指示灯点亮,只是当前供电正常。单片机最小系统部分是整个系统的智能控制部分,也是整个系统的核心部分。电机驱动模块L298需要从外部接两个电压,一个是给电机的,另一个给L298芯片的[12]。
节  单片机最小系统

单片机的最小系统就是让单片机能正常工作并发挥其功能时所必须的组成部分,也可理解为是用最少的元件组成的单片机可以工作的系统。对51 系列单片机来说, 最小系统一般应该包括: 单片机、时钟电路、复位电路、输入/ 输出设备等[13、14]。

图4.1 单片机最小系统框图

图4.2 单片机最小系统原理图

、单片机AT89C52
AT89S52单片机片内集成256字节程序运行空间、8K字节Flash存储空间,支持最大64K外部存储扩展。根据不同的运行速度和功耗的要求,时钟频率可以设置在0~33M之间。片内资源有4组I/O控制端口、3个定时器、8个中断、软件设置低能耗模式、看门狗和断电保护。可以在4V到5.5V宽电压范围内正常工作。不断发展的半导体工艺也让该单片机的功耗不断降低。同时,该单片机支持计算机并口下载,简单的数字芯片就可以制成下载线。根据不同场合的要求,这款单片机提供了多种封装,本次设计根据最小系统有时需要更换单片机的具体情况,使用双列直插DIP-40的封装。下面对定时开关系统中使用到的管脚进行简单说明.
P0口:P0口是一个8位漏极开路的双向I/O口。作为输出口,每位能驱动8个TTL逻辑电平。对P0端口写“1”时,引脚用作高阻抗输入。当访问外部程序和数据存储器时,P0口也被作为低8位地址/数据复用。在这种模式下,P0不具有内部上拉电阻。
P1口:P1口是一个具有内部上拉电阻的8位双向I/O口,P1输出缓冲器能驱动4个TTL逻辑电平。对P1 端口写“1”时,内部上拉电阻把端口拉高,此时可以作为输入口使用。作为输入使用时,被外部拉低的引脚由于内部电阻的原因,将输出电流(IIL)。
P2口:P2口是一个具有内部上拉电阻的8位双向I/O口,P2输出缓冲器能驱动4个TTL 逻辑电平。对P2 端口写“1”时,内部上拉电阻把端口拉高,此时可以作为输入口使用。作为输入使用时,被外部拉低的引脚由于内部电阻的原因,将输出电流(IIL)。
P3 口:P3口是一个具有内部上拉电阻的8位双向I/O口,P3输出缓冲器能驱动4个TTL逻辑电平。对P3端口写“1”时,内部上拉电阻把端口拉高,此时可以作为输入口使用。作为输入使用时,被外部拉低的引脚由于内部电阻的原因,将输出电流(IIL)。
RST——复位输入。当振荡器工作时,RST引脚出现两个机器周期以上高电平将是单片机复位。
. 时钟电路
在设计时钟电路之前,让我们先了解下51 单片机上的时钟管脚:
XTAL1(19 脚) :芯片内部振荡电路输入端。
XTAL2(18 脚) :芯片内部振荡电路输出端。
XTAL1 和XTAL2 是独立的输入和输出反相放大器,它们可以被配置为使用石英晶振的片内振荡器,或者是器件直接由外部时钟驱动。在XTAL1、XTAL2 的引脚上外接定时元件(一个石英晶体和两个电容),内部振荡器便能产生自激振荡。一般来说晶振可以在1.2 ~ 12MHz之间任选,甚至可以达到24MHz 或者更高,但是频率越高功耗也就越大。在本实验套件中采用的11.0592M 的石英晶振。和晶振并联的两个电容的大小对振荡频率有微小影响,可以起到频率微调作用。当采用石英晶振时,电容可以在20 ~ 40pF 之间选择(本实验套件使用30pF);当采用陶瓷谐振器件时,电容要适当地增大一些,在30 ~ 50pF 之间。通常选取33pF 的陶瓷电容就可以了。

. 复位电路
在单片机系统中,复位电路是非常关键的,当程序跑飞(运行不正常)或死机(停止运行)时,就需要进行复位。
MCS-5l 系列单片机的复位引脚RST( 第9 管脚) 出现2个机器周期以上的高电平时,单片机就执行复位操作。如果RST 持续为高电平,单片机就处于循环复位状态。
复位操作通常有两种基本形式:上电自动复位和开关复位。上电瞬间,电容两端电压不能突变,此时电容的负极和RESET 相连,电压全部加在了电阻上,RESET 的输入为高,芯片被复位。随之+5V电源给电容充电,电阻上的电压逐渐减小,最后约等于0,芯片正常工作。并联在电容的两端为复位按键,当复位按键没有被按下的时候电路实现上电复位,在芯片正常工作后,通过按下按键使RST管脚出现高电平达到手动复位的效果。一般来说,只要RST 管脚上保持10ms 以上的高电平,就能使单片机有效的复位。图中所示的复位电阻和电容为经典值,实际制作是可以用同一数量级的电阻和电容代替,读者也可自行计算RC 充电时间或在工作环境实际测量,以确保单片机的复位电路可靠。
. EA/VPP(31 脚) 的功能和接法
51 单片机的EA/VPP(31 脚) 是内部和外部程序存储器的选择管脚。当EA 保持高电平时,单片机访问内部程序存储器;当EA 保持低电平时,则不管是否有内部程序存储器,只访问外部存储器。对于现今的绝大部分单片机来说,其内部的程序存储器(一般为flash)容量都很大,因此基本上不需要外接程序存储器,而是直接使用内部的存储器。在本实验套件中,EA 管脚接到了VCC 上,只使用内部的程序存储器。这一点一定要注意,很多初学者常常将EA 管脚悬空,从而导致程序执行不正常[15]。


  • 电机驱动模块
  • L298N型驱动器的原理及应用
L298是SGS公司的产品,比较常见的是15脚Multiwatt封装的L298N,内部同样包含4通道逻辑驱动电路。可以方便的驱动两个直流电机,或一个两相步进电机。L298N芯片可以驱动两个二相电机,也可以驱动一个四相电机,输出电压最高可达50V,可以直接通过电源来调节输出电压;可以直接用单片机的IO口提供信号;而且电路简单,使用比较方便。L298N可接受标准TTL逻辑电平信号VSS,VSS可接4.5~7 V电压。4脚VS接电源电压,VS电压范围VIH为+2.5~46 V。输出电流可达2.5 A,可驱动电感性负载。1脚和15脚下管的发射极分别单独引出以便接入电流采样电阻,形成电流传感信号。L298可驱动2个电动机,OUT1,OUT2和OUT3,OUT4之间可分别接电动机,本实验装置我们选用驱动一台电动机。5,7,10,12脚接输入控制电平,控制电机的正反转。EnA,EnB接控制使能端,控制电机的停转。其引脚图如图4.3所示。

图4.3 L298N引脚图
1、引脚说明
1、1和15和8引脚直接接。,
2、4管脚VS接2.5到46的电压,它是用来驱动电机的。
3、9引脚是用来接4.5到7V的电压的,它是用来驱动L298芯片的,L298需要从外部接两个电压,一个是给电机的,另一个给L298芯片的。
4、6和11引脚是它的使能端,一个使能端控制一个电机,至于那个控制那个你自己焊接,你可以把它理解为总开关,只有当它们都是高电平的时候两个电机才有可能工作。
5、5,7,10,12是298的信号输入端和单片机的IO口相连,2,3,13,14是输出端,输入5和7控制输出2和3,  输入的10,12控制输出的13,14。
2、驱动原理图

L298N是SGS公司的产品,内部包含4个通道逻辑驱动电路,是一种二相和四相电机的专用驱动器,即内含二个H桥的高电压大电流双全桥式驱动器,接收标准TTL逻辑电平信号,可以驱动4V、2V以下的电机。

图4.4 L298驱动原理图

OUT1、OUT2和OUT3、OUT4之间分别接两个电机。IN1、IN2、IN3、IN4引脚从单片机输入控制电平,控制电机的正反转,ENA、ENB接控制使能端,控制电机的停转。L298N的逻辑功能如表4.1所示。

表4.1 L298逻辑功能表

IN1

IN2

IN3

IN4

左电机

右电机

电动车运动状态

1

0

1

0

正转

正转

前行

1

0

0

1

正转

反转

左转

1

0

1

1

正转

以电机为中心左转

0

1

1

0

反转

正转

右转

1

1

1

0

正转

以电机为中心右转

0

1

0

1

反转

反转

后退


3直流电机实物接线图

图4.5 直流电机实物接线图

4、直流电机原理图

图4.6 L298驱动直流电机原理图

  • 蓝牙模块
一、蓝牙模块HC-06介绍
1、 采用CSR主流蓝牙芯片,蓝牙V2.0协议标准
2、 核心串口模块工作电压3.3V。带底板的可以为3.1-6.5V之间
3、 波特率为1200,2400,4800,9600, 19200,38400,57600,115200用户可设置
4、 核心模块尺寸大小为:28mm x 15 mm x 2.35mm。底板尺寸27mm*47mm
5、 工作电流:配对中为50MA,配对完毕通信中为28MA
6、 休眠电流:不休眠
7、 用于GPS导航系统,水电煤气抄表系统,工业现场采控系统。
8、 可以与蓝牙笔记本电脑、电脑加蓝牙适配器、PDA等设备进行无缝连接
9、 出厂默认参数:从机,波特率:9600,N,8,1。配对密码:1234
二、AT命令集如下
1、测试通讯
发送:AT(返回OK,一秒左右发一次) 返回:OK
2、改蓝牙串口通讯波特率
发送:AT+BAUD1   返回:OK1200   发送:AT+BAUD2  返回:OK2400
1---------1200
2---------2400
3---------4800
4---------9600
5---------19200
6---------38400
7---------57600
8---------115200
9---------230400
A---------460800
B---------921600
C---------1382400
不建议用在超过115200的波特率,信号的干扰会使系统不稳定。
设置超过115200后用电脑无法使用,要用单片机编程于高于115200才能使用此波特率和重新发AT命令设低波特率
用AT命令设好波特率后,下次上电使用不需再设,可以掉电保存波特率。
3、改蓝牙名称
发送:AT+NAMEname
返回:OKname
参数name:所要设置的当前名称,即蓝牙被搜索到的名称。20个字符以内。例:发送AT+NAMEbill_gates
返回OKname
这时蓝牙名称改为bill_gates,参数可以掉电保存,只需修改一次。PDA端刷新服务可以看到更改后的蓝牙名称。
4、改蓝牙配对密码
发送:AT+PINxxxx
返回:OKsetpin
参数xxxx:所要设置的配对密码,4个字节,此命令可用于从机或主机。从机则是适配器或手机弹出要求输入配对密码窗口时,则手工输入此参数就可以连接从机。主机则是在用主蓝牙模块连数码相机时,数码相机是从机,找到相机的配对密码,再设入主蓝牙模块,则主蓝牙模块就可以自动连接相机。
例:发送AT+PIN8888
返回OKsetpin
这时蓝牙配对密码改为8888,模块在出厂时的默认配对密码是1234。参数可以掉电保存,只需修改一次。
第四节 本章小结
本章的任务主要介绍了各个模块的核心芯片,并完成了电路设计工作,本设计由51单片机最小系统、HC-06蓝牙模块、L298电机驱动模块、电源电路、小车底板等组成。然后确定设计硬件模块之间的电路连接图,为实物硬件制作做足准备。

章  系统软件程序设计


这次设计可以用C语言编程序,也可以用汇编语言编程序,由于本次设计中程序系统用C语言编写程序。此次设计所选用的单片机是AT89C52单片机,其C语言语法和结构和标准C语言基本相同,只是有了相应的扩充,用到的编译软件是Keil C。下面结合我的程序编译简要介绍以下Keil C的编译环境的特点。
Keil C51软件提供丰富的库函数和功能强大的集成开发调试工具,全Windows界面。另外重要的一点,只要看一下编译后生成的汇编代码,就能体会到Keil C51生成的目标代码效率非常之高,多数语句生成的汇编代码很紧凑,容易理解。在开发大型软件时更能体现高级语言的优势。Keil C51在使用前一定要先进行注册,否则程序过大会造成编译时出现地址使用错误。程序在编译时就遇到过这种问题。在单个程序运行时没有错误,但是一整合编译后出现地址冲突现象。这个问题困扰了很长一段时间,通过查资料发现若是Keil C51软件没有注册的话使用时当程序过大就会出现地址冲突现象。在注册完成后,程序编译能顺利通过[15]。

节  主程序的设计

在本次设计中,主程序主要是在单片机的控制下,对蓝牙模块输入的信息进行存储分析,来控制电机驱动,以达到控制小车的前进、后退、左转、右转。在这个过程中,单片机首先进行初始化,包括设置单片机各个端口的方向,各个变量的初始化,以及单片机振荡频率的校准等。单片机定时对蓝牙模块串口读数据,如果串口的数据读出,则对读出的数据进行分析,读出的数据如果为A、B、C、D则分别对应小车的前进、后退、左转、右转。小车硬件系统软件设计的流程图如图5.1所示。





图5.1 小车动作流程图

  • 手机程序的设计
本程序是基于Android 2.1系统,所用开发工具为Eclipse集成开发环境,Eclipse是著名的跨平台的自由集成开发环境(IDE)。最初主要用来Java语言开发,但是目前亦有人通过插件使其作为其他计算机语言比如C++、Python和Android的开发工具,在此开发环境下开发软件非常的方便。首先设计本系统手机端软件的程序界面,为了尽快实现程序的功能,本程序没有对软件界面设计做特别美化的设计,仅包含我们所用到的几个按钮和图形显示,以实现我们的功能为最大目标。
下面介绍Android相关资源文件的作用[16、17]:
1、assets 文件夹:此文件夹也可以存放资源文件,而且/assets目录下的资源文件不会在R.java自动生成ID,所以读取/assets目录下的文件必须指定文件的路径(url的路径为:)。除此之外,我们还可以通过AssetManager类来访问这些文件。打开文件时,会把apk文件当做zip文件进行解压读取。但是有文件大小有限制:不能超过1M(android2.2好像放宽(或者取消)了这个限制(至少可以存放>10M,具体没有测试。))。
2、res 文件夹:主要用来存放资源。此文件夹下可以创建子文件,常见的有:动画anim,图片drawable,颜色color,菜单menu, 布局layout,常量值values,详细如下:
(1)anim文件夹:后缀名为.xml。动画文件都放在这里。
(2)drawable文件夹: 用于存放图片资源,图片或者xml。图片格式,有png,9.png,jpg,gif都行。xml文件通常为自定义的形状shape或图片选择器类selector似的东西,就是不同状态下不同的图片,用于设置background的。 对分辨率笼统的分,可以分为高中低三种分辨率。
(3)color文件夹:用于存放color列表,和drawable的xml一样,表示不同状态下的不同颜色
(4)menu文件夹:菜单资源文件夹。
(5) layout文件夹:布局文件夹。此文件夹的名字也是可以起到屏幕适配的功能的。①横竖屏:layout-land|port;②分辨率:layout-1280x720
(6) values文件夹:存放常量值的文件夹。里面常见的xml文件为:
arrays.xml : 资源数组;colors.xml :  颜色值;dimens.xml : 像素值;
strings.xml :字符串值;tyles.xml : 样式值。此文件夹,也有屏幕适配作用。比如:dimens在不同分辨率下的值。同样的是加-1280x720这样的后缀。对于strings,有各种语言的版本对应。默认为英文。中文的文件夹名字应该是:values-zh-rCN,values-zh-rTW。
(7) raw文件夹:存放不需要系统编译成二进制的文件,例如字体文件等同assets文件夹类似。
(8) xml文件夹存放xml文件。
以下是手机端实现功能的程序流程图如图5.2所示。
图5.2 蓝牙通信流程图

  • 手机界面程序设计
在设置手机界面的时候,在Eclipse集成开发环境下,首先新建一个android项目工程,兴建路径是File—New—android project—project name  选择android 1.6版本,工程名命名为Bluetooth-car,选择Create Activity,则自动创建了一个Activity.在创建Activity时,需要注意一下四个要点:
1、一个Activity就是一个类,并且这个类要继承Activity。
2、需要复写Oncreate方法(当一个Activity第一次运行显示在手机上或者虚拟机上的时就会调用Oncreate方法)。
3、每一个Activity都需要在Androidmanifast.xml文件当中配置。
4、为Activity添加必要的控件。如图5.3所示,在制作蓝牙小车手机界面的时候,我用到了Textview 文本控件和 Butten按钮控件,并且在添加控件时采用相对布局形式[18、19]。
图5.3 手机界面图
两个Textview文本控件分别命名为:重庆邮电大学自动化学院和蓝牙控制系统,在layout布局文件下可以任意改变控件的位置、字体的大小、背景图片。改变背景图片的方法为:首先将需要用到的背景图片,分别拖入到drawable下,高中低分辨率都拖入一张,以便不同分辨率的手机识别,然后在layout布局文件下,打开Activity buletooth-car文件,调用添加安卓手机界面背景的语句为android:background="@drawable/background1" >,就能得到我们所修改的背景图片。
二、手机监听程序设计
在Eclipes开发平台上,首先在Layout文件中采用相对布局的形式设计完成手机界面以后,就要考虑为我们的每个Butten按键绑定监听程序,以实现在每个按键按下时,就能通过手机蓝牙发送相应的数据到小车蓝牙接收模块。首先在Layout文件中,每添加一个控件,都会为这个控件设置一个ID,(如android:id="@+id/button1"),然后在R.JAVA文件就会自动生成一个ID地址。然后在主程序里面编写监听程序,当按键按下的时候,通过监听按键的ID地址的不同,采用switch结构,跳转到不同的case里,向小车蓝牙模块发送不同的数据。在程序里直接写进小车蓝牙模块的蓝牙地址(00:12:10:31:01:70),当程序开始运行时,将会自动搜索该地址的蓝牙芯片,当进行过一次配对连接以后,将会记忆该地址,以后每次只要打开手机界面,开始运行时就会自动进行搜索配对连接好[20、21]。
* 按钮点击事件.
              * @param v
              */
              public void onClick(View v) {
                            switch (v.getId()) {
                            //转写按钮
                            case R.id.button1:
                                          message[0] = (byte) 0x41;                                         
                                          vibrator();
                                          Toast.makeText(this, "前进", Toast.LENGTH_LONG).show();
                                          bluesend(message);
                                          break;
                            //设置按钮
                            case R.id.button2:
                                          message[0] = (byte) 0x44;
                                          vibrator();
                                          Toast.makeText(this, "后退", Toast.LENGTH_LONG).show();
                                          bluesend(message);
                                          break;
                            case R.id.button3:
                                          message[0] = (byte) 0x43;
                                          vibrator();
                                          Toast.makeText(this, "左转", Toast.LENGTH_LONG).show();
                                          bluesend(message);
                                          break;
                            case R.id.button4:
                                          message[0] = (byte) 0x42;
                                          vibrator();
                                          Toast.makeText(this, "右转", Toast.LENGTH_LONG).show();
                                          bluesend(message);
                                          break;
                            case R.id.button5:
                                          message[0] = (byte) 0x61;
                                          vibrator();                                         
                                          Toast.makeText(this, "停止", Toast.LENGTH_LONG).show();
                                          bluesend(message);
                                          break;
                                         
                            default:
                                          break;
                            }
              }


第三节  本章小结

本章主要介绍本系统的软件设计,其中就包括单片机端的C语言程序设计和Android手机端的JAVA程序设计。由于我们在本科阶段都只接触过C语言,对JAVA语言从未涉及过,所以在做起来的时候遇到了很多的困难。首先对JAVA语言的开发环境Eclipes的使用不熟悉,对新接触语言的语法不熟悉。后来通过查找资料和对一些做好的工程例子的学习以后,有了对JAVA语言的大致的了解,就开始先学习着做简单的手机界面的程序。然后通过网上找到一些相关的程序进行修改以及在指导老师的指导和修改下,完成了手机端的软件设计。



章  系统整体调试


节  调试方案

根据电路原理图、实物 图把电路板实物做出来后,下一步就是电路板调试。电路板调试是最关键的一步,前面所做的电路设计的成功与否就是在调试步骤里体现的。本系统的调试主要分为硬件调试、软件调试和系统整体调试等三大部分。
经过初步对定时器的分析设计后,在制作硬件电路的同时,调试也在穿插进行。这样有利于问题的分析和解决,不会造成问题的积累,而且不会因为一个小问题而影响整体电路的检查,从而可以节约大量的调试时间。例如当单片机控制模块硬件部分制作好后,就可以先调试电机转动程序,通过电机驱动控制电机转动了,则结果正确了,说明电机驱动电路与单片机的连接电路是正确的,单片机能正常工作。软件编程中,首先完成单元功能模块的调试,然后进行系统的调试,调试的整体思想和步骤和硬件大同小异。系统的整体调试是最重要的一部分,虽然软硬件调试都通过了,但是通过蓝牙传输数据过程中可能会出现新的问题。


节  硬件电路调试

硬件单元电路制作好后,在上电之前,应该先用万用表对各个独立元件进行检查,在排除了虚焊、短路、断路等问题后再通电进行电路功能的调试。具体调试过程如下所述:
一、独立元件的检测
任何组装好的电子电路,在通电调试之前,必须认真检查电路连线是否有误。检查的方法是对照电路图,按一定的顺序逐级对应检查,例如:对电路板的电阻阻值进行确定,可以通过读取电阻上的色环进行确认。特别是注意电源是否接错,电源与地是否有短接,集成电路和晶体管的引脚是否接错,轻轻拨一拨元器件,观察焊点是否牢固等。用万用表检测是不是有短路和断路现象。
给系统上电后,看下电源(绿色)灯亮不亮。假如不亮,就要检查电源指示灯发光二极管的好坏。还要用万用表测一下单片机等芯片的电压是不是符合要求。假如不是,就要进行各个芯片的检查,看一下各个芯片的引脚有没有焊好,芯片是否损坏。

图6.1 驱动模块反面图


图6.2 蓝牙模块正反面图


图6.3 蓝牙模块调试图

二、单片机最小系统的调试
单片机AT89C52最小系统的检测分为硬件调试及软件调试。量电源电压有没有到位,量复位RSL脚电平对不对,如果是高电平复位那么平时应该是低电平,量外部晶振有没有起振,最小系统电路参考芯片PDF文档,确认正确。
硬件调试时用万用表测量单片机的工作电压及各个管脚的电压是否达到正常工作电压。在此检测中还要烧入程序对各个I/O口的输出进行测试,查看I/O口所输出的电压是否与程序所控制值一致。例如:编写一个调试程序,使的所有I/O口从P1.0口开始依次赋予低电平,用万用表测量其输出电压,确定是否与程序所付值一致,一致则证明正确;然后又对其依次赋予高电平,确定是否与程序所付值一致,一致则证明正确。两次测试都正确,证明单片机最小系统是正常工作的。



图6.4 单片机调试图
电源电路的调试
电源电路作为整个系统的供电电路,其输出电压必须在单片机的正常工作电压范围(4V到5.5V之间)内。在电源通电之前,一定要检查电路是否接错,特别是极性电容是否有接反,防止出现极性电容接反而造成爆电容的现象。在确保器件接法无误的情况下,接通电源,并用万用表测量输出电压,得到其电压为5.3V,符合系统的正常工作电压要求。然后再在电机驱动输出端接上干电池, 实现两个电源供电。
四、驱动模块的调试

驱动模块为驱动电机的芯片,L298需要从外部接两个电压,一个是给电机的,另一个给L298芯片的。首先检查驱动芯片与单片机的各个连线是否都正确以后,给芯片通上电源,单片机指示灯点亮以后。运行单片机上的程序,通过单片机P2口的数据变化来控制L298的IN1、IN2、IN3、IN4的电平的高低。L298输入端的高低电平的变化,通过输入端的LED灯的亮灭来显示。当运行前进程序的时候,IN1、IN2、IN3、IN4的值为1、0、1、0,分别点亮LED1和LED3,左右电机都正转,实现小车前进;运行左转程序的时候,IN1、IN2、IN3、IN4分别为1、0、0、1,分别点亮LED1、LED4,左电机正转,右电机反转,实现小车左转;运行右转程序的时候,IN1、IN2、IN3、IN4的值为0、1、1、0,点亮LED2,LED3,左电机反转,右电机正转,实现小车右转;运行后退程序的时候,IN1、IN2、IN3、IN4的值分别为0、1、0、1,分别点亮LED2、LED4,左右电机都反转,实现小车后退。通过调试电机驱动模块能实现基本的功能。其调试图如图6.5,图6.6,图6.7,图6.8所示。



图6.5 小车前进指示图



图6.6 小车后退指示图

图6.7 小车左转指示图




图6.8 小车右转指示图


节  软件调试
C语言的调试
软件的调试包括程序本身语法的调试和在电路板上功能的调试两种。在编程过程中,为了得到满足要求的用户程序,一般都需要有一个对程序的调试过程,甚至需要经过多次反复的调试才能完成。在调试程序前为了调试方便,避免程序出错时将单片机拆来拆去的麻烦,在电路板上做了一个下载口,可以将下载线直接插到电路板上进行调试,这样就可以一边进行调试,一边修改程序。程序用Keil C软件写好后,先用该软件的编译功能编译一下所写的程序,检查程序是有语法错误或其他的错误。如果有错误则根据提示进行分析将错误改过来直至编译成功为止。当完成了语法调试后,再根据定时开关插座设计的功能要求修改程序完成系统的各个功能。在编写程序的时候一定要根据系统实现的功能和连接方式,认真分析,画出系统主程序、时钟程序、设置程序的流程图,并根据画出的流程图一步一步的去写出程序。
根据系统的特点,软件系统应该按模块进行调试,当各个模块调试通过后再将各个模块整合起来,进行综合调试,直到得到预期结果。
与纯粹的C语言编程不同的是,单片机编程要考虑到硬件的设计,所有程序的编写都是根据硬件资源进行。

二.JAVA语言的调试

将做好的工程添加进入Eclipes开发环境中,检查各个文件夹下面的程序有没有出现打红色X的问题以及警告,点开下方的problem的文件,检查该工程有没有出现问题,当排除了所有的问题以后。配置一个2.2版本的模拟器,然后启动模拟器,在模拟器上运行该工程,在模拟器上将会出现已经做好的手机界面,运行完成,调试成功。然后将手机连接到电脑上,打开安卓手机的USB接口。接下来点击运行整个工程项目,在手机上出现前面那个做好的蓝牙小车控制界面。点击各个按钮,都无问题,证明该JAVA程序没有问题[22]。

图6.9 手机端程序运行图


节  系统整体的调试

蓝牙控制小车的硬件模块和软件模块分别调试通过后,接下来就可以进行系统的整体测试。首先检查各个模块之间,以及电机驱动与电机的连接都没有出错的情况下,打开给各个模块提供的5V电源以及打开给电机提供的另一个6V电源。此时最小系统模块指示灯点亮,表示单片机供电正常,蓝牙模块指示灯开始闪烁,表示蓝牙模块也供电正常。此时打开安卓手机的蓝牙,搜索该蓝牙芯片,进行配对。然后打开我们做好的手机界面,当界面打开之后,开始自动搜索蓝牙芯片的地址进行连接,当蓝牙芯片的指示灯有闪烁转变为常亮以后,表示蓝牙配对连接成功。在刚开始的时候调试的时候遇到了一些问题,在电机驱动方面,当在手机端的界面上点击前进、后退、左转、右转按钮的时候,蓝牙模块能接受手机端发送的字符A、B、C、D的ASCII码值,并且能够通过串口相应的传递给单片机,单片机通过分析串口传过来的数据,改变P2口的值分别为65、66、67、68,来控制电机驱动的输入端IN1、IN2、IN3、IN4。相应的电机驱动端的四个指示LED灯都能根据数据的变化采取不同的量灭组合情况,来相应控制小车的前进、后退、左转、右转[23、24、25]。

图6.10 小车底板正面图




图6.11 小车底板反面图



图6.12 小车实体图


节  本章小结

在调试的过程中也遇到一些问题,就是最开始电机驱动输出端控制的电机却不会转动。通过分析,可能有两个原因导致电机不会转动,其一,电机驱动的输出端的接线出现了错误,导致电机转动出现问题;其二,电机驱动端接的给电机供电的电压达不到驱动电机的最低电压,最后通过查询资料和用万用表测驱动模块的输出端的各个引脚的高低电平,发现输出端的电平也能随输入端的改变而变化,当最后测试VCC和GND两端,发现无明显的压降,再用万用表的测电阻值测两端的阻值,发现问题是电机驱动模块输出端的供电端VCC与GND端短路,导致外接电源不能给电机供电。最后我通过直接从芯片的引脚接线到电源端,则电机能够正常转动。





结  论


本次毕业设计是一个基于单片机AT89C52的智能小车控制,包括方案选择、软硬件设计、单片机最小系统、电机驱动电路和蓝牙电路、硬件测试结果及解决在电路调试时遇到的问题。在此期间主要完成的工作包括以下几个方面:
(1)设计初期收集电机驱动、单片机等相关资料,对智能小车的实现原理有比较清晰的了解。
(2)确定系统框图,对电源模块、单片机最小系统模块、蓝牙电路模块和电机及其驱动电路模块等的实施方案进行比较,确定最终的智能小车控制的设计方案。
(3)根据智能小车控制的原理图制作出电路连接图。
(4)根据系统要实现前进、后退、左转、右转等功能编写出小车端的软件程序。
(5)在eclipes开发环境下,应用JAVA程序编写手机界面程序,并且通过模拟器来检测手机界面程序。
(6)软硬件调试通过后进行整体调试,并查找该系统存在的缺陷,进行完善。
(7)最终小车能够实现前进、后退、左转、右转等功能,达到老师给出的基本要求。
本次设计完成了基于安卓手机的智能小车控制系统。该系统采用51单片机AT89C52编程控制电机的正反转来实现小车前进、后退、左转、右转,而电机的正反转则由电机驱动L298N输出端的逻辑电平来控制。
从整个设计的过程来看前期的充分的准备显得非常的重要,经过前期充分的准备,和对嵌入式系统开发的学习,避免了很多在后续的设计中可能出现的问题。
MCU端的软硬件设计因为与所学知识相关性较大,所以出现的问题较少,MCU底板设计时鉴于电路简单,且易于焊接,故未采用PCB制版也相应的节约了成本。特别值得一提的是为了提高系统在硬件上的安全性和稳定性,我特别添加了硬件保护装置,以提高系统的硬件防碰撞的能力。
主要的问题出现在android端的软件设计上,由于对android开发环境的不熟悉,缺乏一些在编写JAVA程序时的一些技巧性问题,所以刚刚开始时总是出现很多问题,并且出现的问题都需要查找相关资料才能解决。通过学习一些android相关的学习视频,最后对android环境有了一个系统的了解在开发的过程中也得心应手些。
Android端图形界面的设计也是一大难点,基于Java的图形界面设计不论是从设计平台还是Java语言的掌握都是一想挑战,但幸于Java软件的开发技术已经成熟,且可查阅的资料多且详尽,所以图形界面的设计达到设计时的五项按键要求,功能实现良好,除界面的友好程度可以更加优化外,其余完成任务。
总体来看,我进行了比较充分的准备,在实践过程中通过查阅相关资料和咨询有关人员,克服了系统设计过程中的绝大多数困难,基本都以达到设计要求,并通过了软件测试。

致  谢


毕业设计完成了,在这个过程中我学到了很多东西。首先我要感谢我的导师罗萍老师,他在我完成论文的过程中,给予了我很大的帮助。在论文开始的初期,我对于论文的结构以及文献选取等方面都有很多问题,是在老师的帮助下进行修改和完善的。本毕业设计是在罗萍老师悉心的关怀与指导下完成,在此对老师献上最衷心地感谢。罗萍老师从毕业设计一开始就对我们严格要求,每周的周一都会和我们开见面会,询问我们的毕设进度并了解我们遇到的困难,积极协助我们解决设计过程中的各种难题,并要求我们每天记录在毕业设计中所作的工作进度及遇到的问题,让我们去发现问题,解决问题。在我遇到难已解决的问题心中急躁时,罗萍老师总是及时的给予鼓励,使我能够有勇敢的克服困难,把毕设继续进行下去。罗萍老师对学生的高度关注和对工作高度负责的精神值得我们尊敬,也是我今后走向工作岗位的榜样。通过本次毕业设计,我不仅是对我们所学知识的一个汇总,同时也是考验我们学习能力和动手能力的一个平台;让我们能学到更多的相关知识,更重要的是学到了面对困难的不放弃、不气馁的态度,不骄不躁的办事风格,奋发向上的精神,这些在我今后的生活和学习中都是一笔宝贵的财富。
最后,我要再次感谢在毕业设计过程中对我提供过制作电路板等工具的同学和老师,以及在毕业设计中对我进行过指导的所有老师和同学。

附  


一、英文原文
Application Fundamentals
Android applications are written in the Java programming language. The compiled Java code — along with any data and resource files required by the application — is bundled by the aapt tool into an Android package, an archive file marked by an .apk suffix. This file is the vehicle for distributing the application and installing it on mobile devices; it's the file users download to their devices. All the code in a single .apk file is considered to be one application.
In many ways, each Android application lives in its own world:
1. By default, every application runs in its own Linux process. Android starts the process when any of the application's code needs to be executed, and shuts down the process when it's no longer needed and system resources are required by other applications.
2. Each process has its own virtual machine (VM), so application code runs in isolation from the code of all other applications.
3. By default, each application is assigned a unique Linux user ID. Permissions are set so that the application's files are visible only to that user and only to the application itself — although there are ways to export them to other applications as well.
It's possible to arrange for two applications to share the same user ID, in which case they will be able to see each other's files. To conserve system resources, applications with the same ID can also arrange to run in the same Linux process, sharing the same VM.
Application Components
A central feature of Android is that one application can make use of elements of other applications (provided those applications permit it). For example, if your application needs to display a scrolling list of images and another application has developed a suitable scroller and made it available to others, you can call upon that scroller to do the work, rather than develop your own. Your application doesn't incorporate the code of the other application or link to it. Rather, it simply starts up that piece of the other application when the need arises.
For this to work, the system must be able to start an application process when any part of it is needed, and instantiate the Java objects for that part. Therefore, unlike applications on most other systems, Android applications don't have a single entry point for everything in the application (no main() function, for example). Rather, they have essential components that the system can instantiate and run as needed. There are four types of components:
Activities
An activity presents a visual user interface for one focused endeavor the user can undertake. For example, an activity might present a list of menu items users can choose from or it might display photographs along with their captions. A text messaging application might have one activity that shows a list of contacts to send messages to, a second activity to write the message to the chosen contact, and other activities to review old messages or change settings. Though they work together to form a cohesive user interface, each activity is independent of the others. Each one is implemented as a subclass of the Activity base class.
An application might consist of just one activity or, like the text messaging application just mentioned, it may contain several. What the activities are, and how many there are depends, of course, on the application and its design. Typically, one of the activities is marked as the first one that should be presented to the user when the application is launched. Moving from one activity to another is accomplished by having the current activity start the next one.
Each activity is given a default window to draw in. Typically, the window fills the screen, but it might be smaller than the screen and float on top of other windows. An activity can also make use of additional windows — for example, a pop-up dialog that calls for a user response in the midst of the activity, or a window that presents users with vital information when they select a particular item on-screen.
The visual content of the window is provided by a hierarchy of views — objects derived from the base View class. Each view controls a particular rectangular space within the window. Parent views contain and organize the layout of their children. Leaf views (those at the bottom of the hierarchy) draw in the rectangles they control and respond to user actions directed at that space. Thus, views are where the activity's interaction with the user takes place.
For example, a view might display a small image and initiate an action when the user taps that image. Android has a number of ready-made views that you can use — including buttons, text fields, scroll bars, menu items, check boxes, and more.
A view hierarchy is placed within an activity's window by the Activity.setContentView() method. The content view is the View object at the root of the hierarchy. (See the separate User Interface document for more information on views and the hierarchy.)
Services
A service doesn't have a visual user interface, but rather runs in the background for an indefinite period of time. For example, a service might play background music as the user attends to other matters, or it might fetch data over the network or calculate something and provide the result to activities that need it. Each service extends the Service base class.
A prime example is a media player playing songs from a play list. The player application would probably have one or more activities that allow the user to choose songs and start playing them. However, the music playback itself would not be handled by an activity because users will expect the music to keep playing even after they leave the player and begin something different. To keep the music going, the media player activity could start a service to run in the background. The system would then keep the music playback service running even after the activity that started it leaves the screen.
It's possible to connect to (bind to) an ongoing service (and start the service if it's not already running). While connected, you can communicate with the service through an interface that the service exposes. For the music service, this interface might allow users to pause, rewind, stop, and restart the playback.
Like activities and the other components, services run in the main thread of the application process. So that they won't block other components or the user interface, they often spawn another thread for time-consuming tasks (like music playback). See Processes and Threads, later.
Broadcast receivers
A broadcast receiver is a component that does nothing but receive and react to broadcast announcements. Many broadcasts originate in system code — for example, announcements that the timezone has changed, that the battery is low, that a picture has been taken, or that the user changed a language preference. Applications can also initiate broadcasts — for example, to let other applications know that some data has been downloaded to the device and is available for them to use.
An application can have any number of broadcast receivers to respond to any announcements it considers important. All receivers extend the BroadcastReceiver base class.
Broadcast receivers do not display a user interface. However, they may start an activity in response to the information they receive, or they may use the Notification Manager to alert the user. Notifications can get the user's attention in various ways — flashing the backlight, vibrating the device, playing a sound, and so on. They typically place a persistent icon in the status bar, which users can open to get the message.
Content providers
A content provider makes a specific set of the application's data available to other applications. The data can be stored in the file system, in an SQLite database, or in any other manner that makes sense. The content provider extends the Content Provider base class to implement a standard set of methods that enable other applications to retrieve and store data of the type it controls. However, applications do not call these methods directly. Rather they use a Content Resolver object and call its methods instead. A Content Resolver can talk to any content provider; it cooperates with the provider to manage any interprocess communication that's involved.
See the separate Content Providers document for more information on using content providers.
Whenever there's a request that should be handled by a particular component, Android makes sure that the application process of the component is running, starting it if necessary, and that an appropriate instance of the component is available, creating the instance if necessary.
Activating components: intents
Content providers are activated when they're targeted by a request from a Content Resolver. The other three components — activities, services, and broadcast receivers — are activated by asynchronous messages called intents. An intent is an Intent object that holds the content of the message. For activities and services, it names the action being requested and specifies the URI of the data to act on, among other things. For example, it might convey a request for an activity to present an image to the user or let the user edit some text. For broadcast receivers, the
Intent object names the action being announced. For example, it might announce to interested parties that the camera button has been pressed.
There are separate methods for activating each type of component:
1. An activity is launched (or given something new to do) by passing an Intent object to
Context.start Activity() or Activity .start Activity For Result(). The responding activity can look at the initial intent that caused it to be launched by calling its getIntent() method. Android calls the activity's  on New Intent() method to pass it any subsequent intents. One activity often starts the next one. If it expects a result back from the activity it's starting, it calls  start Activity For Result() instead of  start Activity(). For example, if it starts an activity that lets the user pick a photo, it might expect to be returned the chosen photo. The result is returned in an Intent object that's passed to the calling activity's on Activity Result() method.
2. A service is started (or new instructions are given to an ongoing service) by passing an Intent object to Context. Start Service(). Android calls the service's onStart() method and passes it the Intent object. Similarly, an intent can be passed to Context. Bind Service() to establish an ongoing connection between the calling component and a target service. The service receives the Intent object in an on Bind() call. (If the service is not already running, bind Service() can optionally start it.) For example, an activity might establish a connection with the music playback service mentioned earlier so that it can provide the user with the means (a user interface) for controlling the playback. The activity would call bind Service() to set up that connection, and then call methods defined by the service to affect the playback.
A later section, Remote procedure calls, has more details about binding to a service.
3. An application can initiate a broadcast by passing an Intent object to methods like Context. Send Broadcast(), Context. Send Ordered Broadcast(), and Context. Send Sticky Broadcast() in any of their variations.
Android delivers the intent to all interested broadcast receivers by calling their on Receive() methods. For more on intent messages, see the separate article, Intents and Intent Filters.
Shutting down components
A content provider is active only while it's responding to a request from a Content Resolver. And a broadcast receiver is active only while it's responding to a broadcast message. So there's no need to explicitly shut down these components.
Activities, on the other hand, provide the user interface. They're in a long-running conversation with the user and may remain active, even when idle, as long as the conversation continues. Similarly, services may also remain running for a long time. So Android has methods to shut down activities and services in an orderly way:
1. An activity can be shut down by calling its finish() method. One activity can shut down another activity (one it started with start Activity For Result()) by calling finish Activity().
2. A service can be stopped by calling its stop Self() method, or by calling Context .stop Service().
Components might also be shut down by the system when they are no longer being used or when Android must reclaim memory for more active components. A later section, Component Lifecycles, discusses this possibility and its ramifications in more detail.
The manifest file
Before Android can start an application component, it must learn that the component exists. Therefore, applications declare their components in a manifest file that's bundled into the Android package, the .apk file that also holds the application's code, files, and resources.
The manifest is a structured XML file and is always named AndroidManifest.xml for all applications. It does a number of things in addition to declaring the application's components, such as naming any libraries the application needs to be linked against (besides the default Android library) and identifying any permissions the application expects to be granted.
But the principal task of the manifest is to inform Android about the application's components. For example, an activity might be declared as follows:
The name attribute of the <activity> element names the Activity subclass that implements the activity. The icon and label attributes point to resource files containing an icon and label that can be displayed to users to represent the activity.
The other components are declared in a similar way — <service> elements for services, <receiver> elements for broadcast receivers, and <provider> elements for content providers. Activities, services, and content providers that are not declared in the manifest are not visible to the system and are consequently never run. However, broadcast receivers can either be declared in the manifest, or they can be created dynamically in code (as BroadcastReceiver objects) and registered with the system by calling Context.registerReceiver().
For more on how to structure a manifest file for your application, see The Android Manifest.xml File.
Intent filters
An Intent object can explicitly name a target component. If it does, Android finds that component (based on the declarations in the manifest file) and activates it. But if a target is not explicitly named, Android must locate the best component to respond to the intent. It does so by comparing the Intent object to the intent filtersof potential targets. A component's intent filters inform Android of the kinds of intents the component is able to handle. Like other essential information about the component, they're declared in the manifest file. Here's an extension of the previous example that adds two intent filters to the activity:
The first filter in the example — the combination of the action "android.intent.action.MAIN" and the category
"android.intent.category.LAUNCHER" — is a common one. It marks the activity as one that should be represented in the application launcher, the screen listing applications users can launch on the device. In other words, the activity is the entry point for the application, the initial one users would see when they choose the application in the launcher.
The second filter declares an action that the activity can perform on a particular type of data.
A component can have any number of intent filters, each one declaring a different set of capabilities. If it doesn't have any filters, it can be activated only by intents that explicitly name the component as the target.
For a broadcast receiver that's created and registered in code, the intent filter is instantiated directly as an IntentFilter object. All other filters are set up in the manifest.
For more on intent filters, see a separate document, Intents and Intent Filters.


  • 英文翻译
应用程序基础Android Developers
Android应用程序使用Java编程语言开发。aapt工具把编译后的Java代码连同应用程序所需的其他数据和资源文件一起打包到一个Android包文件中,这个文件使用.apk作为扩展名。此文件是分发并安装应用程序到移动设备的载体;是用户下载到他们的设备的文件。单一.apk文件中的所有代码被认为是一个应用程序。
从多个角度来看,每个Android应用程序都存在于它自己的世界之中:
   1 默认情况下,每个应用程序均运行于它自己的Linux进程中。当应用程序中的任何代码需要被执行时,Android启动此进程,而当不再需要此进程并且其它应用程序又请求系统资源时,则关闭这个进程。
 2 每个进程都有其独有的虚拟机(VM),所以应用程序代码与所有其它应用程序代码是隔离运行的。
   3 默认情况下,每个应用程序均被赋予一个唯一的Linux用户ID,并加以权限设置,使得应用程序的文件仅对此用户及此应用程序可见——尽管也有其它的方法使得这些文件同样能为其他应用程序所访问。
1 应用程序组件
Android的一个核心特性就是一个应用程序可以使用其它应用程序的元素(如果那个应用程序允许的话)。例如,如果你的应用程序需要显示一个图片卷动列表,而另一个应用程序已经开发了一个合用的而又允许别的应用程序使用的话,你可以直接调用那个卷动列表来完成工作,而不用自己再开发一个。你的应用程序并没有吸纳或链接其它应用程序的代码。它只是在有需求的时候启动了其它应用程序的那个功能部分。
为达到这个目的,系统必须能够在一个应用程序的任何一部分被需要时启动一个此应用程序的进程,并将那个部分的Java对象实例化。因此,不像其它大多数系统上的应用程序,Android应用程序并没有为应用程序提供一个单独的入口点(比如说,没有main()函数),而是为系统提供了可以实例化和运行所需的必备组件。一共有四种组件类型:
1 Activity
activity是为用户操作而展示的可视化用户界面。例如,一个activity可以展示一个菜单项列表供用户选择,戒者显示一些包含说明文字的照片。一个短消息应用程序可以包括一个用于显示要发送消息到的联系人列表的activity,一个给选定的联系人写短信的activity以及翻阅以前的短信或改变设置的其他activity。尽管它们一起组成了一个内聚的用户界面,但其中每个activity都不其它的保持独立。每一个都实现为以Activity类为基类的子类。
一个应用程序可以只有一个activity,戒者,如刚才提到的短信应用程序那样,包含很多个。每个activity的作用,以及有多少个activity,当然是取决于应用程序及其设计的。一般情况下,总有一个应用程序被标记为用户在应用程序启动的时候第一个看到的。从一个activity转向另一个靠的是用当前的activity启动下一个。
每个activity都被给予一个默认的窗口以进行绘制。一般情况下,这个窗口是满屏的,但它也可以是一个小的位于其它窗口之上的浮动窗口。一个activity也可以使用附加窗口——例如,一个在activity运行过程中弹出的供用户响应的对话框,戒是一个当用户选择了屏幕上特定项目后显示的必要信息的窗口。
窗口显示的可视内容是由一系列层次化view构成的,这些view均继承自 View 基类。每个view均控制着窗口中一块特定的矩形区域。父级view包含并组织其子view的布局。叶节点view(位于层次结构最底端)在它们控制的矩形区域中进行绘制,并对用户直达其区域的操作做出响应。因此,view是activity与用户进行交互的界面。例如,view可以显示一个小图片,并在用户指点它的时候产生动作。Android有一些预置的view供开发者使用——包括按钮、文本域、滚动条、菜单项、复选框等等。
view层次结构是由Activity.setContentView() 方法放入activity的窗口之中的。content view是位于层次结构根位置的View对象。(参见独立的用户界面文档以获取关于view及层次结构的更多信息。)
2 Service
service没有可视化的用户界面,而是在一段时间内在后台运行。例如,一个service可以在用户做其它事情的时候在后台播放背景音乐、从网络上获取数据或者计算一些东西并提供给需要这个运算结果的activity使用。每个service都继承自Service基类。
一个媒体播放器播放播放列表中的曲目是一个不错的例子。播放器应用程序可能有一个或多个activity来给用户选择歌曲并进行播放。然而,音乐播放这个任务本身丌应该由任何activity来处理,因为用户期望即使在他们离开播放器应用程序而开始做别的事情时,音乐仍在继续播放。为达到这个目的,媒体播放器activity可以启动一个运行于后台的service。系统将在这个activity不再显示于屏幕乀后,仍维持音乐播放service的运行。
连接至(绑定到)一个正在运行的service(如果service没有运行,则启动之)是可能的。连接之后,你可以通过那个service暴露出来的接口不service进行通讯。对于音乐service来说,这个接口可以允许用户暂停、回退、停止以及重新开始播放。
如同activity和其它组件一样,service运行于应用程序进程的主线程内。所以它不会对其它组件或用户界面有任何妨碍,它们一般会派生一个新线程来执行一些时间消耗型任务(比如音乐回放)。参见稍后的进程和线程。
3 Broadcast receiver
broadcast receiver是一个与注于接收广播通知信息,并做出相应处理的组件。许多广播是由系统代码产生的——例如,通知时区改变、电池电量低、拍摄了一张照片或者用户改变了语言选项。应用程序也可以发起广播——例如,通知其它应用程序一些数据已经下载到设备上并处于可用状态。
一个应用程序可以拥有任意数量的broadcast receiver,以对所有它认为重要的通知信息予以响应。所有的receiver均继承自BroadcastReceiver基类。
broadcast receiver没有用户界面。然而,它们可以启动一个activity来响应它们收到的信息,或者也可以使用NotificationManager来通知用户。通知可以用多种方式来吸引用户的注意力──闪动背光灯、震动设备、播放声音等等。通知一般是在状态栏上放一个持丽的图标,用户可以打开它并获取消息。
4 Content provider
content provider将一些特定的应用程序数据供给其它应用程序使用。数据可以存储于文件系统、SQLite数据库或其它有意丿的方式。content provider继承于ContentProvider 基类,实现了一套使得其他应用程序能够检索和存储它所管理的类型数据的标准方法。然而,应用程序并不直接调用返些方法,而是使用一个 ContentResolver 对象,调用它的方法作为替代。ContentResolver可以与任何content provider进行会话;与其合作对任何相关的进程间通讯进行管理。
参阅独立的Content Providers文档以获得更多关于使用content provider的信息。
每当出现一个需要被特定组件处理的请求时,Android会确保那个组件的应用程序进程处于运行状态,必要时会启动它,并确保那个组件的一个合适的实例可用,必要时会创建那个实例。
1.1激活组件:intent
当接收到ContentResolver发出的请求后,content provider被激活。而其它三种组件——activity、service和broadcast receiver,被一种叫做intent的异步消息所激活。intent是一个保存着消息内容的Intent对象。对于activity和service来说,它指明了所请求的操作名称,并指定了用来操作的数据的URI和其它一些信息。例如,它可以承载一个对一个activity的请求,让它为用户显示一张图片,或者让用户编辑一些文本。而对于broadcast receiver来说,Intent对象指明了所通报的操作。例如,它可以对所有感兴趣的对象通报照相按钮被按下。
对于每种组件来说,激活的方法是不同的: 通过传递一IntentContext.startActivity()Activity.startActivityForResult(以启动(或指定新工作给)一个activity。相应的activity可以通过调用自身的 getIntent() 方法来查看最刜激活它的intent。Android通过调用activity的onNewIntent()方法来传递给它随后的任何intent。
  一个activity经常启动另一个activity。如果它期望它所启动的那个activity迒回一个结果,它会调用startActivityForResult()而不是startActivity()。例如,如果它启动了另外一个activity以使用户挑选一张照片,它也许想知道哪张照片被选中了。其结果将会被封装在一个Intent对象中,并传递给发出调用的activity的onActivityResult() 方法。
2 通过传递一个Intent对象至Context.startService()以启动一个service(或向正在运行的service给出一个新的指令)。Android调用此service的onStart()方法并将Intent对象传递给它。
与此类似,一个intent可以被传递给 Context.bindService()以建立一个处于调用组件和目标service乀间的活动连接。此service会通过onBind() 方法的调用来获取此Intent对象(如果此service尚未运行,bindService()会先启动它)。例如,一个activity可以建立一个不前述的音乐回放service的连接,这样它就可以提供给用户一些途径(用户界面)来控制回放。这个activity可以调用 bindService()来建立此连接,然后调用service中定之的方法来控制回放。
稍后的远程方法调用一节有关于如何绑定至一个service的更多细节。
3 应用程序可以通过传递一个Intent对象至 Context.sendBroadcast() ,Context. sendOrderedBroadcast(), 以及Context.sendStickyBroadcast()和其它类似方法来发起一个广播。Android会调用所有对此广播有兴趣的broadcast receiver的 onReceive()方法,将此intent传递给它们。
1.2 关闭组件
content provider仅在响应来自ContentResolver的请求时处于活动状态。而broadcast receiver仅在响应一条广播信息的时候处于活动状态。所以没有必要去显式地关闭返些组件。
而activity则不同,它提供了用户界面。只要会话依然持续,无论会话过程有无空闲,activity同用户进行长时间会话且可能一直处于活动状态。与此相似,service也会在很长一段时间内保持运行。所以Android为关闭activity和service提供了一系列有序的方法。
activity可以通过调用自身的finish()方法来关闭。一个activity可以通过调用finishActivity()方法来关闭另外一个activity(它用startActivityForResult()启动的)。
service可以通过调用自身的stopSelf()方法,或调用 Context.stopService()来停止。
系统也会在组件不再被使用的时候戒者当Android必须为更多的活动组件回收内存时关闭它。稍后的组件的生命周期一节,将对返种可能性及结果进行更详细的认论。
1.3 manifest文件
当Android启动一个应用程序组件之前,它必须知道那个组件是存在的。因此,应用程序会在一个被打包到Android包中的manifest文件中声明它的组件,.apk文件还将涵括应用程序的代码、文件以及其它资源。
manifest文件是一个结构化的XML文件,而且对于所有应用程序,文件名总是AndroidManifest.xml。除了声明此应用程序各个组件,它会做很多其他工作,比如指明应用程序所需链接到的库的名称(除了默认的Android库乀外)以及标出应用程序期望获得的各种权限。
但manifest文件最重要的任务是向Android报告此应用程序的各个组件。丼例说明,一个activity可能声明如下:
<activity>元素的name属性指定了实现此activity的 Activity子类。icon和label属性指向包含展示给用户的此activity的图标和标签的资源文件。
其它组件也以类似的方法声明——<service> 元素用于声明service, <receiver> 元素用于声明broadcast receiver,而 <provider> 元素用于声明content provider。未在manifest文件中进行声明的activity、service以及content provider将不为系统所见,从而也就永不会被运行。然而,broadcast receiver既可以在manifest文件中声明,也可以在代码中动态创建(为BroadcastReceiver对象),并以调用Context.registerReceiver()的方式注册至系统。
1.4 Intent过滤器
一个Intent对象可以显式地指定一个目标组件。如果进行了返种指定,Android会找到这个组件(基于manifest文件中的声明)并激活它。但如果intent没有显式地指定一个目标,Android就必须找到最合适的组件来响应此intent。这个过程是通过比较Intent对象和所有潜在目标的intent过滤器完成的。组件的intent过滤器会通知Android它所能处理的intent类型。如同组件的其它必要信息一样,这些intent过滤器是在manifest文件中进行声明的。返里有一个对先前例子的扩展,其中加入了针对activity的两个intent过滤器:
示例中的第一个过滤器——action“android.intent.action.MAIN”和category“android.intent.category.LAUNCHER”的组合——是常见的一个。它标明了此activity应该在应用程序启动器中显示,就是用户在屏幕上看到的此设备上可供启动的应用程序的列表。换句话说,这个activity是应用程序的入口点,是用户在启动器中选择运行这个应用程序后所见到的第一个activity。
第二个过滤器声明了此activity在一种特定类型的数据上可以执行的操作。
一个组件可以拥有任意数量的intent过滤器,每个都声明了一套不同的功能。如果组件没有包含任何过滤器,它只能被显式地指明作为目标组件的intent激活。
对于在代码中创建并注册的broadcast receiver来说,intent过滤器将被直接实例化IntentFilter为对象。其它所有的过滤器都在manifest文件中设置。

四、源程序

(一)单片机程序

单片机源程序如下:


  1. #include<reg52.h>
  2. #define uchar unsigned char
  3. #define uint unsigned int
  4. uchar a;

  5. void init()
  6.    {
  7.      TMOD=0X20;   //设置定时器1为方式2
  8.      TH1=0xfd ;   
  9.      TL1=0xfd ;   //装初值
  10.      TR1=1;       //启动定时器1
  11.      REN=1;       // 使能接收

  12.      SM0=0;
  13.      SM1=1;       //设置串口为工作方式1

  14.      EA=1;       // 打开总中断开关
  15.      ES=1;       // 打开串口中断开关
  16.    }
  17.             
  18.     void main()
  19.     {
  20.         init();
  21.               while(1);
  22.      }

  23.    void ser() interrupt 4
  24.                  {
  25.                  ES=0;
  26.            RI=0;   //将接受中断标志位清0;
  27.                                     
  28.                  a=SBUF; //将接受到的数据赋值给a
  29.                                    
  30.         switch(a)
  31.     {
  32.       case 65:  P2=0X17;  break;   //  发送的是A  前进指令
  33.       case 66:  P2=0X1B;  break;   //  发送的是B  右转指令
  34.       case 67:  P2=0X27;  break;   //  发送的是C  左转指令
  35. ……………………

  36. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei提供下载:

基于安卓手机蓝牙控制的智能小车设计.doc (5.65 MB, 下载次数: 138)

回复

使用道具 举报

ID:404522 发表于 2019-1-23 23:12 | 显示全部楼层
写的太好了,谢谢分享
回复

使用道具 举报

ID:250717 发表于 2019-3-28 16:38 | 显示全部楼层
写的太好了,谢谢分享
回复

使用道具 举报

ID:531672 发表于 2019-5-9 16:03 | 显示全部楼层
写的太好了,谢谢分享
回复

使用道具 举报

ID:465853 发表于 2019-5-11 22:13 | 显示全部楼层

写的太好了,谢谢分享
回复

使用道具 举报

ID:372154 发表于 2019-5-31 14:53 | 显示全部楼层


写的太好了,谢谢分享
回复

使用道具 举报

ID:663813 发表于 2019-12-14 15:49 | 显示全部楼层
您好,请问有源代码吗?  能发一份吗?1539733963@qq.com  谢谢!
回复

使用道具 举报

ID:683229 发表于 2020-1-7 21:26 | 显示全部楼层
写的太好了,谢谢分享
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表