本科毕业设计(论文)
题目名称: 基于STM32的智能家居系统设计 学 院: 计算机科学技术学院 专业年级: 计算机科学与技术(工)12级 学生姓名: 张云朋 班级学号: 1 班 41号 指导教师: 范忠诚
2016 年 6 月
I / 68
摘 要
随着科技的不断发展进步和人们对家居生活要求的逐步变高,智能家居已经得到了人们的认可,而现如今一套完整的智能家居设备价格昂贵,一般的家庭难以承受其高昂的价格,针对此种现象,一款功能稳定全面,但成本低廉的智能家居产品会帮助人们在价格和功能之间找到一条满足人们愿望的出路。此款智能家居采用STM32处理器,技术成熟,程序移植方便,价格低廉。本款家居设备设计包括硬件设计和软件设计两个部分:硬件设计包含 :12864液晶电路、温度湿度传感器电路、烟雾浓度采集电路、ADC转换电路、报警电路、电源电路、光照采集电路和灯光控制部分电路,软件设计包含主程序、数据(温度、湿度,气体浓度,光照)检测及处理、和标准气体标定、ADC数据转换,当气体浓度超限时报警程序。经实验测试结果表明该智能家居设备有自动检测家庭环境指标并可以对采集信息进行及时稳妥的处理,精度高,检测范围广,稳定性好,显示简单,操作简便,抗干扰能力强等优良性能。
关键词:ARM-M3;ADC;数据采集与处理;智能家居
I / 68
Abstract
Along with the continuous development of science and technology progress and people's requirement for household life gradually become tall, intelligent household has gained the recognition of people, now a complete set of intelligent household equipment is expensive, the average family is difficult to afford the high prices, aiming at this phenomenon, a stable overall function, but low-cost intelligent household products can help people find a way out between price and functionality. This intelligent household USES STM32 processor, mature technology, application transplant convenience, low prices. This household equipment design including hardware design and software design of two parts: hardware design includes: 12864 LCD, reactive temperature, humidity sensor circuit, the concentration of the smoke collecting circuit, ADC conversion circuit, alarm circuit, power circuit, acquisition circuit and lighting lighting control circuit, software design includes the main program, data (temperature, humidity, gas concentration, light) detection and processing, and calibration standard gases, ADC data conversion, when gas concentration overrun alarm program. By the experimental test results show that the smart home devices have automatic detection family environment index and can be conducted to collect information to err on the side of the processed on time, high precision, detection range, good stability, display is simple, easy operation, strong anti-interference ability and other excellent properties.
Key words: ARMv7-M; ADC; Data acquisition and processing; serial
communication
II / 68
目 录
摘 要 ................................................................ I Abstract ............................................................... II 第1章 绪 论 ........................................................ 1
1.1 选题背景 ....................................................... 1 1.2 课题意义 ....................................................... 1 1.3 国内外发展概况 ................................................. 1 1.4 指导思想 ....................................................... 2 第2章 开发工具与MCU简介 .............................................. 3 2.1 STM32F10XX .................................................... 3 2.2 KEIL MDK ...................................................... 5 第3章 总体分析与设计 .................................................. 7
3.1 方案分析 ...................................................... 7
3.1.1 整体系统方案分析 ......................................... 7 3.1.2 数据采集方案设计 ......................................... 8 3.1.3 数据存储方案分析 ......................................... 8 3.1.4 显示方案分析 ............................................ 10 3.2 功能设计 ..................................................... 11 第4章 详细设计与实现 ................................................. 12 4.1 界面设计 ...................................................... 12 4.2 原理图设计 .................................................... 13
4.2.1 数据采集模块 ............................................ 14 4.2.2 温湿度传感器模块 ........................................ 15 4.2.3 烟雾传感模块 ............................................ 16 4.2.4 液晶显示电路设计 ........................................ 17 4.2.5 报警电路的设计 .......................................... 19 4.2.6 时钟模块 ................................................ 20 4.3 业务处理模块设计 .............................................. 22 4.3.1 界面显示任务 ............................................ 22 4.3.2 AD采样及数据处理 ....................................... 23 4.3.3 烟雾传感器 .............................................. 28 4.3.4 温湿度传感器 ............................................ 30 4.4.5 灯光控制与光照检测 ...................................... 32
第5章 结果分析 ........................................................ 36
5.1 硬件设计的结果分析 ............................................ 36
1 / 68
5.1.1 温湿度模块的分析 ........................................ 36
5.1.2 光照模块的分析 .......................................... 36 5.1.3 烟雾检测 ................................................ 37 5.1.4 硬件综合测试 ............................................ 38 5.2 软件设计的结果分析 ......................................................................................... 38 结 论 .............................................................................................................................. 40 致 谢 .............................................................................................................................. 41 参考文献 .............................................................................................................................. 42 附 录 .............................................................................................................................. 44
2 / 68
第1章 绪 论
1.1 选题背景
进入21世纪,人们的生活节奏越来越快,生活压力也越来越大,家成为人们最温馨的地方,人们对待自己最温暖舒适的家庭环境要求也随之在不断提高,如今的人们早八晚五的工作,上级的压力,父母长辈的压力,同事之间盲目的攀比等等,早已经将当代人压的喘难以呼吸,人们似乎已经注意到了家是自己的避风港,家居生活得到了人们的广泛关注,如今电子行业的发展速度飞涨,智能产品横飞,先进的科技与人们想要的智能家居生活擦出了美丽的火花--智能家居,时光荏苒,转眼间,智能家居从出现到现如今经历了几十年的漫长发展逐步走向成熟,安全,智能,方便的家居生活得到了广大普通百姓的认可,从企业到个人都无时无刻与它发生着亲密关系,人们已经清楚的看到,智能家居的发展已成必然,他的腾飞亦不可阻挡。
1.2 课题意义
众所周知智能家居应经崭露头角,近几年一直以良好高速的发展态势在前进,智能家居市场上也开始出现了很多新颖的设备来满足人们的生活需要,但从总体的状况来分析总结,仍有不尽善尽美的地方,最主要两点是标准不统一和权威产品的缺乏。伴随着科技的进步,经济的发展,人们的财富变多的同时,对自己的生活环境的要求水平也的随着变高,智能家居也越发变的受人青睐。家居智能化控制的开发和研究是未来国家经济发展的必然趋势。智能家居控制器可以为系统提供更智能更人性化生活模式,使住户的生活更加便捷,更高效,更能为家庭的日常活动,为快节奏的都是生活减小人们的压力,同时提供巨大方便。而且在现在这个重视健康环保的世界里,智能的为住户提供检测好空气的温度,湿度等检查空气成分让住户安心,放心可以满足人们的个性化需求。同时,智能家居控制器可以根据住户的要求调整方案,紧急事故处理,危机救护等急救控制,充分满足用户的需要。
1.3 国内外发展概况
智能家居在国内早已经不是一个新兴产业,处于一个导入期与成长期的临界点,大众市场的消费观念还未完全形成,但随着智能家居市场经营者推广的进一步实施,引导消费者的消费方向和新产品的使用等措施的应用,智能家居
1 / 68
市场的的活跃只是时间的问题。如今智能家居至今在中国已经历了近13年的发展,从人们刚开始的梦想,到今天真真正正的走进我们的生活,经历了一个反复曲折路。在1994年---1999,渡过智能家居的第一阶段萌芽期/智能小区期,在2000年---2005年期间,迎来了自己的第二阶段——开创期,在2006年,经过了5年的发展,智能家居正式进入第三阶段--徘徊期,现如今,我们正在经历他的第四个阶段--融合演变期,自进入2011年以后,产品需求市场明显增长,现阶段房产行业不好,智能家居的进入能否再添新动力受到大家的关注。智能家居的产品需求量增长说明智能家居行业进入了一个新的时间段,接下来的几年的时间里,智能家居一方面进入一个相对快速的发展阶段,另一方面协议与技术标准也开始慢慢走向统一,为标准化生产提供软条件的准备。而良好的势头也吸引了一批商人的加入,开发人员工资不断攀高,新的产品层出不穷,市场竞争越来越激烈。
根据美国该行业权威公司PARKS的统计资料显示:1995年,美国一个家庭智能家居方面的花费大概在7000至9000美元之间。1995年美国家庭已使用先进家庭自动化设备的比率为0.33%,看来市场真正启动尚需时日。预计这五年内,家庭自动化的市场年平均增长率为8%.PARKS公司的资料亦显示:到2004年,家庭网络市场总额可达57亿美元,由此可知,智能家居无论在国内还是国外都有良好的发展前景,形势一片大好。
1.4 指导思想
本系统开发基于C语言。使用Keil4集成开发环境,使用现已经技术成熟的器材,以保障系统正常安全使用、质量性能好、稳定。
界面操作简单,功能全面,实用性强,人机交互友好,无需复杂操作就可以使用产品,易学易用。
2 / 68
第2章 开发工具与MCU简介
2.1 STM32F10XX
STM32系列单片机是为高性能、低成本、低功耗的嵌入式应用专门设计的,十分适合现在的智能家居研发,款型多、功能完备,资料丰富,技术也相对成熟,下面我们就来系统的了解一下这款单片机。按内核架构分为不同产品。
其中STM32F1系列有: STM32F103\"增强型\"系列 STM32F101\"基本型\"系列
STM32F105、STM32F107\"互联型\"系列 增强型系列时钟频率为72MHz,再同品型的单片机中是性能最好的一款;普通型的时钟频率为36MHz,而如今普通产品的价格得到性能大幅提升产品,相信是很多用户的最佳选择。两个系列产品都内置闪存大小是相同的,还是32K到128K,不同的是SRAM的最大容量和外设接口的这两部分。当时钟频率72MHz时候,可以从闪存中直接运行程序,速度更快,STM32功耗为36mA,是32位单片机同类市场上功耗最低的产品。
图2-1 STM32F10XX功能框图
内核:32位mcu处理器,频率为72MHz,采用单周期乘法,不容易受外部设备电流影响,稳定性更好。
3 / 68
存储器:片上集成32-512KB的闪存。6-64KB的只读存储器。
时钟、复位和电源管理:电源为3V供电。上电复位、掉电复位电路完善,自带可编程的电压探测器(现不常应用)。晶振为16MHz(频率可设置,可满足不同外部设备的驱动)。8MHz RC电路。40 kHz的RC振荡电路(可外接振荡电路,也可利用自身具有的振荡电路)。CPU时钟具有校准功能,由的32kHz的晶振单独完成。
低功耗模式:3种低功耗模式:休眠,停止,待机模式。 调试模式:串行调试接口和JTAG接口。 DMA:12通道DMA控制器。
支持的外设:定时器,ADC,DAC,SPI,IIC和UART。
3个12位的us级的A/D转换器:A/D测量范围:0-3.6V。双采样和保持能力。 D/A转换器的种类多,可以适合不同型号外设信息采集,非常全面。
快速I/O端口:所有的端口都可以链接到个外部中断。排除模拟量的输入,所有的端口都可以接受5V以内的信号输入。
定时器:4个16位定时器,每个定时器都配有4个IC/OC/PWM或者脉冲计数器。2个16位控制定时器:最多6个通道可用于PWM输出除此还有2个看门狗定时器,可供多个外设同时工作时应用。
Systick定时器:24位倒计数器。2个16位基本定时器用于驱动DAC。
拥有3个SPI接口,两个和IIS复用端口。一个2.0B的CAN接口,一个2.0USB接口含5个USART接收端口,13个通信接口,2个IIC接口,和一个SDIO接口。 1、相较传统的嵌入式处理器多一个嵌入式ARM内核,使其兼容性更加强悍,不仅对编程软件还是与单片机相关的工具都是一次技术上的统一,与此同时提高了代码处理效率,运行,调试更加高效。
2、嵌入式Flash存储器和RAM存储器:内置512KB的闪存,为数据的安全性提供了更好的保障,存储数据程序也更加方便,只读存储器与CPU的时钟速度相同,可进行高速读写操作,更加贴近产品驱动需要。
3、可变静态存储器(FSMC):STM32的静态存储器拥有4个片选,且每一种片选模式还有四种模式选择,控制的更加细致,精确,多更控制更加方便,不需要再加繁杂的外设,代码都是从外部存储器执行,不占用没存,节省空间,提高运行速度,外部访问按照36MHz进行,速度更高,出错率更低。
4、ARM的中断:可以处理43个中断通道,包含16个中断优先级,可以同时处理多个外部中断,对外设的处理精确度得到有效提高,更适合处理复杂多样的外设。紧密耦合的NVIC实现了低的中断处理延迟,直接向内核传递中断入口向量表地址,紧密耦合的NVIC内核接口,更加方便允许中断提前处理,对后到的更高优先级的中断进行处理,自动保存处理器状态,中断入口在中断退出时自动恢复,不需要指令控制,自动化程度更好,减小程序员的工作量。
5、外部中断/事件控制器(EXTI):外部中断/事件控制器由19个产生中断请求检索组成。每条线都是经过独特配置用于选择触 发事件(模式:上升沿,
4 / 68
下降沿,或者两者都可以),可以同时屏蔽多个,也可以只屏蔽一个,更有利于对外设的控制。有一个挂起寄存器用来检测中断请求。当外部线上出现长度超过内部时钟周期的脉冲时,EXTI便马上能检测到是由外部的信号在申请中断。
6、时钟和启动:系统的时钟在系统在工作前,先需要时钟的设定,一种是利用内部8MHz的晶振作为CPU时钟源。另外可以选择一个外部的4-16MHz时钟源,STM32在时钟的检测十分严格,会实时监控当与控制器被禁止那么软件中断管理也会跟着被禁止。还可以在PLL时钟的中断管理设定时钟。多个预比较器可以用来配置AHB频率,包括高速APB2和低速APB1,高速APB最高的频率为72MHz,低速APB最高的频率为36MHz。
7、Boot模式:Boot引脚有3种Boot模式选项可供选择:从Flash进入,从系统存储器导入,从SRAM进入。Boot导入代码存储在系统存储器,用于通过USART1对Flash存储器编程。
8、电源供电方案:工作电压2.0V-3.6V,外部电源通过VDD引脚连接,用于I/O和内部调压器。VSSA和VDDA的电压范围都是2.0-3.6V,外部模拟电压用于ADC,复位模块,RC和PLL,在VDD范围之内,VSSA和VDDA必须相应连接到VSS和VDD才可以。VBAT的电压范围为1.8-3.6V,当VDD无效时为RTC,晶振和备份寄存器也可以为其提供电源,保证正常工作不受到影响。
2.2 KEIL MDK
Keil MDK 的应用十分广泛,因其功能全面性能佳,界面简介友好,从其问世就迅速被广大程序工程师所熟知和使用,工程师的反馈---非常适合STM32的开发。Keil MDK,也称MDK-ARM,Realview MDK、I-MDK、uVision4 等。
MDK-ARM软件为基于Cortex-M、Cortex-R4、ARM7、ARM9处理器设备提供了一个完整的开发环境,一款软件多项应用,方便嵌入式工程师们在不同项目中多种程序的编写,不用多次熟悉开发工具,单凭这一点,早已在嵌入式工程师的心中占据巨大优势, MDK-ARM是一款专为微控制器应用而设计生产的,因其界面简洁清晰,不仅易学易用,而且功能强大,能够满足大多数的嵌入式应用,综合分析是嵌入式工程师的不二选择。
MDK-ARM有四个可用版本。所有版本均提供一个完善的C / C++开发环境,实现多界面,多机型,多语言集于一身的高性价比产品,其中MDK-Professional还包含大量的中间库,方便调用且数据库全面。
使用Keil 来开发嵌入式软件,大致有以下几个步骤:
1. 创建一个project,选择芯片,并进行一些必要的配置信息 2. 编写C 源文件 3. 编译工作代码
4. 修改源程序中的错误 5. 下载程序调试
5 / 68
uVision4 开发环境如下我们可以做到编辑,编译,项目管理等多个程序调试步骤,窗口设计合理,出错显示更加清晰,方便程序的调试。
uVision4的特点:支持多系列单片机(Cortex-M、Cortex-R4、ARM7和ARM9);多语言(C/C++)的工具链,操作系统自带源码,封装模块化数据;不仅提供编译,调试,还具备仿真环境;网络套件提供多种协议应用;拥有标准的USB设备连接可能,与外设交互友好;不仅可以处理程序代码,还可以处理图形;程序每运行一次会有一次覆盖;符合国际公认的软件接口标准。
ULINK USB-JTAG 界面适配器:
ULINK USB-JTAG 是一个用于连接PC USB 口和开发板JTAG 口的小硬件适配 器。通过JTAG你可以很方便的将你的程序下载到目标板上测试和验证程序运行的效果。ULINK 支持如下操作:
1. 下载目标程序
2. 检查存储器和寄存器 3. 单步运行程序 4. 插入多个中断点 5. 实时运行程序 6. 烧写FLASH 存储器
6 / 68
第3章 总体分析与设计
3.1 方案分析
3.1.1 整体系统方案分析
每个智能家居系统的设计者首先考虑到的问题就是MCU选型的问题。嵌入式设计中比较主流的两款单片机就属ARM与AVR/51最受大家的青睐,51是一款8位MCU的处理器,相较32位处理器的ARM在运算能力上有明显的不足,但32位的运算的指令也是非常复杂的,进行大量的数据运算,视频数据,能力虽然较8位机强很多,运算速度也高好多倍,但在各个中断,寄存器配置,时钟要求等等也更为严格,而且AVR的编程需要配置gcc或icc才能正常工作,有固定的工作的环境,和51单片机相比,很复杂,可以用来参考的文献资料也没有51多,ARM与51相比虽然采用指令集简化了很多,可以在每个时钟周期内执行一条命令,51需要12个时钟周期才能完成一条指令的工作,综合来分析51与STM32单片机都拥有各自的优势,如何选择就要从需求上加以分析。
51单片机是每一嵌入式编程人员的入门课程,很基础,电路也相对简单,资料丰富,芯片很便宜,市面很常见,但一旦处理大量的数据,设计复杂运动控制,视频时,51就力不从心了,运算的速度和效率低也是51的一个致命的缺点,简单的总结下就是AVR的指令系统比较精简,总线和存储结构也与51单片机不同,速度比51快很多。其次,从性能的角度分析,ARM是32位处理器,频率高达百兆赫兹,速度和处理能力远远优于AVR和51,根据智能家居需要控制多个家用设备,传送视频图像等等因素考虑,为了满足该设备的设计要求,以上的51和AVR类的MCU产品功能上仍显不足。
STM32FX 系列的MCU从功能上来说更具吸引力,尤其是STM32F103VCT6这款MCU,片内外设相当丰富,3 个12 位模数转换器、2 通道12 位D/A 转换器、12通道DMA 控制器、80个快速I/O 端口、8 个定时器、多达13 个通信界面。除了其丰富的片内外设,它的每个I/O口都对应着32位的配置寄存器,可以进行自由的配置,还具有锁存器和16位的复位寄存器和复位寄存器。每个I/O口都可以自由的编程,每个I/O口都可以由软件配置成多种模式。它的嵌入式中断矢量控制器,具有16个可编程优先级,60个可屏蔽中断通道,还具有延迟的异常和中断处理。
STM32F103VCT6 优秀的特性决定了本设备产品设计的最终平台。在选定MCU 后,
首先规划本设备的各个功能的实现。通过分析该设备在工业现场需要发挥的监控作用,初步将该设备的功能设计如下:AD 数据采集,串行通信,EEPROM 数
7 / 68
据存储的读写,SD 卡数据存储的读写,NANDFLASH 数据存储的读写,时钟的读写设置。
STM32F103VCT6的ADC转换器是一种12位精度的逐次逼近型的数字转换器。它有18个通道用来传递信息数据,可以测量16个外部信号和2个内部信号。本款产品没有全部使用所有的ADC,仅使用了其中的6条AD转换通道。在ADC 通过外部传感器将模拟信号转化为数字信号后,接收返回的数据存储在SD卡中或者EEPROM 中,供使用程序人员对数据进行分析和处理。时钟在不断电的情况下即可正常运行,可以为产品的液晶屏显示提供时间不需要外接设备提供时间。 3.1.2 数据采集方案设计
我们所常用的传感器信号一般都是模拟量,例如温度传感器,湿度传感器等为了数据的操作与处理方便,需要将其转换为数字量,所以需要使用到ADC 器件。紧接着就是AD方案的选择问题:其中一种是使用独立的ADC转换器,另一种使用MCU中自带的ADC 转换模块。而ADC的选择依据有如下几个关键的参数有分辨率,转换速率,模拟量输入端数,模拟量输入电压范围,数字量输出方式等等。我们以ADC0809为例简单说明下,0809的参数如下:1)8路输入通道,8位A/D转换器,即分辨率为8位。2)具有转换起停控制端。3)转换时间为100μs。4)5V电源供电。5)模拟输入电压范围0-+5V,不需要校准和清零过程。6)工作温度在-40~+85摄氏度。7)功耗低,约15mW。
ADC0809属于中等速度的ADC转换器,价格也比较低,但分辨率较低。如果外接高速ADC 转换器,价格又过高,并不是最好的选择。然而,对于MCU自带的ADC模块,其工作性能并不差。该ADC属于逐次逼近型模拟数字转换器。它有18个信息采集返回通道,可测量16个外部信号和2个内部信号。在本次设计中我们将两种ADC的采集方法并用,下面会有详细的使用说明。 3.1.3 数据存储方案分析
在智能家居系统里,需要存储的数据并不是很多,温湿度信息的存储和登录密码存储即可。说到STM32的闪存用途,我们的第一反应是用来装程序代码的,实际上,STM32的片内FLASH不仅可以用来装程序数据代码,还用来装芯片配置、芯片ID等等。虽然智能家居系统里的数据存储只放在FLASH就可以了,但我们为了大家能够更好的了解,还是简谈下FLASH的有关问题: 1、FLASH分类
根据用途进行分类,STM32片内的闪存分成两部分:主存储部分、信息块部分。 主存储块可以用于存储程序,我们写的代码,数据都会存储在这里。 信息块又分成两部分:系统存储器部分、选项字节部分。系统存储器存储是出厂时就被锁死的,用户不需要处理它,用来存储系统代码, 选项字节存储芯片的配置内容是对主存储块内容的一种保护。 2、FLASH的页面
8 / 68
STM32的FLASH主存储块按页组织,有的产品每页1KB,有的产品每页2KB。
页面典型的用途就是用于按页擦除FLASH。从这点来看,页面有点像通用FLASH的扇区。
3、STM32产品的分类
STM32根据FLASH主存储块容量、页面的不同,系统存储器的不同,分为小容量、中容量、大容量、互联型,共四类产品。
小容量产品的主存储存容量在1-32KB之间,系统占2KB,中容量产品主存储容量在64-128KB之间,每页占1KB大小;大容量产品主存储容量在256KB以上,系统占2KB,每页占2KB;互联网型产品主存容量最大为 256KB以上,系统占18KB,每页占2KB。
根据以下简单的规则进行区分,根据其主存储块容量来划分,STM32F105xx、STM32F107xx是互联型产品。
几类单片机的不同之处就在于引导装载程序的不同,小中大容量产品的BootLoader占用空间很小,只能通过USART1进行在线编程,而互联型产品的BootLoader有18KB是小中型的9倍,从而编程的方式选择也就更加的多样化,例如USAT1、4、CAN等多种方式。 1、关于ISP与IAP ISP即在系统编程,是指直接在目标电路板上对芯片进行编程,一般需要一个自举程序(BootLoader)来执行。ISP也有叫ICP(In Circuit Programming)、在电路编程、在线编程。 IAP(In Application Programming)在应用中编程,是指最终产品出厂后,由最终用户在使用中对用户程序部分进行编程,实现在线升级。IAP要求将程序分成两部分:引导程序、用户程序。引导程序总是不变的。IAP也有叫在程序中编程。 ISP与IAP的区别在于,ISP一般是对芯片整片重新编程,用的是芯片厂的自举程序。而IAP只是更新程序的一部分,用的是电器厂开发的IAP引导程序。综合来看,ISP受到的限制更多,而IAP由于是自己开发的程序,更换程序的时候更容易操作。 2、FPEC
FPEC(FLASH Program/Erase controller 闪存编程/擦除控制器),
STM32通过 FPEC来擦除和编程FLASH。FPEC使用7个寄存器来操作闪存: FPEC键寄存器(FLASH_KEYR) 写入键值解锁。 选项字节键寄存器(FLASH_OPTKEYR) 闪存控制寄存器(FLASH_CR) 闪存状态寄存器(FLASH_SR) 闪存地址寄存器(FLASH_AR) 选项字节寄存器(FLASH_OBR) 象。
写保护寄存器(FLASH_WRPR) 象。
9 / 68
写入键值解锁选项字节操作。 选择并启动闪存操作。 查询闪存操作状态。 存储闪存操作地址。 选项字节中主要数据的映 选项字节中写保护字节的映
主存储块不仅可以全部擦除,重新写入,也可以对其中的一页或者几页进
行删除,重新写入的操作。 建议使用以下步骤进行页擦除:
1.检查FLASH_SR寄存器的BSY位。保证没有其他正在进行的闪存操作。设置一段延时等待BSY位为0,才可继续操作。 2.设置FLASH_CR寄存器的PER位为1。
3.选择出所要擦除的页码地址,尽行擦出准备。 4.启动擦除操作。
5.当收到响应信号也就是寄存器BSY变为0。
6.做检查,如果EOP位为1,说明此次操作成功否则检查前几步操作是否得当。
7.分析数据位,每次擦完后数据位都会被设置成数字1,若操作正确既可以得到全部为1的数据位,整片擦除的方法(与写入方式相反的操作)大体如下:
1.检查BSY位,确认没有其他正在进行的操作。 2.设置寄存器的MER位为1。 3.设置寄存器的STRT位为1。 4.等待寄存器的BSY位变为0。
5.查询FLASH_SR寄存器的EOP位,EOP为1时。 6.做验证。
主存储块的编程:主存储模块的程序编写每一次只可以写16bit,当寄存器的PG位被设置为1时,在一个Flash地址写入一个16位将会进行一次编程;写入任何其他的数字或者数据,总线上都会产生错误信息,当发现读取闪存时会使CPU停止工作,有可能是FPEC设置错误产生的。
建议对主存储块使用如下过程进行编写程序:
1.检查寄存器的BSY位,确认所有的其他程序操作没有占用。
2.选择编程操作。
3.在指定的地址写入要编程的半字,切记不要输入其他的数字。 4.设置一段延时,等待寄存器的BSY位变为0。
5.再一次查询寄存器的EOP位,若EOP为1表示此次操作是成功的。 3.1.4 显示方案分析
在数据显示方面上,常用的实验器材有两种可供选择,12864液晶和1602液晶,12864 顾名思义像素是128乘以64,能显示32个汉字,如果型号不同,待的汉子库不同,能显示的数字和效果都会有所不同,功能相比1602强大很多,1602只能显示符号、数字和字母能显示32个字符,但寄存器不止32个,可以将内容滚动显示出来,显示字符的顺序也可以设置,从左往右或者相反都可以,因为其功能和显示效果简单,价格比12864少很多,在嵌入式使用方面,两者
10 / 68
难度差不多,原理也相近,只要配置好指令、地址、数据即可。智能家居的在显示方面需要同时显示几行数据,而1602每一次显示的数据过少,相互比较而言12864是不错的选择。
3.2 功能设计
智能家居设备可以同时检测三个不同区域的气体浓度,三个地方温湿度情况,三个地域光照强度并且控制灯光,超过标准值时的报警功能,采用整屏显示模式。产品功能设计如图3-1所示。
ADC0809采集模块 感器烟雾传模块 温湿 度传感器模块 光照强度信 息采集模块
图3-1智能家居整体功能设计
I/O I/O I/O I/O T1 STM32 T0 I/O T2 I/O 照明显示模块 液晶显示12864模块 报警器
11 / 68
第4章 详细设计与实现
4.1 界面设计
1.温湿度显示界面
图4-1 温湿度显示界面
2. 烟雾显示界面
图4-2 烟雾显示界面
12 / 68
4.2 原理图设计
电源电路 显示 液晶电路 供电 LED电路 控制 中央处理器 CPU 控制 继电器电路 数据 温湿度电路 烟感电路 图4-3 硬件系统原理
本智能家居系统的设计分为温湿度数据采集模块、烟雾数据存采集模块、光照数据采集模块、灯光控制模块、报警模块和显示模块等6部分组成。每个模块的设计上均有其难点和特殊性,需要严格按照原理图设计规范来设计[13],原理图设计要点如下所示:
1. 各功能块布局要合理,整份原理图需要布局均衡,避免有些地方很挤,而有些地方很松。
2. 将温度信息采集模块、如温度采集模块、湿度数据采集,光照信息采集,报警部分各功能部分模块化,方便差错和修改程序。
3 在接插口时尽量将外设分布在四周,不要分布不均一面造成一侧的端口不够用。例如电源输入,输出负载接口等等。
4 对于一些像滑阻类似的可调元件,都应该标清楚方向以及物体说明,以免在实验中损坏器件。
5 外部的元器件在向主控电路接入的过程中,采取就近原则即可。 6 滤波器件应该就近排放,减少不必要的空间浪费。
7 重点的模块、信号和器件,应该用标签标注清楚,接线清楚,接口也要标注清楚,如果有条件可以用PCB画板技术。
13 / 68
9 将所需要的所有二极管统一放在一个表格中,进行标注作用,方便后续的错误检测与查找。
10 在写文档时,将重要的程序可以用黑体或者加粗。
11 用于特别表示的文字,或者标签,为了更好的区分可以不同的用不同的颜色区分,例如器件用红色,接口用黄色等等。
12 在标注元器件参数时,应该格外注重电阻的阻止,或者器件的工作电压,和工作条件,为查找故障提供方便条件。 4.2.1 数据采集模块
设备的数据采集,即ADC 数据转换模块,利用了MCU 自带的ADC 模块和外部设备ADC0809两种数据转换模式,将传感器的模拟信号转换为数字量存储起来。本设备设计的传感器为6路,所以需要MCU 的6个ADC 模拟量输入引脚,在综合考虑MCU 引脚使用情况后,决定使用PA0~PA3,PB0,PB1 引脚作为模拟信号输入端。为简化下位机电路,没有将传感器模拟信号采集部分设计到下位机上[14]。
电路设计图如图4-4所示:
图4-4 AD输入端电路图
各个模拟量输入端子全部直接连接到MCU 的ADC 模拟输入引脚上 AD数据采集程序:
void AD_data(uchar x)
{double i; int j;int ge,shi,bai; init();cs=1;cs=0;rd=1; while(x){x--;for(a=0;a<13;a++)
14 / 68
{write_com(0x80+a);write_date(table[a]);
delay(5);}delay(5);wr=1;wr=0;wr=1;delay(10); rd=0;delay(5);i=P1;i=i/255;i*=5;
i*=100;j=(int)i;ge=j%10;put_str(4,ge); j-=ge;shi=j/10;shi=shi%10; write_date(shi);bai=j/100; put_str1(2,'.');delay(5); put_str(1,bai);delay(5);
rd=1;delay(5);write_com(0x80+0x40+4); delay(5);write_date('V');delay(5);}} 4.2.2 温湿度传感器模块
为了测量的准确性和多通道数据采集,这里选择3片dht11 连接到stm32芯片上,由芯片上的IO引脚作为3片dht11 的器件数据及时钟选择端口。
电路图设计如图4-5所示:
图4-5 温湿度设计电路图
温湿度数据采集程序: u8 DHT11_Rea }
d_Bit(void) {u8
retry=0;while(DHT11_DQ_IN&&retry<100){retry++;delay_us(1);}retry=0;
while(!DHT11_DQ_IN&&retry<100){retry++;delay_us(1);} delay_us(40);if(DHT11_DQ_IN)return 1;else return 0; }
15 / 68
u8 DHT11_Read_Byte(void)
{ u8 i,dat; dat=0;for (i=0;i<8;i++) {dat<<=1; dat|=DHT11_Read_Bit();} return dat;}
u8 DHT11_Read_Data(u8 *temp,u8 *humi)
{ u8 buf[5];u8 i;DHT11_Rst();if(DHT11_Check()==0) {for(i=0;i<5;i++){buf[i]=DHT11_Read_Byte(); if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4]){
*humi=buf[0];*temp=buf[2];}}else return 1; return 0;} 4.2.3 烟雾传感模块 传感器采用两种数是数字量DO的采集判是模拟量输出AO检测况,以及判断该浓度对
详细电路设计如下
图4-6 烟雾传感电路设计图
据采集方法,一种断有无气体,一种气体的浓度状态情人体是否有害。 图4-6所示:
烟雾传感数据采集程序:
u16 Get_Adc(u8 ch)
{ ADC_RegularChannelConfig(ADC1, ch, ADC_SampleTime_239Cycles5 );
ADC_SoftwareStartConvCmd(ADC1, ENABLE); while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC )); return ADC_GetConversionValue(ADC1); } u16 Get_Adc_Average(u8 ch,u8 times) {u32 temp_val=0;u8 t;
16 / 68
1,
for(t=0;t adcx=Get_Adc_Average(ADC_Channel_1,10); if(!adcx1){adcx1=adcx;} longdu=(adcx-adcx1)*100/256; printf(\"\\r\\n您发送的消息为:浓度:%d\\r\\n\\r\\n\ 4.2.4 液晶显示电路设计 本系统液晶显示采用LCM12864液晶作为显示器。显示相关的提示信息和数据的输出。该液晶模块支持串行通信和并口通信。串行通信为单根数据线,通信速率低于并口通信,占用端口少。并口通信通信速率块但是占用端口多。为了节约IO口采用串行方式设计电路 电路图设计如图4-7下: 图4-7 液晶显示电路设计图 液晶初始化程序: void SendByte(unsigned char dat) {unsigned char i;CLK_L; for(i=0;i<8;i++){if(dat&0x80) {SID_H;}else {SID_L;} CLK_L;delay(10);CLK_H;dat=dat<<1;}CLK_L;} void WriteCommandLCD(unsigned char dat,unsigned char tt) { CS_H;delay(10);CLK_L;delay(10); SendByte(0xF8);//11111,00,0 RW=0,RS=0 同步标志 delay(10);SendByte(dat&0xF0);//高四位 SendByte((dat&0x0F)<<4);//低四位 17 / 68 delay_ms(1);CS_L;} void WriteDataLCD(unsigned char dat) {CS_H;delay(10)CLK_L;delay(10);SendByte(0xFA);//11111,01,0 RW=0,RS=1 delay(10);SendByte(dat&0xF0);//高四位 delay(10); SendByte((dat&0x0F)<<4);//低四位delay_ms(1);CS_L;} void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData){ CS_H; if(Y<1) Y=1; if(Y>4) Y=4; X &= 0x0F; switch(Y){ case 1:X|=0X80;break; case 2:X|=0X90;break; case 3:X|=0X88;break; case 4:X|=0X98;break;} WriteCommandLCD(X, 0); WriteDataLCD(DData); delay(100); CS_L;} void SET_ADDR(unsigned char X, unsigned char Y){ CS_H; if(Y<1) Y=1;if(Y>4)Y=4; X &= 0x0F; switch(Y){ case 1:X|=0X80;break; case 2:X|=0X90;break; case 3:X|=0X88;break; case 4:X|=0X98;break;} WriteCommandLCD(X, 0); delay(100);CS_L;} void SET_ADDR1(unsigned char X, unsigned char Y){ CS_H; if(Y<1)Y=1;if(Y>4)Y=4;X &= 0x0F; //限制X不能大于16,Y不能大于1 switch(Y){ case 1:X|=0X80;break; case 2:X|=0X90;break; case 3:X|=0X88;break; case 4:X|=0X98;break;} WriteCommandLCD(X, 0); delay(100); CS_L;} void LCDInit(void) //LCM初始化{ CS_H;delay_ms(100);CLK_L; WriteCommandLCD(0x30,1); //显示模式设置,开始要求每次检测忙信号 WriteCommandLCD(0x02,1); WriteCommandLCD(0x06,1); // 显示光标移动设置 WriteCommandLCD(0x0C,1); // 显示开及光标设置 WriteCommandLCD(0x01,1); //显示清屏 WriteCommandLCD(0x80,1); //显示清屏CS_L;} void LCDClear(void) //清屏 {CS_H;CLK_L; 18 / 68 WriteCommandLCD(0x01,1); //显示清屏 WriteCommandLCD(0x34,1); // 显示光标移动设置 WriteCommandLCD(0x30,1); // 显示开及光标设置 CS_L;}void Line_white(){CS_H; WriteCommandLCD(0x16,1); WriteCommandLCD(0x17,1); CS_L;} void SendCMD(unsigned char dat) {CS_H;CLK_L;SendByte(0xF8);//11111,00,0 RW=0,RS=0 同步标志 SendByte(dat&0xF0);//高四位SendByte((dat&0x0F)<<4);//低四位 CS_L;delay_ms(1);} void SendDat(unsigned char dat) {CS_H;CLK_L; SendByte(0xFA);//11111,01,0 RW=0,RS=1 SendByte(dat&0xF0);//高四位 SendByte((dat&0x0F)<<4);//低四位 CS_L;} void initlcm(void) {CS_L;delay_ms(100);SendCMD(0x30);SendCMD(0x0C);SendCMD(0x01); SendCMD(0x02);SendCMD(0x80);SendCMD(0x04);} void display(unsigned char x_add,unsigned char *ptr) {SendCMD(x_add);while(*ptr != '\\0'){SendDat(*ptr);++ptr;}} void lcd_num(unsigned char *ptr,u8 size) {while(size--){SendDat(*ptr);++ptr;}} 4.2.5 报警电路的设计 本系统主要以灯光提示为主。电路主要采用发光二极管以及保护电阻组成,达到对流过发光二极管进行限流保护。如图4-8所示: 图4-8 灯光报警电路设计图 19 / 68 4.2.6 时钟模块 时钟模块利用了DALLAS 公司推出的涓流充电时钟芯片DS1302,另外设计了纽扣电池连接到DS1302 的VCC2 备用电源引脚上。对于该芯片的供电DALLAS 公司设计了如下约定:5V电为电源电压,还有自己的备份电源。当备份电源等于电源电压加上2V,由备份电源供电,备份电源小于电源电压时,有电源自己供电。这也就是系统掉电的情况下DS1302的时钟还不会出现差错的且恢复电时正常工作的原因。 表4-1 DS1302有关的日历与时间的寄存器: 读寄存器 81h 83h 85h 87h 89h 8Bh 8Dh 8Fh 写寄存器 80h 82h 84h 86h 88h 8Ah 8Ch 8Eh WP BIT7 CH 12/24 0 0 0 0 0 0 0 10年 0 0 0 0 0 BIT6 BIT5 10 AM/PM 时 BIT4 BIT3 BIT2 BIT1 秒 分 时 日 月 0 年 0 0 周 BIT0 范围 00-59 00-59 1-12/ 0-23 1-31 1-12 1-7 00-99 - 10日 0 0 10月 0 这张表介绍了DS1302与时间日期有关的7个寄存器,我们需要做的就只是把相应的时间和日期写入到这几个寄存器中,然后不断的读取这几个寄存器里面的数值就能得到我们所需要的时间和日期。这几个寄存器介绍如下: 1. 秒寄存器(81h、80h)的第7位是时钟暂停标志(CH)。初始值为1, DS1302此时处于低功耗状态,时钟振荡器处于停止状态;只有将秒寄存器的该位置改为0时,时钟才能开始运行。 2. 小时寄存器(85h、84h)的第6位是DS1302的运行模式;分为12小时模式和24小时模式。当将其置高时,为12小时模式,反之为24小时模式。 3. 控制寄存器(8Fh、8Eh),当将写保护位设置为1时,程序员是不能对任何一个寄存器其中的数值进行修改的,正常情况下,设置为0,其他的7位也都设置为0的第7位是写保护位(WP),将其它7位均置为0。,只有将WP设为0时才可以DS1302单字节读写时序如图4-9所示: 20 / 68 图4-9 DS1302单字节读写时序图 21 / 68 具体电路设计如图4-10所示: 图4-10 DS1302设计电路 4.3 业务处理模块设计 4.3.1 界面显示任务 开始 显示窗口 数据 否 否 是 温湿度检测 过标检测 报警 数据 是 模 烟雾浓度检 过标检测 块 测 数据 否 光照数据检测 过标检测 灯光控制 图4-11 显示界面流程图 22 / 68 4.3.2 AD采样及数据处理 在该智能家居系统里分别用到了自带的ADC和芯片ADC0809,下面我们对他们分别进行简单说明。 表4-2 ADC引脚和输入通道关系 ADC1 ADC2 ADC3 通道0 通道1 通道2 通道3 通道4 通道5 通道6 通道7 通道8 通道9 通道10 通道11 通道12 通道13 通道14 通道15 通道16 通道17 本次采用通道10即PC0引脚输入。 1. 新建工程将其命名为.c文件,添加串口通信的头文件。 2. 串口已经配置完毕,不需要在配置,只要配置好普通的I/O口即可。 PA0 PA1 PA2 PA3 PA4 PA5 PA6 PA7 PB0 PB1 PC0 PC1 PC2 PC3 PC4 PC5 温度传感器 内部参照电压 PA0 PA1 PA2 PA3 PA4 PA5 PA6 PA7 PB0 PB1 PC0 PC1 PC2 PC3 PC4 PC5 PA0 PA1 PA2 PA3 PF6 PF7 PF8 PF9 PF10 PC0 PC1 PC2 PC3 23 / 68 24 / 68 4. 首先要在主函数中调用两个函数初始化,接着调用串口初始化。 5. 每间隔一秒打刷新一次数据。 25 / 68 开始 ADC初始化 启动ADC采样 读取通道0 转换结果 处理数据 N 转换结束 Y 一次读取其他通道的数据 数据处理 液晶显示 图4-12 ADC采样流程图 26 / 68 ADC0809的主要特征,这里简单介绍一下DMA 的主要特性 1. 12 个单独的可配置的信息通道,分为DMA1和DMA2,前者含有7个通道后者有5个传递信息的通道; 2. 每个通道都支持软件触发,每个通道都直接连接专用的硬件DMA 请求。这 些功能通过软件来配置; 3. 因为有的数据是后续计算机前提,所以说数据传送也是有优先级的,优先级是通过编程来实现的,分别为很高,高,中等和地四个级别,当然也可以通过软件进行设置。 4. 源和目标数据区的传输宽度是独立的,相似于打包和拆包的过程。源和目标地址必须按数据传输宽度对齐; 5. 存储器之间数据信息的传输; 下面是配置DMA 通道x 的过程(x 代表通道号): 1. 在DMA_CPARx 寄存器中配置外设寄存器的地址。当外部设备请求传输数据时,数据或者代码会传送到这里。 2. 在DMA_CMARx 寄存器中设置数据存储器的地址。当外部设备请求数据传输时,数据将会从这个地址读出来或者写进来。 3. 在DMA_CNDTRx 寄存器中设置传输的数据值。每传送一条消息或数据数值减一当数据减到零结束传输数据 4. 在DMA_CCRx 寄存器的PL中设置传递信息通道的优先级; 5. 在DMA_CCRx 寄存器中设置数据信息传输的方向、循环模式和存储器的 增量模式、外部设备和存储器的数据宽度。 程序中的DMA 配置代码如下: 27 / 68 为了提高采集数据的稳定性以及可靠性,采用了多次采集然后再求平均值,这 样得到的数据将会更加的可靠准确!计算平均值的程序如下: 4.3.3 烟雾传感器 烟雾传感器就是一种感知烟雾浓度的电子器件,技术先进,工作稳定可靠,常常被安放在大型商场或者各种消防报警系统里,本次设计中使用的是性能优秀的离子式烟雾传感器,它相较与传统的以气敏电阻为核心的传感器工作稳定性更高,串行接收和发送数据,外围电路更加简单,体积小,不占用空间,耗能低,长时间使用不会造成较大的功耗。 表4-3烟雾传感器标准工作条件 符号 Vc VH RL RH PH 参数名称 回路电压 加热电压 负载电阻 加热电阻 加热功耗 技术条件 ≤15V 5.0±0.2V 可调 31Ω±3Ω ≤900mW 备注 AC or DC AC or DC 室温 28 / 68 表4-4 烟雾传感器环境条件 符号 Tao Tas RH 02 表4-5 烟雾传感器灵敏度特性 参数名称 使用温度 储存温度 相对湿度 氧气浓度 技术条件 -10℃-50℃ -20℃-70℃ 小于 95%RH 21% 标准条件最小值 备注 符号 RS α(3000/1000)异丁烷 参数名称 敏感体表面电阻 浓度斜率 技术参数 备注 3KΩ-30KΩ探测浓度范围(1000ppm 异丁100ppm-10000ppm烷) 液化气和丙烷 300ppm-5000ppm 丁烷 5000ppm-20000ppm 甲烷 ≤0.6 300ppm-5000ppm 氢气 100ppm-2000ppm 酒精 标准工作条件 温度:20℃±2℃ VC: 5.0V±0.1V 相对湿度:65%±5% Vh:5.0V±0.1V 不超过 1小时 预热时间 29 / 68 开始 初始化 采集烟雾数值 无线传输 读取数据 Y 烟雾浓度异常 N 显示 结束 图4-13 烟雾传感器工作流程图 报警 4.3.4 温湿度传感器 DHT11温湿度传感器由数字采集模块和温湿度传感模块两部分组成,因其 现有的结构稳定再带校准数字信号技术,从而使其具有极高的稳定性。传感器部分包括一个感湿元件和一个测温器件,外加与单片机相连,抗干扰能力强,响应快,综合而言性价比非常高。DHT11采用4针单排封装,外电路简单,连接方便,而他的体积小巧,功耗低则使它更加适合现在的智能家居乐,不占用空间,长时间使用不会造成大量的功耗。 DHT11通信过程,总线处于高电平时,总线发出等待接收信号指令,拉低电平,等待DHT11响应,当低电平持续时间大于18us后,满足DHT11接收到信号的时间长度,DHT11开始接收主机的信号,当接收到主机开始信号后,发送80us低电平响应信号,主机发送开始信号后,等待大约30us后,读取DHT11 30 / 68 反馈回来的信号,主机发送开始信号后,便可以切换到输入模式,也就是输出高电平,总线再由外界上拉电阻拉高电平。 图4-14 温湿度感器工作时序图 起始阶段总线为低电平,DHT11先发送一个请求响应信号,随后总线会将总线拉高80us作为响应应答,此时,DHT11开始准备发送数据,每一个bit发送响应信号都在50us低电平时隙,如果读到的信号为高电平,则DHT11不会响应,此时应该检查一下电路是否正确,当所有数据都发送完毕后,DHT11总 线会拉低50us,随后总线上拉电阻进入空闲状态,等待下一次信号的来临。 开始 主机拉低延时18us 总线上拉阻拉高主机延时40us N 从机是否响应信号 Y Y 从机发出 80us 低电平 从机发出80us高电平 读出数据 数据检验 结束 31 / 68 图4-15 温湿度传感器读取数据流程图 4.4.5 灯光控制与光照检测 1、光照检测部分: 光敏电阻又称光敏电阻器或光导管,常见的材质为硫、硒、铋和铝。因为采用这种材质所以导致光敏电阻对阳光有特别的敏感度,当有光照射时,光敏电阻的阻止会急剧减小,这是因为太阳照射产生的载流子参与了导电,,在外电场的作用下做运动,电子向正极运动,空穴向电源负极运动。从而使光敏电阻器的阻值迅速下降。 2、光敏电阻的工作原理: 光敏电阻的工作原理是基于内光电效应。当入射光线减弱时,由光电子激发产生的电子合空穴进行复合,从而电阻变大,使电路中电流减小,一般可以达到1M欧姆以上,而当电阻在光线慢慢变强的时候,电阻就会慢慢减小,电流变大,它有一个计算光线和电阻大小的公式,I=KUaLb,式子中大I通过电路中的电流大小,大U为电路中的电压大小,大L为光敏电阻所受的光线强弱,K为比例系数,通过电压和电流既可以计算出电阻的阻值,从而可以知道当没有光线的时候,光敏电阻的阻值为最大值,当受到光照的时候,电阻会一点点的减小,即光照愈强,阻值愈低。入射光消失后,由光子激发产生的电子—空穴对将复合,光敏电阻的阻值达到恢复原值。在光敏电阻金属电的两端极加上电压,形成闭合回路,有电流通过后,受到不同波长的光线照射时,电流的大小就会随光照的增强的而变大,从而实现光电转换的需求。光敏电阻没有极性,不像二极管单向导通,使用很方便,只要两端的电压和通过的电流不要超过太大,都不会对光敏电阻产生破坏,稳定性较强。 32 / 68 开始 系统初始 光线是否充 有无人体红外 输出亮灯信号 延时调整 N 信号延时时间 Y 图4-16 光敏电阻工作流程图 输出没等信号 输出信号保持 延时时间调整 输出灭灯信号 33 / 68 3、灯光控制部分: 在灯光控制部分比较主要的是继电器的工作原理和使用方法,继电器其实就是一个较复杂的开关,常见的继电器有五个引脚,其中的两个引脚用来和电源的正负极接通,作为外设的工作电压,另外三个引脚组成一个单刀双掷开关,与控制模块相连接,其工作原理是,通电线圈产生磁吸引力,致使继电器吸合达到电控继电器的效果。如下图所示为继电器电路的原理图 图4-17 继电器工作电路 如图4-17采用继电器控制两个外接接口的通断达到控制灯光的目的,设计中采用三极管进行隔离单片机控制RS1可以控制三极管导通达到控制继电器的常开接口与常闭接口。 34 / 68 35 / 68 第5章 结果分析 5.1 硬件设计的结果分析 5.1.1 温湿度模块的分析 温湿度模块采用目前市场上精度较高的DHT11传感器,该传感器采集精度高,抗干扰能力强。适合应用于很多环境温度复杂的情况下进行数据采集,并且能够保证其精度。 通过对硬件模块的设计以及软件程序的设计,采用数据校验的算法以及温度补偿可以是传感器数据的小数位数达到小数后八位,根据系统的精度要求,选取小数后四位的数据作为准确数据输出。同时也达到了数据重复性位千分之二。 图5-1 温湿度数据采集 5.1.2 光照模块的分析 光照模块采用GY-30高精度的光照传感器输出能达到1LX,为了降低难度系统选取精度为5LX所以该传感器完全满足要求,雨量传感器采用电阻式传感器,并且配备24Bit AD(±20mv)进行数据量采集。所以也可以实现高精度的采集。 一般的台灯发光强度1000-1200-1400MCD的亮度根据光强坎德拉(CD)和光通量(LM),光通量LM与光照度的关系LX理论的光照度为3140LX~4396LX即 1 CD = 1000 MCD= 1LM/SR(立体角); 36 / 68 理论上1LX=1LM(流明)均匀分布在1m2表面上的光照度; 1 MCD/SR(Beam Angle = 120 Degree) = 3.14LM; 实际应用在,通过对光照的采集实际精度达到3LX完全满足5LX的精度要求。雨量部分采集能达到小数后5位数据,完全满足小数后两位的要求如图4-2。 图5-2 光照数据图 5.1.3 烟雾检测 为了避免单一的火光传感器产生的数据错误,对火光传感器采用多点数据采集并且确认的方式进行火光采集,软件界面如图5-3。 图5-3 烟雾检测图 37 / 68 5.1.4 硬件综合测试 主要以单一功能进行组合测试,判断系统是否能够实时响应数据后进行操作。要求对温湿度的数据实时采集,同时对其它的操作应能及时的响应。例如进入温湿度实时采集后,应该对火光模块实时监测,当发生意外时能够及时反映,不能在单一功能执行时屏蔽其它功能模块的工作。这是本系统综合测试的指导思想。 在该指导思想下,设计出测试方法,第一部分是报警的测试,第二部分是单一功能中兼容报警的测试。第三部分完整的系统运行测试。 5.2 软件设计的结果分析 表4-1 黑盒测试 输入等价类 控制输入 数据输出 有效等价类 ⑴指令开始E1 ⑵指令结尾EE ⑶24位二进制 ⑻输出开始CD ⑼输出结尾ED ⑽24位二进制 无效等价类 ⑷指令开始不为E1⑸指令结尾不为EE ⑹小于24位二进制⑺大于24位二进制 ⑾输出开始不为CD⑿输出结尾不为ED⒀小于24位二进制 ⒁大于24位二进制 1) 设计测试用例,以便覆盖所有的有效等价类在表中列出的有效等价类 有效等价类 ⑴⑵⑶ ⑻⑼⑽ 测试数据 覆盖的有效等价类 期望结果 E101EE ⑴⑵⑶ 输入有效 CD01ED ⑻⑼⑽ 输入有效 2) 为每一个无效等价类设计一个测试用例, 测试数据 期望结果 覆盖的无效等价类 sdsd 输入无效 ⑷ E1sdcd 输入无效 ⑸ E121 输入无效 ⑹ E121312A 输入无效 ⑺ Ewasdw 输入无效 ⑾ E1asdw 输入无效 ⑿ 38 / 68 E1 输入无效 ⒀ 输入无效 ⒁ E1sdasd 39 / 68 结 论 该智能家居系统采用了STM32F103VCT6单片机,移植了μC/OS-II操作系统实现了一个气体检测与报警系统,与传统的气体检测仪器相比,本设计具有操作简单,可以显示变化趋势,运行可靠等特点,检测气体浓度主要通过片内的12位的A/D转换通道与外部传感器进行连接,获得的是标准的电压信号(有的传感器是上行,有的传感器是下行信号)。然后通过程序中设置0或者1来决定程序的上下行,这样做就使本仪器具有很大的通用性,只要连接不同的传感器然后设置一下上下行就可以采集到不同的数据源的数据,做到了系统与数据源的无关性。 STM32F103VCT6具有较大的存储空间。可以将传感器采集到的信息存储在闪存中,方便程序员通过电脑调取,分析,处理数据,在这个空间中给不同的任务分配不同的优先级,这样系统就可以有条不紊的执行各项操作。 在实现的过程中,首先要完成的是工作电路的设计,接下来就是程序流程图的设计和任务分配的设计。再实现的是μC/OS-II操作系统的移植,在进行任务优先级分配和数据处理,最后进行调试。 通过对本次手持气体检测仪的研究,使我对STM32单片机的原理结构,基础时钟、定时器、中断服务、ADC模块、USART模块有了深刻的理解,同时也对μC/OS-II操作系统的多任务处理机制有了一定的理解。 从专业的角度来看该产品的自动升级,存储能力和抗干扰能力方面还有很多待改进和优化的地方,希望以后专业知识的学习能进一步改进该设备,以满足实际工业和使用人员的需求。 40 / 68 致 谢 毕业设计的整个过程中,我得到了范忠诚老师的全力帮助。在智能家居系统设计之初,我并没有完整的设计思路,在老师热心的帮助下,我开始从不知道到了解逐步过度,最终理清了整个系统的设计思路,并在硬件电路上给予了我很大的帮助。在编程设计过程中,范老师教给了我最基本的编程设计方法,从而顺利完成了各个模块的设计,整个过程都有范老师给我及时的帮助,从而才有我顺利的做完整这次的毕业设计。所以在此我要真诚的对范老师说声:老师,谢谢你! 41 / 68 参考文献 [1] STMicroelectronics NV.32 位基于ARM 微控制器STM32F101xx 与 STM32F103xx固件函数库[Z].2007-10. [2] 文先仕.基于ARM Cortex-M3 的智能监控器的设计[D]. 2010. [3] STMicroelectronics NV.STM32 产品宣传册[Z].2007-06. [4] ATMEL.2-wire Serial EEPROM 1M (131,072 x 8)[Z].2003-03. [5] 南京沁恒电子有限公司.U 盘和SD 卡文件管理控制芯片 CH376[Z].2005-07. [6] DALLAS.DS1302 Trickle Charge Timekeeping Chip[Z].2007-09. [7] STMicroelectronics NV.NAND_FLAHS_ECC 校验原理与实现[Z].2005-06. [8] 开源电子网.ADC 时钟校准问题[Z].2011-07. [9] 开源电子网.STM32 多通道ADC 规则转换实现[Z].2011-01. [10] STMicroelectronics NV.通用串行总线(USB) 2.0[Z].2010-07. [11] 周立功.ARM 微控制器基础与实践(第2 版)[M].2003. [12] 江俊辉.基于ARM 的嵌入式系统硬件设计[J].微计算机信息,2005. [13] 刘丁,毛德柱.USB 在数据采集系统中的应用[J].电子技术应用,2000. [14] 戴向华.USB 原理及其在数据采集系统中的应用[J].计算机工程与设计, 2004. [15] 姚锡林.24 系列串行EEPROM 的正确选用[J].电子技术(上海),1998. [16] 姚亚峰,陈建文.嵌入式系统中EEPROM 接口及控制电路设计[J].集成电 路设计与开发,2007. [17] 虞日跃.RS-485 总线的理论与实践[J].电子技术应用,2001. [18] 朱志伟,周志光.RS-485 总线通信系统的可靠性措施[J].单片机与嵌入式 系统应用,2006. [19] 邓素萍.串行通信RS232/RS485 转换器[J].国外电子元器件,2001. 42 / 68 43 / 68 附 录 #include \"led.h\" #include \"delay.h\" #include \"key.h\" #include \"sys.h\" #include \"usart.h\" #include \"adc.h\" //ALIENTEK战舰STM32开发板实验4 //串口实验 //技术支持:www.openedv.com //广州市星翼电子科技有限公司 void MQ_Init(void) //IO初始化 { GPIO_InitTypeDef GPIO_InitStructure; //初始化KEY0-->GPIOA.13,KEY1-->GPIOA.15 上拉输入 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE);//使能PORTA,PORTE时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;//PE2~4 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入 GPIO_Init(GPIOD, &GPIO_InitStructure);//初始化GPIOE2,3,4 } int main(void) { u8 t; u8 len; u16 times=0; u8 temperature; u8 humidity; u16 adcx; u16 adcx1=0; float longdu; delay_init(); //延时函数初始化 NVIC_Configuration(); //设置NVIC中断分组2:2位抢占优先级,2位响 44 / 68 应优先级 uart_init(9600); //串口初始化为9600 Adc_Init(); //ADC初始化 //LED_Init(); //LED端口初始化 //KEY_Init(); //初始化与按键连接的硬件接口 while(DHT11_Init()) //DHT11初始化 { //LCD_ShowString(60,130,200,16,16,\"DHT11 Error\"); printf(\"ERROR OK\"); delay_ms(200); //LCD_Fill(60,130,239,130+16,WHITE); //delay_ms(200); } printf(\"DHT11 OK\"); while(1) { DHT11_Read_Data(&temperature,&humidity); printf(\"\\r\\n您发送的消息RH:%d\\r\\n\\r\\n\ delay_ms(500); //读取温湿度值 为:TEMP:%d if(GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_15)==1) { delay_ms(10); if(GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_15)==1) { printf(\"\\r\\n您发送的消息为:烟雾触发\\r\\n\\r\\n\ while(1); } } adcx=Get_Adc_Average(ADC_Channel_1,10); if(!adcx1) { adcx1=adcx; } longdu=(adcx-adcx1)*100/256; printf(\"\\r\\n您发送的消息为:浓度:%d\\r\\n\\r\\n\ 45 / 68 } } //ADC头文件 #ifndef __ADC_H #define __ADC_H #include \"sys.h\" #include \"stm32f10x_adc.h\" //本程序只供学习使用,未经作者许可,不得用于其它任何用途 //ALIENTEK战舰STM32开发板 //ADC 代码 //正点原子@ALIENTEK //技术论坛:www.openedv.com //修改日期:2012/9/7 //版本:V1.0 //版权所有,盗版必究。 //Copyright(C) 广州市星翼电子科技有限公司 2009-2019 //All rights reserved ////////////////////////////////////////////////////////////////////////////////// void Adc_Init(void); u16 Get_Adc(u8 ch); u16 Get_Adc_Average(u8 ch,u8 times); #endif #include \"adc.h\" #include \"delay.h\" #include \"sys.h\" ////////////////////////////////////////////////////////////////////////////////// //本程序只供学习使用,未经作者许可,不得用于其它任何用途 //ALIENTEK战舰STM32开发板 //ADC 代码 //正点原子@ALIENTEK //技术论坛:www.openedv.com //修改日期:2012/9/7 //版本:V1.0 //版权所有,盗版必究。 46 / 68 //Copyright(C) 广州市星翼电子科技有限公司 2009-2019 //All rights reserved ////////////////////////////////////////////////////////////////////////////////// //初始化ADC //这里我们仅以规则通道为例 //我们默认将开启通道0~3 void Adc_Init(void) { ADC_InitTypeDef ADC_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1 , ENABLE ); //使能ADC1通道时钟 RCC_ADCCLKConfig(RCC_PCLK2_Div6); //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M //PA1 作为模拟通道输入引脚 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入引脚 GPIO_Init(GPIOA, &GPIO_InitStructure); ADC_DeInit(ADC1); //复位ADC1,将外设 ADC1 的全部寄存器重设为缺省值 ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC工作模式:ADC1和ADC2工作在独立模式 ADC_InitStructure.ADC_ScanConvMode = DISABLE; //模数转换工作在单通道模式 ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //模数转换工作在单次转换模式 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //转换由软件而不是外部触发启动 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC数据右 47 / 68 对齐 ADC_InitStructure.ADC_NbrOfChannel = 1; //顺序进行规则转换的ADC通道的数目 ADC_Init(ADC1, &ADC_InitStructure); //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器 ADC_Cmd(ADC1, ENABLE); //使能指定的ADC1 ADC_ResetCalibration(ADC1); //使能复位校准 while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位校准结束 ADC_StartCalibration(ADC1); //开启AD校准 while(ADC_GetCalibrationStatus(ADC1)); //等待校准结束 // ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能 } //获得ADC值 //ch:通道值 0~3 u16 Get_Adc(u8 ch) { //设置指定ADC的规则组通道,一个序列,采样时间 ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 ); //ADC1,ADC通道,采样时间为239.5周期 ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能 while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束 return ADC_GetConversionValue(ADC1); //返回最近一次ADC1规则组的转换结果 } 48 / 68 u16 Get_Adc_Average(u8 ch,u8 times) { } u32 temp_val=0; u8 t; for(t=0;t //DTH11部分 #ifndef __DHT11_H #define __DHT11_H #include \"sys.h\" ////////////////////////////////////////////////////////////////////////////////// //本程序只供学习使用,未经作者许可,不得用于其它任何用途 //ALIENTEK战舰STM32开发板 //DHT11数字温湿度传感器驱动代码 //正点原子@ALIENTEK //技术论坛:www.openedv.com //修改日期:2012/9/12 //版本:V1.0 //版权所有,盗版必究。 //Copyright(C) 广州市星翼电子科技有限公司 2009-2019 //All rights reserved ////////////////////////////////////////////////////////////////////////////////// //IO方向设置 #define DHT11_IO_IN() {GPIOG->CRH&=0XFFFF0FFF;GPIOG->CRH|=8<<12;} #define DHT11_IO_OUT() {GPIOG->CRH&=0XFFFF0FFF;GPIOG->CRH|=3<<12;} ////IO操作函数 #define DHT11_DQ_OUT PGout(11) //数据端口 PA0 #define DHT11_DQ_IN PGin(11) //数据端口 PA0 49 / 68 u8 DHT11_Init(void);//初始化DHT11 u8 DHT11_Read_Data(u8 *temp,u8 *humi);//读取温湿度 u8 DHT11_Read_Byte(void);//读出一个字节 u8 DHT11_Read_Bit(void);//读出一个位 u8 DHT11_Check(void);//检测是否存在DHT11 void DHT11_Rst(void);//复位DHT11 #endif #include \"dht11.h\" #include \"delay.h\" ////////////////////////////////////////////////////////////////////////////////// //本程序只供学习使用,未经作者许可,不得用于其它任何用途 //ALIENTEK战舰STM32开发板 //DHT11数字温湿度传感器驱动代码 //正点原子@ALIENTEK //技术论坛:www.openedv.com //修改日期:2012/9/12 //版本:V1.0 //版权所有,盗版必究。 //Copyright(C) 广州市星翼电子科技有限公司 2009-2019 //All rights reserved ////////////////////////////////////////////////////////////////////////////////// //复位DHT11 void DHT11_Rst(void) { DHT11_IO_OUT(); //SET OUTPUT DHT11_DQ_OUT=0; //拉低DQ delay_ms(20); //拉低至少18ms DHT11_DQ_OUT=1; //DQ=1 delay_us(30); //主机拉高20~40us } //等待DHT11的回应 //返回1:未检测到DHT11的存在 50 / 68 //返回0:存在 u8 DHT11_Check(void) { u8 retry=0; DHT11_IO_IN();//SET INPUT while (DHT11_DQ_IN&&retry<100)//DHT11会拉低40~80us { retry++; delay_us(1); }; if(retry>=100)return 1; else retry=0; while (!DHT11_DQ_IN&&retry<100)//DHT11拉低后会再次拉高40~80us { retry++; delay_us(1); }; if(retry>=100)return 1; return 0; } //从DHT11读取一个位 //返回值:1/0 u8 DHT11_Read_Bit(void) { u8 retry=0; while(DHT11_DQ_IN&&retry<100)//等待变为低电平 { retry++; delay_us(1); } retry=0; while(!DHT11_DQ_IN&&retry<100)//等待变高电平 { retry++; delay_us(1); } delay_us(40);//等待40us if(DHT11_DQ_IN)return 1; 51 / 68 else return 0; } //从DHT11读取一个字节 //返回值:读到的数据 u8 DHT11_Read_Byte(void) { u8 i,dat; dat=0; for (i=0;i<8;i++) { dat<<=1; dat|=DHT11_Read_Bit(); } return dat; } //从DHT11读取一次数据 //temp:温度值(范围:0~50°) //humi:湿度值(范围:20%~90%) //返回值:0,正常;1,读取失败 u8 DHT11_Read_Data(u8 *temp,u8 *humi) { } u8 buf[5]; u8 i; DHT11_Rst(); if(DHT11_Check()==0) { for(i=0;i<5;i++)//读取40位数据 { buf[i]=DHT11_Read_Byte(); } if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4]) { *humi=buf[0]; *temp=buf[2]; } }else return 1; return 0; 52 / 68 //初始化DHT11的IO口 DQ 同时检测DHT11的存在 //返回1:不存在 //返回0:存在 u8 DHT11_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG, ENABLE); //使能PG端口时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; //PG11端口配置 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOG, &GPIO_InitStructure); //初始化IO口 GPIO_SetBits(GPIOG,GPIO_Pin_11); //PG11 输出高 DHT11_Rst(); //复位DHT11 return DHT11_Check();//等待DHT11的回应 } //KEY部分 #include \"dht11.h\" #include \"delay.h\" ////////////////////////////////////////////////////////////////////////////////// //本程序只供学习使用,未经作者许可,不得用于其它任何用途 //ALIENTEK战舰STM32开发板 //DHT11数字温湿度传感器驱动代码 //正点原子@ALIENTEK //技术论坛:www.openedv.com //修改日期:2012/9/12 //版本:V1.0 //版权所有,盗版必究。 //Copyright(C) 广州市星翼电子科技有限公司 2009-2019 //All rights reserved ////////////////////////////////////////////////////////////////////////////////// //复位DHT11 53 / 68 void DHT11_Rst(void) { DHT11_IO_OUT(); //SET OUTPUT DHT11_DQ_OUT=0; //拉低DQ delay_ms(20); //拉低至少18ms DHT11_DQ_OUT=1; //DQ=1 delay_us(30); //主机拉高20~40us } //等待DHT11的回应 //返回1:未检测到DHT11的存在 //返回0:存在 u8 DHT11_Check(void) { u8 retry=0; DHT11_IO_IN();//SET INPUT while (DHT11_DQ_IN&&retry<100)//DHT11会拉低40~80us { retry++; delay_us(1); }; if(retry>=100)return 1; else retry=0; while (!DHT11_DQ_IN&&retry<100)//DHT11拉低后会再次拉高40~80us { retry++; delay_us(1); }; if(retry>=100)return 1; return 0; } //从DHT11读取一个位 //返回值:1/0 u8 DHT11_Read_Bit(void) { u8 retry=0; while(DHT11_DQ_IN&&retry<100)//等待变为低电平 { retry++; 54 / 68 delay_us(1); } retry=0; while(!DHT11_DQ_IN&&retry<100)//等待变高电平 { retry++; delay_us(1); } delay_us(40);//等待40us if(DHT11_DQ_IN)return 1; else return 0; } //从DHT11读取一个字节 //返回值:读到的数据 u8 DHT11_Read_Byte(void) { u8 i,dat; dat=0; for (i=0;i<8;i++) { dat<<=1; dat|=DHT11_Read_Bit(); } return dat; } //从DHT11读取一次数据 //temp:温度值(范围:0~50°) //humi:湿度值(范围:20%~90%) //返回值:0,正常;1,读取失败 u8 DHT11_Read_Data(u8 *temp,u8 *humi) { u8 buf[5]; u8 i; DHT11_Rst(); if(DHT11_Check()==0) { for(i=0;i<5;i++)//读取40位数据 { 55 / 68 buf[i]=DHT11_Read_Byte(); } if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4]) { *humi=buf[0]; *temp=buf[2]; } }else return 1; return 0; } //初始化DHT11的IO口 DQ 同时检测DHT11的存在 //返回1:不存在 //返回0:存在 u8 DHT11_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG, ENABLE); //使能PG端口时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; //PG11端口配置 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOG, &GPIO_InitStructure); //初始化IO口 GPIO_SetBits(GPIOG,GPIO_Pin_11); //PG11 输出高 DHT11_Rst(); //复位DHT11 return DHT11_Check();//等待DHT11的回应 } #include \"key.h\" #include \"sys.h\" #include \"delay.h\" ////////////////////////////////////////////////////////////////////////////////// //本程序只供学习使用,未经作者许可,不得用于其它任何用途 //ALIENTEK战舰STM32开发板 //按键驱动代码 //正点原子@ALIENTEK 56 / 68 //技术论坛:www.openedv.com //修改日期:2012/9/3 //版本:V1.0 //版权所有,盗版必究。 //Copyright(C) 广州市星翼电子科技有限公司 2009-2019 //All rights reserved ////////////////////////////////////////////////////////////////////////////////// //按键初始化函数 void KEY_Init(void) //IO初始化 { GPIO_InitTypeDef GPIO_InitStructure; //初始化KEY0-->GPIOA.13,KEY1-->GPIOA.15 上拉输入 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE,ENABLE);//使能PORTA,PORTE时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;//PE2~4 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入 GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIOE2,3,4 //初始化 WK_UP-->GPIOA.0 下拉输入 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PA0设置成输入,默认下拉 GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.0 } //按键处理函数 //返回按键值 //mode:0,不支持连续按;1,支持连续按; //0,没有任何按键按下 //1,KEY0按下 //2,KEY1按下 //3,KEY2按下 //4,KEY3按下 WK_UP //注意此函数有响应优先级,KEY0>KEY1>KEY2>KEY3!! 57 / 68 u8 KEY_Scan(u8 mode) { static u8 key_up=1;//按键按松开标志 if(mode)key_up=1; //支持连按 if(key_up&&(KEY0==0||KEY1==0||KEY2==0||KEY3==1)) { delay_ms(10);//去抖动 key_up=0; if(KEY0==0)return 1; else if(KEY1==0)return 2; else if(KEY2==0)return 3; else if(KEY3==1)return 4; }else if(KEY0==1&&KEY1==1&&KEY2==1&&KEY3==0)key_up=1; return 0;// 无按键按下 } //LED灯部分 #ifndef __LED_H #define __LED_H #include \"sys.h\" ////////////////////////////////////////////////////////////////////////////////// //本程序只供学习使用,未经作者许可,不得用于其它任何用途 //ALIENTEK战舰STM32开发板 //LED驱动代码 //正点原子@ALIENTEK //技术论坛:www.openedv.com //修改日期:2012/9/2 //版本:V1.0 //版权所有,盗版必究。 //Copyright(C) 广州市星翼电子科技有限公司 2009-2019 //All rights reserved ////////////////////////////////////////////////////////////////////////////////// #define LED0 PBout(5)// PB5 #define LED1 PEout(5)// PE5 void LED_Init(void);//初始化 #endif 58 / 68 #include \"led.h\" ////////////////////////////////////////////////////////////////////////////////// //本程序只供学习使用,未经作者许可,不得用于其它任何用途 //ALIENTEK战舰STM32开发板 //LED驱动代码 //正点原子@ALIENTEK //技术论坛:www.openedv.com //修改日期:2012/9/2 //版本:V1.0 //版权所有,盗版必究。 //Copyright(C) 广州市星翼电子科技有限公司 2009-2019 //All rights reserved ////////////////////////////////////////////////////////////////////////////////// //初始化PB5和PE5为输出口.并使能这两个口的时钟 //LED IO初始化 void LED_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOE, ENABLE); //使能PB,PE端口时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED0-->PB.5 端口配置 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz GPIO_Init(GPIOB, &GPIO_InitStructure); 初始化GPIOB.5 GPIO_SetBits(GPIOB,GPIO_Pin_5); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; 端口配置, 推挽输出 GPIO_Init(GPIOE, &GPIO_InitStructure); 59 / 68 //根据设定参数 //PB.5 输出高 //LED1-->PE.5 //推挽输出 ,IO 口速度为50MHz GPIO_SetBits(GPIOE,GPIO_Pin_5); //PE.5 输出高 } //继电器部分 #include char table[]={\"Dian Ya Biao \char a; void delay(char x) { int i,j; for(j=0;j void write_com(unsigned char com) { RS=0; RW=0; P2=com; delay(5); E=1; delay(5); E=0; } void write_date(unsigned char date) { RS=1; RW=0; P2=date; delay(5); E=1; delay(5); //写指令; //写数据; 60 / 68 E=0; } void init() //初始化函数 { write_com (0x38); delay(5); write_com (0x38); delay(5); write_com (0x38); delay(5); write_com (0x08); delay(5); write_com (0x01); delay(5); write_com (0x06); delay(5); write_com (0x0c); delay(5); } void put_str(char j,unsigned char dat) //指针定位; { write_com(0xc0+j-1); delay(10); write_date('0'+dat); delay(10); } void put_str1(char j,unsigned char dat) //指针定位; { write_com(0xc0+j-1); delay(10); write_date(dat); delay(10); } void main() { double i; int j; int ge,shi,bai; 61 / 68 init(); cs=1; cs=0; rd=1; while(1) { for(a=0;a<13;a++) { write_com(0x80+a); write_date(table[a]); delay(5); } delay(5); wr=1; wr=0; wr=1; delay(10); rd=0; delay(5); i=P1; i=i/255; i*=5; i*=100; j=(int)i; ge=j%10; put_str(4,ge); j-=ge; shi=j/10; shi=shi%10; //write_date(shi); bai=j/100; put_str1(2,'.'); delay(5); put_str(1,bai); delay(5); rd=1; delay(5); write_com(0x80+0x40+4); 62 / 68 delay(5); write_date('V'); delay(5); } } 注:资料可能无法思考和涵盖全面,最好仔细浏览后下载使用,感谢您的关注! 63 / 68 因篇幅问题不能全部显示,请点此查看更多更全内容