单片机+ISD1760智能家用语音唤醒系统设计

在节奏过快的生活中,人们承受的精神和心理压力十分巨大,这就使得现代人都希望在当代繁忙而枯燥的工作和学习中能身心愉悦的生活。随着信息化发展水平的逐步提高,智能化系统越来越受到人们的重视。市场上普遍的闹钟只是一种到了人们设定的时间就被令人烦躁的声音而吵醒的机械化闹钟,机械化的闹钟不仅将熟睡的人们从梦中惊醒,影响了人们起床的心情,还影响了人们的身体健康。因此,人性化的唤醒系统显得尤为重要,它以多种方式联动,可对光线亮度、语音提示和人体感应等诸多唤醒元素进行个性化调整或设定,尽可能将对人的刺激减低到最低限度,让睡眠中人在设定的时间里自然醒来[1]。
目前,市场上越来越多小型普遍的电子产品的功能不断地被更替,这一现状由于智能化电子产品的出现, 毋庸置疑闹钟就是一个典型代表。普通的响铃闹钟设计缺乏的是人性化关怀这一理念,比如人们还在熟睡中就会被刺耳的闹铃叫醒,这种唤醒方式不仅会使人感到厌烦、浑身不舒服,更重要的是会影响人们的身体健康,因此,人性化的智能唤醒系统显得相当不可忽视。近年来,智能系统的研究已经带领社会进入了更为人性化的领域,这一现状引起了国内外学者及企业的广泛重视。国内,浙江大学提出了一种人性化控制的智能家居若干关键技术研究;中国信息界提出的一款智能闹钟,每天早上能够温柔的唤醒熟睡中的人们;另外,杭州电子科技大学、吉林大学、山东大学等众多学者也进行了智能唤醒系统的相关研究。其研究成果填补了国内在相关领域的多项空白,为人性化的智能家居设计提供了新的思路和技术支持,在很大程度上推动了国内智能化系统的发展进步[2]。国外有一款地毯闹钟Reggie,这款闹钟功能是在唤醒时倘若不站上去,那么它就会一直响直到将人们唤醒,如此就解决了起床困难户的问题;Baboomi智能闹钟,这款智能化的设计既有为闹钟充电的功能,在一定程度上又有震动的功能。临睡前在枕头下放置智能闹钟的震动设备,早上熟睡的人就会被它人性化地震动声音而慢慢唤醒,这种传达起床信息的方式更加智能化;倘若在智能手机上安装智能闹钟的App,也可以实现智能化的语音闹钟,通过设置起床时间,在早上就能感受到舒适地被唤醒。
针对目前功能比较大众化的闹钟设计中存在的人性化关怀不够,以及没有充分考虑到消费者的使用体验等问题[3-5],本设计做出了进一步的改进,主要体现在在唤醒系统的视觉、听觉等方面。家用智能唤醒系统,可根据人们预先设定的起床时间,慢慢调整周围的光照闹钟响起唤醒熟睡中的人们,同时,以温柔的语音提示当天的室外温度来提醒人们穿衣厚度指数等。本系统不仅能满足普通人的唤醒需求,也能满足老年人以及有耳疾的残疾人的唤醒需求。
2系统的设计方案
一款智能家用唤醒系统必须具备基本的电子时钟功能,这可以根据不同的需求设定不同的操作从而实现不同的功能。智能闹钟在设定的起床时间还没到达之前,自动调光灯由暗变亮,闹钟开始响铃,并进入语音提醒模式,和普通闹钟相比较有很大的创新。如果人们还未从熟睡中醒来,那么闹钟就会持续响起直至手动关闭闹钟。本智能家用唤醒系统核心硬件是以STC89C51单片机为主控芯片,根据主控芯片的外围接口这一特点,在外围加以其他硬件电路,然后根据单片机的指令设计要求,在编译软件中采用C语言设计程序,并通过执行一定的程序来实现此系统的功能。系统设计主要由单片机最小系统、温度检测、实时时钟模块、PWM波调光、具有语音提醒功能的闹钟模块、显示和按键模块等几个部分组成。STC89C51单片机最小系统作为主控模块,时间、日期信息的采集由DS1302时钟芯片来完成,温度的获取用DS18B20温度传感器来实现,时间和温度等的显示主要是在LCD12864液晶显示器中完成的;通过按键完成日期、时间的初始化设置和闹钟的设定;借助PWM波的变化实现唤醒灯自动调光;采用语音模块完成闹钟唤醒和温度提醒功能。家用智能唤醒系统设计原理框图如图1所示。


图1系统原理框图
3系统的硬件设计
根据系统的设计方案,系统的原理图设计如图2所示。总体原理图以单片机STC89C51为核心的控制电路[6],外围辅以时钟电路、温度传感器电路、PWM唤醒灯电路、液晶显示电路及语音播报电路等。通过按键设置闹钟,单片机将温度传感器和实时时钟传来的信息处理后送到液晶显示器显示,在设定的时间提前一段时间单片机控制唤醒灯打开,语音模块与单片机进行通信协议,从而实现各个功能。

图2 系统原理图
3.1控制模块的设计
主控制模块以基于STC89C51单片机为核心,这是智能家用唤醒系统设计的最重要的部分,一个能够正常工作的单片机系统是在核心芯片上加入一些外围电路组成的。最小系统和按键控制电路是控制模块设计中的两个主要部分,控制模块负责整体电路的主要工作,通过操作按键和单片机控制电路的运行。
晶振电路和复位电路是单片机最小系统必不可少的部分[7]。单片机正常工作时的工作速度是由晶振电路提供的,这种工作速度是由晶振电路产生的脉冲信号。在理论上,STC89C51单片机的最小系统本应使用的是和系统相配的晶振,然而在本系统中选取的是比较接近的12MHz晶振。由于单片机内部结构的特殊性,因此,只需要一个晶振和两个电容连接在单片机外面的电路中就可实现时钟电路,电容一般选用的是30pF的容量就可以满足要求,图中C1和C2电容的作用就是为了使单片机能够迅速的起振,并且能够使单片机工作时的频率达到稳定。晶振的一端接XTAL2(19),另一端接的是XTAL2(18),两个电容并联接于振荡源之间,工作时能更好的为单片机服务。智能家用唤醒系统的各个部件在处于初始化状态时,单片机可由此开始工作进行操作,这一系列是复位电路提供的条件,复位电路是单片机的准备工作,包括上电复位和按键复位两种模式。在按键复位中,电容C3取值一般为10uF,电阻R取值约为10KΩ,K5是为实现按键复位而设置的。然而,在上电复位中,由单片机运行后给定的高低电平直接实现复位功能。
按键控制电路中,设置了五个按键实现设计所需的要求,按键在设计中能够起到控制外部电路的作用,不同的操作实现不同的功能。本设计中使用的按键不多,仅需五个按键系统所需要的功能即可完成。按键有四个接脚,两个相连的之间导通,按键其中一端接单片机的I/O接口,另一端可以接电源,也可以接地端,此系统中按键另一端是接地的,低电平完成按键的操作,这样的接法程序是比较简单且系统也相对稳定。五个独立按键实现的功能分别有确认返回、加一、减一、闹钟开关及唤醒灯开关,按键K1、K2、K3、K4和K5分别与单片机的P1.0、P1.1、P1.2、P1.3和P1.4引脚连接,控制模块电路图如图3所示。


图3 控制模块电路图
3.2时钟模块的设计
实时时钟电路的设计是本次设计的基本模块,在数字时钟所具备的功能下才能实现闹钟的设定。时钟模块的设计需要采用时钟芯片DS1302,这款芯片可以精确的计数,具有农历和阳历转换的功能,可以编程接口,与此同时还具有掉电保存等功能,在编写程序时能够对其比较方便的进行程序控制[8]。与直接使用单片机内部定时器实现计数功能相比,DS1302时钟芯片实现的功能很便捷,程序简单易编写,稳定性好、容易控制、时间精度高等。由于单片机内部定时器虽然没有使用芯片,但是实现的时间误差较大,不能满足系统要求。所以系统完成时钟电路的首选芯片就是DS1302时钟芯片。
DS1302时钟芯片与单片机进行通信时,仅需要SCLK、I/O和RST三条线连接的方式,可以实现以一对多的方式传送多个字节的时钟信号或数据。DS1302比同类的芯片性能好,功耗低能更好的为系统的运行减少不必要的负荷。时钟模块有两个电源,在Vcc2 不能正常运行时,时钟依然能在Vcc1的作用下维持原来的状态继续运行。若两个电源大小不一,则使用其中较大的一个电源为电路供电,Vcc1采用3V的纽扣电池,Vcc2主电源使用的是整个系统的电源。DS1302时钟芯片需要使用32.768KHz的晶振,晶振电路可产生计时脉冲。为了对所传送的数据进行初始化,DS1302工作时复位脚就需要被置为高电平,反之,数据的传送就会被停止导致数据不能继续传输。
在本系统的设计中,实时时钟电路主要是为了能够准确的显示电子时钟等信息。通过与单片机连接,将用软件实现功能,然后经过显示器显示需要的时间信息。DS1302时钟芯片与单片机的通信接口由3条线组成,VCC接在系统电源上,GND接在地端, RST复位管脚与单片机的P2.2端口连接,实现了时钟电路在复位时由低电平跳变成高电平并启动一次数据传输的过程,SCLK管脚与P2.1端口连接,时钟输入端将记录的脉冲信号存入时钟芯片,I/O管脚与P2.0端口连接,数据线输入输出记录的时间数据。根据电路的需求,可在三线上加上拉电阻,由于P2口内部的缘故,本系统连接的单片机P2接口也可不加电阻。DS1302时钟电路在设计中的原理图如图4所示。


图4 时钟电路原理图
3.3温度检测模块的设计
为了使测得温度值更加精确,DS18B20温度传感器的高精度性能就成了温度检测模块选取的标准。这款传感器属于数字式传感器,而且在进行数据的传送时仅仅一条数据线就可以实现,最重要的一点是它与单片机连接的时候显得更加简单方便,也鉴于此类传感器的结构简单易懂,不需外围的电路辅助完成所需的功能。若采用热敏电阻和A/D转换器实现温度采集,就需选用标准稳定的电阻才可完成设计要求,并且检测的数值可靠性较差。在经过比较论证后,选用DS18B20能更好的满足设计需求,它的分辨率比起同类型的传感器更高更精确,所以温度检测模块选用了DS18B20型号的传感器。
DS18B20温度检测模块在设计中用于采集温度,早晨人们在经过闹钟唤醒后通过语音系统提醒当前的温度。温度模块采集温度值后,经过与单片机通信将所检测的示数传送到显示器显示,最后由ISD1760语音模块播报温度值。DS18B20与单片机的通信只需将DS18B20的信号线I/O口与单片机的其中一个双向端口I/O口相连即可。在焊接时必须注意将电源端VDD和地端GND焊接牢固[9],如果VDD没有接好,那么传感器就只会传送一个固定不变的温度值,就不能检测当前的温度。在设计中,传感器须与本设计选用的主机STC89C51单片机连接,其中U3为温度检测控制芯片DS18B20。I/O(2)管脚与单片机的P3.7端口连接可以传输信号,温度模块电路图如图5所示。


图5 DS18B20温度检测电路原理图
3.4语音模块的设计
本设计使用的ISD1760是一款语音录放功能强大的语音芯片。与其他语音芯片相比较,ISD1760不仅实现了较为方便的录放音,还具备了一些较智能的提示功能,在一定程度上音质也有了很大的改善。ISD1760芯片的新功能比较多,能全方位的提高整个系统的性能。此外,该芯片在录放音时音质清晰明了,几乎不存在噪音干扰。与使用蜂鸣器实现的闹钟比较,在通过语音芯片完成的语音闹钟播报更能体现出人性化的一面,也更体现了ISD1760芯片功能的强大。这款芯片有两种实现模式,一类是用硬件直接录放音,另一类是采用四线协议与单片机通信,智能家用唤醒系统使用了第二种情况,通过软件编译实现语音播报功能。在主控单片机与 ISD1760进行通信时,所采用的是通过四线SPI协议来完成的,而且几乎所有的操作都可以通过SPI协议来完成[10],因此,录放音模块可以作为一种新形式完成播报。SPI协议四线接口功能描述如表2所示。
表1 协议接口功能描述
接口
功能描述
MOSI
数据输入端口。主控制芯片在SCLK上升沿前的半个周期将数据放入MOSI端,SCLK在上升沿时,数据会被锁存在芯片内
MISO
串行输出。ISD1700在 SCLK前的半个周期将数据放置在MISO端,在SCLK的下降沿时,数据移出
SCLK
通信接口的时钟。由主控制芯片产生,并且被用来同步芯片MOSI和MISO 端各自的数据输入和输出
/SS
若此接口为低时,该芯片就被选为被控制的设备并开启通信协议接口
语音模块起到响铃功能,并能提醒人们温度和穿衣的建议。ISD1760的工作方式分别为独立方式和SPI协议方式。本系统采用了SPI工作模式,在单片机作为主控机时,ISD1760作为从机,若需要播报不同的语音段,就会通过单片机发送不同的指令来控制播报。ISD1760芯片是在8KHz采样率下的录音,录音经过麦克风输入,为了使得到的声音效果比较好,选择了喇叭来播报,同时,电路选取合适的电阻和电容来配合语音模块完成各项功能 。在ISD1760语音芯片被SPI总线控制时,系统中采用STC89C51单片机的P3口完成与之通信,STC89C51单片机与ISD1760语音芯片通信时接口不多,仅需四条线即可,语音芯片的MISO管脚接单片机的P3.2引脚,此管脚可实现数据的输出,ISD1760输出的数据信号可以从MISO引脚被单片机接收存储;语音芯片MOSI管脚与单片机的P3.3口通信时,此管脚实现的就是数据的输入,所需的读入操作和放音地址都是从ISD1760的MOSI管脚输入的;语音芯片的SCLK与单片机的P3.4端口通信时,SCLK主要是实现时钟输入的;P3.5管脚接语音芯片的片选引脚/SS,此管脚主要是用来控制芯片是否选通。SP+和SP-端口分别接外接喇叭的正负极。语音模块电路原理图如图6所示,其中U4为语音芯片。


图6语音模块电路图
3.5显示模块的设计
系统采用LCD123864液晶作为显示模块,常用的12864液晶模块有蓝色背光和绿色背光、有无字库的[11],本次设计中所用的是蓝色有字库的液晶显示器,具有两类接口方式,一种是四位或八位的并行接口,另一种是二线或三线的串行接口。 12864液晶可以显示设计中所需的时间、日期、温度及闹钟图标等内容,这比1602功能明显强的多。相对而言,一般的显示器内部结构有一定的缺陷,会消耗大量的电量,然而LCD12864液晶显示器耗电量却比其它的显示器耗电量小很多,所需的电压也容易满足。液晶显示器的工作温度范围能够满足中温度采集所需的温度值,并且能较准确的显示。LCD12864的硬件设计相对而言比较简单,显示所需程序在一定程度上比较容易编译实现,而且价格合适,所以此系统采用了这款显示器。
显示模块中采用12864液晶显示器,由于设计中需要的时间、日期等内容都能通过这款显示器来实现,所以12864液晶显示器是设计中相当重要的模块。12864显示器是数字式的接口,能在显示屏上显示智能闹钟的数据,与单片机系统连接时采用了并行接口。显示模块主要是将单片机发送来的时间数据和温度数据进行一系列的处理并由显示器显示,还能在设置闹钟后闹钟图标也能显示出来。在液晶显示器和单片机连接时,显示器的数据线DB0(7)-7(14)与单片机的P0.0-P0.7相连接,并需要10K的上拉电阻。VO端口接一个103的电位器,改变电位器的阻值液晶显示器的亮度有所变化。PSB引脚高电平时选择并口,低电平时选择串口的接法,引脚NC不需要接任何管脚。液晶显示模块原理图如图7所示。


图7 液晶显示模块电路图
3.6PWM唤醒灯模块设计
调光模块设计中,采用了较为简单的三极管驱动LED电路。考虑到设计需要,因为三极管驱动成本低,而且容易控制和实现等特点,所以最终选用了大功率三极管驱动唤醒灯模块[12]。由于STC89C51单片机不具备PWM配置,因此通过单片机软件产生PWM波并实现自动调光的功能,唤醒灯的本质是利用PWM对LED中的正向电流进行调节来完成的。减小LED电流将起到调节LED光输出强度的作用,然而,正向电流的变化也会改变LED的亮度,因为LED的亮度会随着电流的变化而变化[13]。模拟早晨日光的效果是通过与单片机连接产生PWM波,LED发光二极管亮度会由暗变亮,直到亮度达到最大。
三极管是放大电流的器件,它分为两类,一类是NPN型,一类是PNP型,设计中采用了NPN型,这种三极管理解起来很容易。三极管的放大作用是小的基极电流


变化引起大的集电极电流


变化,并且基极电流与集电极电流成正比。若基极电流由零开始增大时,在三极管没有达到饱和前,那么LED的亮度就会随着变亮。LED的亮度受到电流控制,通过控制电流改变LED的亮度[13]。
本系统LED光源用三极管来放大电流,LED灯串联一个上拉电阻限流来保护二极管。电流通断的变化用NPN型三极管实现,PWM波由单片机的P3.6输出,低电平有效。在单片机上电后设置闹钟时间,在设定的时间范围内调光电路开始启动,唤醒灯模拟日光直到达到最亮,调光电路原理图如图8所示。


图8 调光电路原理图
4软件系统设计
4.1编译软件及语言
在智能家用唤醒系统设计中,采用Keil C51软件作为编译软件,这款编译软件拥有功能强大的开发调试工具,软件里包括各种各样的函数可以容易的调用。单片机软件的开发系统能够完成编辑、编译、调试和仿真等这一系列开发流程。程序在经过编译后,就能体会到此软件编译软件生成代码效率是相当高,语句简洁易懂。
该智能家用唤醒系统软件部分所用的编程语言是C语言,由于C语言结构比较丰富,程序设计时相对而言比较容易实现,同时C语言所能够适用的范围大而且灵活方便。其中,最主要的因素C语言是大学期间一直应用的编程语言,这种语言相对汇编语言而言比较简单易懂。因此,本次设计的软件任务最终决定选用C语言编程来完成。
4.2系统主程序
为实现系统功能,系统软件各部分功能必须按要求编程。智能家用唤醒系统的软件部分主要包括:单片机主控部分、LCD12864液晶显示部分、时钟控制部分、语音播报、温度检测部分、调光及按键部分等[14]。主程序对模块进行初始化,而后调用DS1302时间处理子程序、读温度、处理温度、显示、按键及语音录放子程序等模块。系统的整体程序流程图如图9所示。


图9 流程图
4.3子程序设计
本系统功能是通过软件和硬件相结合实现的。子程序设计包括显示、时间、温度、语音、调光及按键等。各个模块所实现的功能大体可由模块的流程图表示,主要介绍显示、时间和温度的工作流程。由于程序较长,所以程序将在附录部分中以模块的形式全部列出。
LCD显示子程序的设计,程序主要实现对需要的信息的显示,显示包括时间及温度等信息。需要在写程序时注意它的读写控制指令,对显示进行初始化,调用时间、温度及农历转公历等子程序的调用,将温度值和时间数据转换为液晶字符显示。通过液晶显示程序能够实现时钟的实时显示以及温度值的显示,可以实现万年历功能。使用串口方式将液晶显示与控制芯片通信,程序比并口方式简单易实现。子程序LCD12864显示模块子程序的流程图如图10所示。


图10 LCD子程序流程图
DS1302子程序的设计,在将时钟初始化后写入时钟的初值,时钟模块开始计时并读出数据送至显示器显示,其流程图如图11。


     图11 DS1302子程序流程图
DS18B20温度子程序,主要包括初始化,检测温度的存在与否,进行读写操作并转换读取温度,其程序流程图如图12所示。


图12 温度子程序流程图
5系统安装与调试
5.1硬件系统调试
智能家用唤醒系统设计的电路系统较大,因而这对焊接方面而言更是不容轻视。在庞大的电路系统中,在焊接时出现一点的失误,后续的检测及调试就不会顺利地进行,而且电路在焊接时线比较多,要尽量避免线与线之间的干扰,若影响较大则会对电路造成短路现象[15]。
硬件模块电路调试是为了检测电路中是否会出现电路不通等情况,同时也是在检测各个元器件之间的连接是否正确。先检测电源部分的电路,然后依次检测实时时钟模块、温度检测模块、显示模块及语音模块等,主要检测各引脚的连接。经过模块测试后再进行整体测试,在该设计硬件调试的过程中,遇到以下问题:
第一,当确保硬件电路连接无误后,系统上电启动后LCD12864不显示,这样的情况可能是硬件电路中存在错焊或虚焊,也可能芯片插反导致短路。解决的方法:首先,检查芯片的供电电压是否5V,检查电路有没有问题;然后,调节控制背光的电位器,电位器阻值不合适也会使所显示出来的光亮有一定的差异;最后,显示不是很稳定,应将单片机的31引脚接高电平。
第二,电路工作一段时间后芯片会发热,经过仔细地用万用表检查电路,发现有短路现象。由于在液晶显示器所接的排阻短路导致此种情况出现,解决的办法:断掉短路部分重新连接。
5.2软件系统测试
智能家用唤醒系统是多功能的设计,当前的日期、时间和温度都能被液晶显示器显示。由于唤醒系统所需的功能较多,因此它的程序编写也较为复杂,所以在编写程序时各个模块的程序相当重要,子程序和主程序之间在连接和调试时就需要注意逻辑问题。在保证硬件电路无误时,对软件开始调试。首先,将系统的整体主程序框架写出,主流程分为几个子程序,分别是温度、时钟、语音、显示等系列;然后,每个子程序开始调试,完成各部分的软件功能;最后,系统进行整体调试完成设计功能。在经过多次的修改程序并调试完所有的程序后,在实物上进行验证。在调试过程中遇到了一些问题,在修改时间时,农历的显示没有自动调整对应上。针对这一问题,在调试时把其他的程序设置断点并暂时屏蔽,将农历转换的子程序进行独立调试。这时就会发现调用时间自动调整不能完成更新,十进制和十六进制的处理不太合理导致时间出现混乱。最后经过进制之间的修改调整使得时间能正常显示。
5.3系统误差分析
本系统的误差来源:第一,DS1302时钟芯片本身的问题,这个可以通过测试,确定在一定时间内误差是多少,可用程序调节弥补误差;第二,系统的外围器件等带来的误差,因此在焊接时元器件布局要合理,保证线路质量,最大程度的减小误差。第三,在软件设计时,温度值的转换没有经过精确的计算导致温度的读取出现了问题,精度不准,测量的数值有所偏差,因此需精确计算温度,采用软件实现。
6结束语

通过本次智能家用唤醒系统的设计,人性化的智能系统设计显得越来越重要。这款基于单片机的智能唤醒系统从硬件和软件两大方面解决了普通闹钟的不足,在加入光度调节从而使熟睡中的人们能够在设定的时刻醒来。闹钟会在设定时间前将唤醒灯打开,调节人体生物钟,在人们浅睡眠时闹钟响起并播报温度等信息。该系统以单片机为控制芯片,外接时钟电路、语音电路、温度采集电路、自动调光电路等来实现各项功能。这款智能唤醒系统不仅能够更人性化的唤醒熟睡中的人们,还能提高人们的工作效率。这次设计中,智能家用唤醒系统在仿真时能够很好的结合软硬件的设计,但是在实际中由于外界因素的干扰,智能唤醒系统无法精确的检测出温度示数,也由于软件设计中延迟不当会影响时间的不准确。在实际操作时会出现偏差,只有不断地改进调试,在经过整体的优化才能有所改善。这款较人性化的智能闹钟设计在一定程度上实现了为我们服务的功能,但难免总是会存在一定的弊端,温度模块检测的温度是室内温度,可以通过不断改进测量室外温度,可以在本次设计的基础上引入红外遥控,从而更人性化的为人们服务。
附录2 实物图


单片机源程序如下:

#include <STC89C51.H>
#include <stdio.H>
#include <string.H>
#include "LCD12864.h"
#include "DS1302.h"
#include "DS18B20.h"
#include "delay.h"
void display_2(void)
{
              unsigned char display_char[16] = {0};
              int temp = 0;
            
              write_com(0x03);
              delay(50);
              write_com(0x91);
              display_char[0] = (TIME[6]/16) + '0';//年
              display_char[1] = (TIME[6]&0x0f) + '0';
              display_char[2] = '-';
              display_char[3] = (TIME[4]/16) + '0';//月
              display_char[4] = (TIME[4]&0x0f) + '0';
              display_char[5] = '-';
              display_char[6] = (TIME[3]/16) + '0';//日
              display_char[7] = (TIME[3]&0x0f) + '0';
              hzkdis(display_char, 8);
              write_com(0x97);
              switch((TIME[5]&0x07))
              {
                            case 1: hzkdis("一", 2);break;
                            case 2: hzkdis("二", 2);break;
                            case 3: hzkdis("三", 2);break;
                            case 4: hzkdis("四", 2);break;
                            case 5: hzkdis("五", 2);break;
                            case 6: hzkdis("六", 2);break;
                            case 7: hzkdis("日", 2);break;
              }
            
              write_com(0x8A);
              display_char[0] = (TIME[2]/16) + '0';//时
              display_char[1] = (TIME[2]&0x0f) + '0';
              display_char[2] = ':';
              display_char[3] = (TIME[1]/16) + '0';//分
              display_char[4] = (TIME[1]&0x0f) + '0';
              display_char[5] = ':';
              display_char[6] = (TIME[0]/16) + '0';//秒
              display_char[7] = (TIME[0]&0x0f) + '0';
              hzkdis(display_char, 8);
            
              temp = Ds18b20ReadTemp();
              write_com(0x9B);
              if(temp < 0)//负
              {
                            temp =~ temp;
                            temp -= 1;
                            temp=(float)temp*0.625+0.5;
                            display_char[0] = '-';
              }
              else
              {
                            display_char[0] = ' ';
                            temp=(float)temp*0.625+0.5;
              }
            
              display_char[1] = temp / 100 + '0';
              display_char[2] = temp % 100 / 10 + '0';
              display_char[3] = '.';
              display_char[4] = temp % 10 + '0';
              hzkdis(display_char, 5);
}
/********************************************************************
* 名称 : main
* 功能 : 主函数
* 输入 : 无
* 输出 : 无
***********************************************************************/
void main(void)
{
              lcdinit();
              Ds1302Init();
              display();
            
              while(1)
              {
                            Ds1302ReadTime();
                            display_2();
                            Delay1ms(200);
              }
}
#include "DS18B20.h"
/*******************************************************************************
* 函 数 名         : Ds18b20Init
* 函数功能                                 : 初始化
* 输    入         : 无
* 输    出         : 初始化成功返回1,失败返回0
*******************************************************************************/
static uchar Ds18b20Init(void)
{
              uchar i;
              DSPORT = 0;                                          //将总线拉低480us~960us
              i = 70;            
              while(i--);//延时642us
              DSPORT = 1;                                          //然后拉高总线,如果DS18B20做出反应会将在15us~60us后总线拉低
              i = 0;
              while(DSPORT)              //等待DS18B20拉低总线
              {
                            i++;
                            if(i>5)//等待>5MS
                            {
                                          return 0;//初始化失败
                            }
                            Delay1ms(1);            
              }
              return 1;//初始化成功
}
/*******************************************************************************
* 函 数 名         : Ds18b20WriteByte
* 函数功能                                 : 向18B20写入一个字节
* 输    入         : com
* 输    出         : 无
*******************************************************************************/
static void Ds18b20WriteByte(uchar dat)
{
              uint i, j;
              for(j=0; j<8; j++)
              {
                            DSPORT = 0;                                   //每写入一位数据之前先把总线拉低1us
                            i++;
                            DSPORT = dat & 0x01;  //然后写入一个数据,从最低位开始
                            i=6;
                            while(i--); //延时68us,持续时间最少60us
                            DSPORT = 1;              //然后释放总线,至少1us给总线恢复时间才能接着写入第二个数值
                            dat >>= 1;
              }
}
/*******************************************************************************
* 函 数 名         : Ds18b20ReadByte
* 函数功能                                 : 读取一个字节
* 输    入         : com
* 输    出         : 无
*******************************************************************************/
static uchar Ds18b20ReadByte()
{
              uchar byte, bi;
              uint i, j;            
              for(j=8; j>0; j--)
              {
                            DSPORT = 0;//先将总线拉低1us
                            i++;
                            DSPORT = 1;//然后释放总线
                            i++;
                            i++;//延时6us等待数据稳定
                            bi = DSPORT;              //读取数据,从最低位开始读取
                            /*将byte左移一位,然后与上右移7位后的bi,注意移动之后移掉那位补0。*/
                            byte = (byte >> 1) | (bi << 7);                                                                                    
                            i = 4;                            //读取完之后等待48us再接着读取下一个数
                            while(i--);
              }                                                      
              return byte;
}
/*******************************************************************************
* 函 数 名         : Ds18b20ChangTemp
* 函数功能                                 : 让18b20开始转换温度
* 输    入         : com
* 输    出         : 无
*******************************************************************************/
static void Ds18b20ChangTemp()
{
              Ds18b20Init();
              Delay1ms(1);
              Ds18b20WriteByte(0xcc);                            //跳过ROM操作命令                           
              Ds18b20WriteByte(0x44);                  //温度转换命令
//              Delay1ms(100);              //等待转换成功,而如果你是一直刷着的话,就不用这个延时了
}
/*******************************************************************************
* 函 数 名         : Ds18b20ReadTempCom
* 函数功能                                 : 发送读取温度命令
* 输    入         : com
* 输    出         : 无
*******************************************************************************/
static void Ds18b20ReadTempCom()
{            
              Ds18b20Init();
              Delay1ms(1);
              Ds18b20WriteByte(0xcc);              //跳过ROM操作命令
              Ds18b20WriteByte(0xbe);              //发送读取温度命令
}
……………………
————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
                        
原文链接:https://blog.csdn.net/runweipa/article/details/139536088

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值