摘  要

随着科技的进步和智能家居概念的普及,人们对于居住环境的智能化要求越来越高。智能灯光控制系统作为智能家居系统中的一个重要组成部分,不仅能提高居住的便捷性和舒适度,而且还能有效地节约能源,响应可持续发展的全球趋势。基于这一背景,本文设计并实现了一款基于STM32F103C8T6单片机的智能灯光控制系统,通过整合先进的传感器技术、无线通信技术和人工智能算法,实现了一套功能全面、操作简便、响应灵敏的照明控制解决方案。

系统的核心控制单元采用STM32F103C8T6单片机,以其高性能处理能力、低功耗特性和丰富的外设接口为基础,配合光线检测模块、PWM亮度调节模块、LCD显示模块、蓝牙通信模块和语音识别模块等,构建了系统的硬件平台。在软件设计方面,系统采用模块化设计理念,每个功能模块均设计有相应的软件服务程序,通过主控制程序协调各模块工作,实现了灯光的自动调节、状态显示、远程控制和语音操作等功能。

系统的实验测试表明,该智能灯光控制系统具有良好的性能稳定性和操作响应性,能够满足现代家庭照明的多样化需求。未来的研究方向将包括提高系统的互操作性,使其能够更好地与其他智能家居设备协同工作;开发更加先进的用户交互方式,如触摸屏控制和手势识别;以及引入机器学习算法,实现基于用户行为的智能灯光调控策略,进一步提升系统的智能化程度和用户满意度。

关键词:光线检测;PWM亮度调节;蓝牙通信;语音识别;用户交互

Abstract

With the advancement of technology and the popularization of the concept of smart homes, the demand for the intelligence of living environments is increasing. As a crucial component of smart home systems, intelligent lighting control systems not only enhance the convenience and comfort of living but also effectively save energy, responding to the global trend of sustainable development. Against this backdrop, this paper designs and implements an intelligent lighting control system based on the STM32F103C8T6 microcontroller, integrating advanced sensor technology, wireless communication technology, and artificial intelligence algorithms to achieve a comprehensive, user-friendly, and responsive lighting control solution.

The core control unit of the system adopts the STM32F103C8T6 microcontroller, leveraging its high-performance processing capability, low power consumption, and abundant peripheral interfaces. Combined with modules such as light detection, PWM brightness adjustment, LCD display, Bluetooth communication, and voice recognition, the hardware platform of the system is constructed. In terms of software design, the system adopts a modular design concept, with each functional module designed with corresponding software service programs. Through the coordination of the main control program, functions such as automatic light adjustment, status display, remote control, and voice operation are realized.

Experimental testing of the system demonstrates its good performance stability and operational responsiveness, capable of meeting the diversified lighting needs of modern homes. Future research directions will include enhancing the system's interoperability to better collaborate with other smart home devices, developing more advanced user interaction methods such as touchscreen control and gesture recognition, and introducing machine learning algorithms to implement intelligent lighting control strategies based on user behavior, further enhancing the system's intelligence and user satisfaction.

Keywords:Light Detection,PWM Brightness Adjustment,Bluetooth Communication,Voice Recognition,User Interaction

目  录

原创性声明 

摘  要 

Abstract 

1  绪  论 

1.1 研究背景与意义 

1.2 国外研究现状 

1.2.1国外研究现状 

1.2.2国内研究现状 2

2 智能灯控系统总设计以及相关技术介绍 3

2.1系统的总体设计 3

2.2相关技术介绍 5

2.2.1 STM32单片机 5

2.2.2光线检测技术 5

2.2.3 PWM亮度调节技术 6

2.2.4 LCD显示技术 6

2.2.5蓝牙通信技术 

2.3本章小结 7

3 智能灯光控制系统硬件设计 7

3.1硬件总体设计 7

3.2单片机的选择和介绍 8

3.2.1单片机的选择 8

3.2.2单片机的介绍 8

3.3光线检测 9

3.4 PMW灯光调节电路 10

3.5 LCD显示器模块设计 

3.6蓝牙模块设计 

3.7 LD3322语音识别模块设计 

3.8本章小结 

4 智能灯光控制系统软件设计 

4.1系统软件设计 

4.1.1软件开发环境配置 17

4.1.2软件总体框架 17

4.2光线检测模块的软件设计 18

4.3 PMW亮度调节的软件设计 20

4.4 LCD显示器模块的软件设计 20

4.5蓝牙模块的软件设计 22

4.6 LD3322语音识别模块的软件设计 24

4.7本章小结 25

5 系统测试及结果 

5.1测试 

5.2结果 26

6 总结与展望 27

6.1总结 27

6.2展望 27

参考文献 29

致谢 30

附录 31

1  绪  论

    1.  研究背景与意义

随着科技的高速发展,我们都希望在生活中可以享受科技带来的便利,而智能灯控系统是现代智能家居和智慧城市建设的重要组成部分,许多复杂的操作,都可以通过科技的手段进行简化。STM32单片机以其强大的处理能力、丰富的外设接口以及低功耗的特性,为智能灯控系统的开发提供了良好的硬件支撑。研究并开发基于STM32单片机的智能灯控系统,不仅具有实际应用价值,还具有重要的理论和技术研究意义。

在环保和节能这方面,智能灯控系统可以有效避免资源浪费,传统的照明系统常常因为遗忘而导致能源的浪费。智能灯控系统可以根据环境光线的变化自动调节灯光的亮度以及根据房间内是否有人而选择是否开关灯光,这样提高了能源的利用率,对保护环境、实现可持续发展具有重要意义。

最主要的,智能灯控系统能够提升用户的生活质量。通过智能控制系统,用户可以根据个人喜好或生活上的需求,调整灯光的亮度和色温,制造出适宜的照明环境。例如,在阅读时提供明亮的光线,在休息时则切换到柔和的光线,大大增强了居家环境的舒适度和灵活性。并且,可以让用户预先设置,适应更多的环境场景需要。

开发基于STM32单片机的智能灯控系统,对于推动电子技术、自动控制技术以及人工智能技术的发展均有着积极的作用。在设计和实现的过程中,研究者可以探索新的传感技术、无线通信技术和控制算法,促进跨学科技术的融合与创新,为其他领域的智能系统开发提供宝贵的经验和技术支持。

    1.  国内外研究现状

智能灯控系统作为智能家居和智慧城市的重要组成部分,在全球范围内都得到了广泛的研究和应用。国内外在这一领域的研究现状表现在多个方面,包括硬件设计、软件开发、控制策略及其应用实践等。

1.2.1国内研究现状

随着科学技术的革新,能够为工作、学习和办公提供便利的智能设备与系统正在逐渐成为工作生活的一部分,正在不断地改变着人们的沟通方式和生活方式[3]国内对智能灯控系统的研究起步稍晚,但发展迅速。近年来,随着物联网和智能制造的快速发展,以及国家对节能减排和智慧城市建设的大力支持,智能灯控系统在中国得到了快速的发展。国内许多高校、研究机构和企业都在积极开展相关技术的研究,并取得了一系列成果。这些研究不仅涉及基于STM32单片机的硬件设计和软件开发,还包括基于ZigBee、Wi-Fi等无线通信技术的控制系统设计,以及基于人工智能技术的光照调节和能耗管理策略等。

LED智能灯在中国的研究已经取得了显著的进展,主要集中在提高能效、智能控制技术和集成化设计方面。由于 LED 具有能耗低、效率高、高可控制性、显色性好等特点,被看成是替代耗能巨大的传统灯具的理想产品。[9]随着物联网和智能制造的快速发展,以及国家对节能减排和智慧城市建设的支持,智能灯控系统在国内得到了快速的发展。许多高校、研究机构和企业都在积极开展LED智能灯的硬件设计、软件开发和无线通信技术的控制系统设计等方面的研究。此外,还涉及到基于人工智能的光照调节和能耗管理策略的研究,以实现灯光系统的自动化和智能化管理。

在应用层面,国内外的智能灯控系统都趋向于多功能、高效能、用户友好和易于集成,通过集成环境传感器,智能灯控系统可以实时监测和响应环境光线的变化,自动调整室内照明,达到节能的目的。例如:根据现实需求设计了一款多功能的智能护眼台灯,该台灯通过检测距离、时间、光强自主调节达到护眼功能,并且能够进行语音识别,语音控制、语音提示提高了台灯的便捷性和智能化程度。[4]通过人体活动监测,实现灯光的智能开关控制,提高使用便捷性;通过学习用户习惯,智能调节光线以适应不同用户的需求,提高生活质量。

综上所述,无论是在国内外,智能灯控系统都展现出了强大的发展势头和广泛的应用前景。随着技术的不断进步和市场需求的不断扩大,智能灯控系统的研究和应用将持续深化,不断推动相关领域的技术创新和产业升级。

1.2.2国外研究现状

智能灯控系统的研究在国际上已经有较为成熟的发展。国外许多技术先进的国家,特别是在欧美地区,智能灯控技术的研究与应用比较广泛,涉及自动光照调节、节能管理以及用户交互体验的优化等方面。

在欧美等发达国家,智能灯控系统已集成到智能家居与智慧城市的建设中,不仅仅局限于简单的开关控制。从文献中的“voice and light prompting device is used to prompt the action of entering into garage and the exact heading direction of the wagon, namely due west.”[16]知道可以运用到语音指令和光采集功能实现智能灯控系统更便捷的与用户进行交互。研究人员与企业不断探索将传感器网络、无线通信技术和人工智能算法融入智能灯控系统中,以实现更高效的能源管理和更加个性化的照明体验。例如,飞利浦和西门子等公司在智能照明产品的开发上具有长期的技术积累,他们的产品能够通过用户的行为习惯进行学习优化,自动调节室内光环境,满足不同场景下的照明需求。

此外,国外研究者也在智能灯控系统的互操作性和标准化方面取得了一定的进展。如在美国和欧洲,智能照明系统已开始向兼容各种智能设备的方向发展,使得系统可以与其他智能家居系统无缝集成,实现更加智能化、个性化的照明解决方案。研究背景与意义

随着科技的高速发展,我们都希望在生活中可以享受科技带来的便利,而智能灯控系统是现代智能家居和智慧城市建设的重要组成部分,许多复杂的操作,都可以通过科技的手段进行简化。STM32单片机以其强大的处理能力、丰富的外设接口以及低功耗的特性,为智能灯控系统的开发提供了良好的硬件支撑。研究并开发基于STM32单片机的智能灯控系统,不仅具有实际应用价值,还具有重要的理论和技术研究意义。

在环保和节能这方面,智能灯控系统可以有效避免资源浪费,传统的照明系统常常因为遗忘而导致能源的浪费。智能灯控系统可以根据环境光线的变化自动调节灯光的亮度以及根据房间内是否有人而选择是否开关灯光,这样提高了能源的利用率,对保护环境、实现可持续发展具有重要意义。

最主要的,智能灯控系统能够提升用户的生活质量。通过智能控制系统,用户可以根据个人喜好或生活上的需求,调整灯光的亮度和色温,制造出适宜的照明环境。例如,在阅读时提供明亮的光线,在休息时则切换到柔和的光线,大大增强了居家环境的舒适度和灵活性。并且,可以让用户预先设置,适应更多的环境场景需要。

开发基于STM32单片机的智能灯控系统,对于推动电子技术、自动控制技术以及人工智能技术的发展均有着积极的作用。在设计和实现的过程中,研究者可以探索新的传感技术、无线通信技术和控制算法,促进跨学科技术的融合与创新,为其他领域的智能系统开发提供宝贵的经验和技术支持。

2 智能灯控系统总设计以及相关技术介绍

2.1系统的总体设计

(1)系统的组成

本智能灯光控制系统以STM32F103C8T6单片机为核心控制器,整合了多种模块实现灯光的智能控制。系统利用模拟数字转换(ADC)采集环境光线强度信息,同时集成了语音识别模块和PWM控制接口,实现灯光的自动调节和智能交互。

图1-1  系统框图

  1. 工作原理:

系统上电后,首先执行存储在启动文件中的汇编代码,这一步骤建立了必要的硬件和软件运行环境。随后,系统开始对连接的硬件和外部模块进行初始化,这包括设置GPIO端口的模式和速率、配置ADC参数、初始化LCD显示屏、配置PWM模块、设置串口通信以及初始化人体感应和语音识别模块。

初始化完成后,系统进入正式的工作循环,持续监控与解锁条件相关的中断信号。由于各模块有不同的中断优先级,系统将根据优先级顺序决定处理哪个模块的中断。在本系统中,如果将类似的解锁模块比作中断源,则其优先级可由环境光线强度变化、人体活动检测、语音控制信号和远程控制指令决定。

当中断事件发生时,STM32F103C8T6单片机按优先级处理中断请求。例如,如果光线强度降低到特定阈值以下,ADC模块将产生中断,单片机响应该中断,并通过PWM输出调整灯光亮度。同样地,如果语音模块LD3322检测到有效的语音指令,它将通过串口中断通知单片机,单片机将处理该中断并执行相应的灯光调节命令。

同时,人体感应模块检测到人体活动时,也会触发中断,由单片机响应并控制灯光开关。此外,如果系统包含远程控制功能,蓝牙模块接收到远程指令后,将通过串口中断通知单片机,单片机再进行相应处理。

在所有操作中,系统状态如光线强度、语音识别状态、人体感应结果和远程指令反馈都将实时显示在LCD1602显示器上,为用户提供直观的系统信息反馈。

综上所述,该智能灯光控制系统综合了环境监测、用户交互和等多项功能,通过中断驱动和优先级管理,确保了系统的高效和稳定运行。如下图所示:

图1-2  智能灯控系统工作原理图

(3)该系统的主要功能:

1、可以通过蓝牙,用APP远程控制灯光亮灭、档位以及模式。

2、显示器可以显示当前环境中光照强度、灯光档位、模式。

3、自动模式下,光敏传感器可以根据环境光线强度调节灯光开关和档位。

2.2相关技术介绍

2.2.1 STM32单片机

STM32单片机是由STMicroelectronics(意法半导体)公司生产的一系列32位微控制器,基于ARM Cortex-M内核。STM32系列涵盖了从低功耗微控制器到高性能微控制器的各种产品,以满足广泛的应用需求,如工业控制、医疗设备、消费电子产品、汽车应用等。这些单片机以其高性能、低功耗、丰富的外设集成度和灵活的配置而受到市场的青睐。

STM32单片机分为多个系列,每个系列针对不同的应用场景和性能需求。例如,STM32F系列注重性能和集成度,适合要求较高的应用;STM32L系列强调低功耗,适合电池供电的便携式设备;STM32H系列提供了更高的性能,适合复杂和要求高的应用等。

除了提供丰富的硬件资源,如ADC(模拟数字转换器)、DAC(数字模拟转换器)、定时器、通信接口(如I2C、SPI、UART等)和更多,STM32还支持多种开发环境和工具链,包括官方的STM32CubeIDE、Keil MDK-ARM、IAR Embedded Workbench等,极大地方便了开发人员的开发工作。。

2.2.2光线检测技术

光线检测技术通过监测环境中的光照强度变化,实现对设备或系统的智能控制。这项技术主要依赖于光敏元件,如光敏电阻、光敏二极管等,这些元件的电学性能会随着光照强度的变化而改变,生成能够代表光照强度的模拟信号。这些模拟信号经过模拟数字转换器(ADC)转换成数字信号后,便可由微控制器或单片机进行读取和处理,根据预设的算法进行相应的输出控制。在智能灯光控制系统中,光线检测技术使得系统能自动调整灯光的亮度,以适应环境光线的变化,不仅提高了能源使用效率,降低了能耗,还能够根据实际环境需要调节照明强度,增强用户体验。光线检测技术因其节能、环保、提升使用舒适度等优点,在智能家居、办公自动化及公共照明等领域得到了广泛应用。

2.2.3 PWM亮度调节技术

PWM(脉冲宽度调制)亮度调节技术是通过改变光源供电的脉冲宽度来控制亮度的一种方法。这种技术能够精确地控制LED灯或其他光源的亮度,同时维持光源的颜色和色温不变。PWM调节是通过快速地开关光源实现的,这个开关动作足够快,以至于人眼不易察觉到闪烁。通过调整光源开启(高电平)与关闭(低电平)的时间比例,即脉冲的占空比,可以很好的控制光源的亮度等级。占空比越高,光源接收的平均功率也就越大,亮度也就越亮;相反,占空比越低,亮度越暗。PWM亮度调节技术因其高效、能耗低、控制简单等优点,在照明、显示屏背光和各类视觉效果中得到了广泛应用。

2.2.4 LCD显示技术

液晶显示技术(LCD),是一种基于液晶材料光电特性的显示方式,液晶处于固体和液态之间的特殊物态,通过电场的控制改变液晶分子的排列状态,进而调节光线的透过率,以实现图像的显示。这种技术的显示屏由两片极化玻璃、夹着液晶材料、彩色滤光片和背光源等多层结构组成。电流通过时,液晶分子排列变化,通过精确控制电压变化在屏幕上形成细腻的图像。LCD显示技术因其体积小巧、重量轻、低能耗和减少辐射的特点,此技术已经应用于多种显示屏产品,如电视、计算机显示器、移动电话和平板电脑等。与此同时,LCD技术也在不断进步,不仅在液晶材料、显示结构优化、能效比提升等方面有所创新,也在追求更高的分辨率和更丰富的色彩表现,以满足市场对高质量显示效果的需求。

2.2.5语音识别技术

在本设计中通过集成LD3322语音识别模块,可以将用户的语音转换成可以执行的控制命令。该模块的加入不仅方便了用户与系统的交互过程,还提升了整个系统的智能化。用户不仅可以使用传统的物理开关或应用界面,还可以直接通过说话来控制灯光的开关、亮度调节及模式切换等。

LD3322模块作为一个高性能的语音识别芯片,具备了强大的声音信号处理能力和高准确率的识别效果。通过内置的数字信号处理器(DSP)对捕获到的语音信号进行分析处理,识别出用户的具体指令。得益于其高效的算法和大量的预训练数据,该模块能够准确识别各种语音指令,并且具有较好的抗噪声能力。

通过语音控制灯光,可以为用户操作系统更加灵活。特别是在一些特定场景下,如用户手脚不便、空间较暗或需要远程控制时,语音指令的优势便能显现出来。此外,这种智能控制方式还能与其他智能家居系统集成在一起,实现家居自动化。

2.2.6蓝牙通信技术

蓝牙通信技术在生活中非常常见,已经成为现代智能设备中不可或缺的一种无线通信方式,特别是在智能家居系统中的应用,让设备之间的连接和交互变得更加简便和高效。通过HC-05蓝牙模块,可以让智能灯光控制系统拥有远程控制的功能,允许用户通过各种智能设备,如手机或平板电脑等,与灯光系统进行无线通信,实现远程调节亮度、切换工作模式等操作。

HC-05蓝牙模块的应用不仅限于基本的开关控制和亮度调节,它还可以做到更复杂的操作,如设定灯光的工作时段、调节颜色温度等,为用户提供了更丰富和个性化的灯光控制功能。此外,随着物联网技术的发展,蓝牙通信技术在智能家居领域的应用将更加广泛,与其他智能设备的协同工作能力也将不断增强,为用户创造出更加智能、舒适、便捷的生活环境。

2.3本章小结

本章主要介绍了智能灯控系统的总体设计以及相关的技术。系统以STM32单片机作为核心,通过集成光线检测、人体感应、语音识别和PWM亮度调节等多种模块,实现了灯光的智能控制和用户交互。系统的工作原理是在上电初始化后,不断监控中断信号,根据中断优先级决定响应模块,以达到智能调节灯光亮度、模式切换等功能。主要功能包括蓝牙远程控制灯光、实时显示环境中的光照强度和灯光当前的状态等。在相关的技术介绍方面,包括了光线检测技术、PWM亮度调节技术、LCD显示技术、语音识别技术以及蓝牙通信技术。这些技术的应用不仅提高了系统的智能化和用户体验,也代表了当前智能家居系统的设计趋势。

3 智能灯光控制系统硬件设计

3.1硬件总体设计

该智能灯光控制系统以STM32F103C8T6微控制器为核心,围绕此中心展开了精心设计的硬件架构,整合了光敏电阻5528、LCD1602显示屏、LD3322语音识别模块和蓝牙通信模块等关键组件。光敏电阻负责监测环境光线变化,其信号通过ADC转换后由微控制器分析以调节LED灯的亮度,实现自动光线适应功能。LCD显示屏提供了直观的用户界面,显示当前的光线强度、系统模式和LED亮度等级,增强了用户交互体验。LD3322语音模块引入了语音控制能力,使用户可以通过语音命令操作系统,而蓝牙模块则支持远程控制,允许用户通过智能设备无线控制系统状态。PWM输出技术用于精确调节LED亮度,提供平滑的灯光调整。此外,系统设计了按键输入和电源管理机制,确保了操作的便捷性和系统的稳定运行。通过印刷电路板(PCB)上的精细布局,各模块之间的物理连接既稳固又确保了信号的完整性。整个系统的设计兼顾了性能、可靠性、用户友好性和成本效益,旨在提供一套多功能、高效、易用的智能灯光控制解决方案。

3.2单片机的选择和介绍

3.2.1单片机的选择

方案一,选取复杂可编程逻辑元件CPLD作为计步器的控制器,CPLD最典型的特点是接口丰富、使用简单,不仅需要的外围电路简单,而且本身编程使用硬件描述语言进行编程,更加的底层,贴近于硬件本身,可以更好的起到控制目的。此外,CPLD本身还具备资源多、体积小、稳定性高、易扩展等特点。在许多大规模的系统中常常和DSP、或者FPGA等控制器结合起来,实现整个系统的高效控制。但由于本设计系统不需要复杂的功能,对数据运行处理要求也不高。且考虑到设计的成本,此方案舍弃。  

方案二,选择ST公司的STC89C52单片机作为主控制器,STC89S52主要是低功耗、高性能器件,具有良好的存储功能。该单片机价格低,功能比较全面,  功耗小,但它是个8位存储器,不能达到实现本次设计的需求,故而因此放弃。

方案三,STM32单片机是一款超低功耗的32位器件,功能性比较丰富,模电数电集中到一个芯片上,可以较好地解决很多问题,实用性比较强。STM32F103C8T6是该系列应用较为广泛的一款控制芯片,该芯片运行在32位系统、支持精简指令集、超低功耗的混合型单片机,具有高可靠性、低功耗、易扩展、体积小、性价比高、电路简单等优势,在精密仪器上被广泛应用,以及很多智能化产品中,提高产品质量,提升经济价值,已成为众多单片机系列中一颗耀眼的新星。

最后选择方案三。

3.2.2单片机的介绍

STM32F103C8T6单片机属于STMicroelectronics(意法半导体)生产的STM32F1系列中的一款高性能微控制器。这款单片机基于ARM Cortex-M3核心,以其强大的处理能力、丰富的功能集成以及高效的能源管理而著称,广泛应用于各种嵌入式系统和智能设备中。

ARM Cortex-M3 核心是STM32F103C8T6微控制器的核心驱动,具备最高72 MHz的运行频率,以高性能的计算能力满足多样化的应用。这款微控制器提供了64KB的闪存和20KB的SRAM,能够充分满足各种复杂应用的存储要求。在电源适应性方面,它支持2.0V至3.6V的宽范围电源电压,保障了在不同电源设计需求下的灵活运用。由于低功耗的特性,使其更适合于本设计。

STM32F103C8T6微控制器的外设非常丰富,提供了包括I2C、SPI、USART/UART在内的多种通信接口,确保了它可以轻松与外部模块通信。它还配备了多达37个GPIO引脚,满足各种输入和输出的需求,以及12位的ADC和DAC,简化了模拟信号的处理过程。此外,配备的高精度定时器和通用定时器也是其适用于复杂时间控制任务的理由之一。

在开发和编程方面,STM32F103C8T6支持Keil、IAR、GCC等众多成熟的开发环境,开发者可以根据个人喜好和项目需求选择最适合的工具。同时,它也支持JTAG和SWD调试编程接口,极大地便利了程序的下载和调试过程。

在应用范围上,STM32F103C8T6由于其卓越的性能和灵活性,已被广泛应用于工业控制、医疗设备、消费电子产品以及智能家居等领域。它不仅能够应对基础的控制需求,还能够处理更为复杂的算法和任务,是设计现代智能设备的首选微控制器。

总的来说,STM32F103C8T6单片机以其卓越的性能、灵活的外设配置和高效的能源管理,为广泛的应用场景提供了强有力的支持。以上特点也使其更适合应用与本设计。

3.3光线检测

光线采集电路我们是通过光敏电阻5528进行光线采集,光敏电阻会根据不同的光线值输出不同的电阻,然后把数据通过传输给单片机,单片机通过内部AD进行模数转换,根据不同的光线值单片机在通过PWM脉冲电路进行灯光调节。

  

图3-1  光线采集电路

光敏电阻5528与一个固定电阻(R固定)组成一个分压电路,连接到STM32F103C8T6单片机的一个ADC(模拟数字转换器)输入引脚。光敏电阻的一端连接到Vcc(通常为3.3V或5V),另一端同时连接到固定电阻和ADC输入引脚。固定电阻的另一端接地。这样,光敏电阻和固定电阻之间的分压点提供一个与光照强度相关的电压信号给ADC

校准:为了允许系统根据实际应用场景调整光照强度的测量阈值,设计中加入了一个可调电位器(R调整)。这个电位器可以细微调节分压电路的电压,进而调整ADC读取的值,以适应不同环境光线的需求。通过调节电位器,用户可以根据实际光照条件微调系统的响应,如将实际光照强度从50%调整至期望的60%。

利用光敏电阻5528的这些特性,光线检测模块不仅能够实现对环境光线强度的实时监测,还能够根据监测结果自动调节系统的灯光亮度,或者提供给用户相关的环境光线信息。结合单片机的PWM脉冲电路输出,系统能够实现灯光的精细调节,满足不同环境下对光照强度的需求。

3.4 PMW灯光调节电路

脉冲宽度调制(PWM)技术是实现LED亮度精确调节的关键技术之一。PWM技术通过调整方波信号的占空比—即信号高电平状态占总周期的比例—来编码模拟信号的电平,实现对LED亮度的精细控制。在给定的时间内,通过调节信号的ON(通电)和OFF(断电)状态的时间比例,可以模拟出接近于连续变化的电压级别,从而精确控制LED的亮度。

在本设计中,PWM信号由STM32F103C8T6微处理器生成,并通过数字输出直接控制LED。为了驱动电流较大的LED或LED阵列,设计采用了外部晶体管(如8550)作为电流放大器,以及10kΩ的电阻作为上拉电阻确保电路稳定性。在这个电路中,8050晶体管用于接收微处理器输出的PWM信号,并根据该信号控制电流的通断,进而控制LED的亮度。通过调整PWM信号的占空比,即可调节流经LED的平均电流量,从而实现亮度的调节。

 图3-2  PWM脉冲调节电路

10k电阻在这里只是用作上拉(如果不接vcc电流直接就可以导通8050就无法进行控制),8550这个时候就可以正常工作,然后我们通过程序来控制一段时间内通过8050的高电平次数(脉冲)从而控制了M1工作的频率(8550是放大电流,驱动m1进行工作,实际控制就是8050在一定时间内通过高电平的次数

3.5 LCD显示器模块设计

LCD1602液晶显示器是一种常见的字符型液晶显示模块,能够显示2行,每行16个字符。这种显示器广泛应用于各种电子项目和设备中,尤其是在嵌入式系统中,因为它提供了一个简单、直观的用户界面来显示文本信息。LCD1602由显示屏、偏压产生电路、控制器和列驱动器等关键部件组成,支持4位或8位数据传输模式,使其能够轻松与各种微控制器接口,如STM32、Arduino等。

LCD1602液晶显示器因其低功耗、高成本效益、易用性以及清晰的字符显示能力而受到广泛应用。它支持2行每行16个字符的显示,足以满足多种显示需求,而且其背光功能确保了在光线较暗的环境下也能清楚地阅读信息。LCD1602的设计简洁,内置的控制器和内存使得用户无需外部数据存储就能控制显示内容,且支持用户自定义字符,进一步增加了其显示内容的灵活性。此外,其普遍可用性和成熟的开发资源使得开发者能够轻松集成此显示模块到各种项目中,快速开发出稳定可靠的用户界面。正是因为这些优点和特性,LCD1602成为智能灯光控制系统中理想的显示选择,既满足了基本的信息显示需求,又保持了系统的经济性和实用性。

选择LCD1602作为智能灯光控制系统的显示模块,主要基于其低功耗、高成本效益和易用性等优点。LCD1602的简单文本显示能力完全符合系统需求,能够有效地向用户提供如光线强度、工作模式和亮度调节等重要信息。此外,LCD1602的普遍可用性和成熟的开发资源也意味着开发者可以轻松集成此显示模块,并快速开发出稳定可靠的用户界面。最后,LCD1602模块的物理尺寸和接口特性使其容易集成到各种大小的系统中,无论是在原型设计阶段还是成品制造阶段,都能提供灵活的适配性。LCD1602液晶显示屏的主要技术参数:

表3-1  LCD1602液晶主要参数

显示容量

芯片工作电压

工作电流

模块最佳工作电压

字符尺寸

16×2个字符

  4.5~5.5V

  2.0mA(5.0V)

5.0V

2.95×4.35(mm)

1602液晶显示屏采用标准的16脚接口,其中各接口的功能如下表所示:

表3-2  1602液晶显示器的引脚功能

引脚号

引脚名

电平

输入/输出

引脚说明

1

VSS

电源地

2

VDD

电源正极(+5V)

3

VL

液晶显示偏压信号

4

RS

0/1

输入

数据/命令选择端,0:输入指令,1:输入数据

5

R/W

0/1

输入

读/写选择端,0:向LCD写入指令或数据,1:从LCD读取信息

6

E

1→0

输入

使能信号,1时读取信息,1→0(下降沿)执行指令

7

D0

0/1

输入/输出

数据总线(最低位)

8

D1

0/1

输入/输出

数据总线

9

D2

0/1

输入/输出

数据总线

10

D3

0/1

输入/输出

数据总线

11

D4

0/1

输入/输出

数据总线

12

D5

0/1

输入/输出

数据总线

13

D6

0/1

输入/输出

数据总线

14

D7

0/1

输入/输出

数据总线(最高位)

15

BLA

+VCC

LCD背光电源正极

16

BLK

接地

LCD背光电源负极

本设计采用与单片机的连接方式为间接控制方式,该方式可以占用单片机的存储空间,而是利用他的I/O口实现与显示模块的联系,他的时序完全由编程来实现,与接口电路无关。液晶显示原理图如下图所示

图3-3  液晶显示屏原理图

3.6蓝牙模块设计

在本智能灯光控制系统中,无线通信方面我们采用的模块是HC05蓝牙模块,我们通过此模块可以把当前的数据和参数无线端发送到用户手机上进行显示,同时我们也可以通过手机端对当前的实物像按键一样进行控制。

HC-05蓝牙模块负责实现无线通信功能,使用户能通过智能设备远程控制灯光。HC-05模块与STM32F103C8T6单片机通过串口连接,实现双向数据传输。模块的工作电压为3.3V,直接与STM32的IO电平兼容,无需额外的电平转换。模块的TXD和RXD引脚分别连接单片机的RX和TX引脚,实现通信。在需要对HC-05进行参数配置时,通过将KEY或EN引脚设为高电平来进入AT命令模式。在PCB设计中,考虑到蓝牙信号的敏感性,注意避免数据线路与高频线路的交叉或靠近,并确保模块周围没有金属遮挡,以保证良好的信号传输效果。通过这种设计,HC-05蓝牙模块不仅为系统提供了远程控制的能力,还通过其与STM32F103C8T6的高效配合,增强了用户交互体验,使系统操作更加便捷和直观。

图3-4  蓝牙HC-05原理图

3.7LD3322语音识别模块设计

在智能灯光控制系统中,本设计使用的LD3322语音识别模块,该模块的引入可以通过语音命令提供一种直观且高效的用户交互方式。该模块与STM32F103C8T6微控制器通过串口连接,实现了双向通信,其中STM32处理器发送初始化和配置命令至LD3322,而LD3322负责识别用户的语音指令并将结果返回给处理器执行相应操作。LD3322模块通常由3.3V供电,需要在设计中考虑电源的稳定性和去耦电容的使用,以确保模块的可靠运行。为了提高识别准确率和系统响应速度,还需考虑噪声抑制和回声消除技术。LD3322模块的集成不仅使系统操作更加便捷直观,而且通过提供新颖的控制方式,极大地增强了智能灯光控制系统的用户体验和市场竞争力。

首先对接收到的语音信号进行一系列的运算处理, 然后和关键词列表中所有的关键词进行对比, 对每一个关键词的相似度打分, 得分最高的那个关键词就认为是正确的, 最后输出 。这样, 当接收到相似度比较高的语音时, 可以通过设置“无用关键词”把它过滤掉, 这是一个非常有效的手段, 设置“无用关键词”越多, 误识别 率越低, 但是不可避免地要牺牲关键词列表地址。 所以本设计通过的是像声词进行识别,只要说的词句是写入的词语进行匹配。语音模块电路如下图所示:

图3-5  LD3322语音识别模块

表3-3  UNV-LD3322产品规格

硬件介绍

项目

说明

对外接口

9个IO口或者(7个IO+一组串口)

工作温度

-40℃ ~ +105℃

工作电压

5V电流推荐不小于1A

供电电流

不小于150MA。

封装尺寸

19.5*22*2.5mm

喇叭接口

板载功放(注意正负极)

咪头接口

直接接咪头(注意正负极)

图3-6  产品引脚顺序

表3-4  引脚说明

引脚说明:

1、NC 用户无法使用的 IO,无须接线。

2、模块的 IO 为 3.3V 电平。

3、B6,B7 当作为串口时,B7 为发送端,外接控制器的接收端。

4、喇叭接口,模组已经集成功放,使用 5V 供电时,可接 4R 3W 8R 2W 16R 1W 喇叭。

通过上面的描述和结合本设计的实物就可以进行知道,此模块为5V供电,自身也可以做为IO口输出,但是本设计没有用到此功能,是和单片机做串口通信,所以只需要接VCC,GND,TXD就可以了。

3.8本章小结

本章深入探讨了智能灯光控制系统的硬件设计,详细描述了系统中关键硬件组件的选择和配置,包括STM32F103C8T6单片机、光敏电阻5528、LCD1602显示屏、LD3322语音识别模块、HC-05蓝牙模块及PWM灯光调节电路的设计与实现。每一部分的设计都旨在提高系统的性能、可靠性和用户交互体验。

整个系统通过精心的硬件设计和协同工作的各组件,实现了一套多功能、高效、易用的智能灯光控制解决方案。系统的设计兼顾了性能、可靠性、用户友好性和成本效益,旨在为用户提供一个舒适、便捷的照明环境。通过这些设计,智能灯光控制系统不仅提高了居住和工作环境的舒适度和便利性,还展示了现代微控制技术在智能家居领域的广泛应用潜力。

4 智能灯光控制系统软件设计

4.1系统软件设计

4.1.1软件开发环境配置

在本设计中,我们选择了Keil MDK5作为智能灯光控制系统的主要软件开发环境。Keil MDK5是针对基于ARM Cortex-M系列微控制器的一套全面的开发工具,提供了从代码编辑、项目管理到编译、调试一体化的解决方案,极大地提高了开发效率。

使用Keil MDK5进行软件开发的一个显著优点是它能够提供对STM32F103C8T6单片机强大的支持,这是智能灯光控制系统的核心控制单元。MDK5的C/C++编译器优化能力强,可以生成高效率的代码,对于我们要求实时响应的照明控制系统而言,这一点尤为重要。此外,MDK5的调试器功能完善,支持JTAG和SWD调试技术,使得我们能够在开发过程中实时跟踪程序运行状态,快速定位和解决问题。

Keil MDK5的库管理功能也为开发提供了便利,通过调用广泛的中间件库和驱动库,我们可以轻松实现LCD显示、PWM调节、ADC转换等功能的编程,加速了开发流程。由于Keil MDK5具有良好的模块化设计和用户友好的界面,使得整个项目的管理和维护变得更加高效。

总之,选择Keil MDK5作为开发环境,不仅提高了开发效率,还保证了系统运行的稳定性和可靠性,是智能灯光控制系统开发中的关键选择。

4.1.2软件总体框架

主程序模块:系统上电后,我们需要配置个个传感器的引脚,蓝牙串口初始化然后光敏进行数据采集,初始化最后通过LCD1602进行液晶显示信息,人体感应当前是否有人,并且通过光敏电阻检测当前光线强弱,最后把数据通过LCD1602显示当前采集到的数据,最后进入按键扫描判断按键是否按下如果按下则处理按键扫描函数。语音识别当前的指令控制灯光。

图4-1  智能灯光控制系统流程图

4.2光线检测模块的软件设计

首先需要初始化单片机的ADC模块,以使其能够读取模拟信号。这在代码中通过Adc_Init();函数实现。此函数配置了单片机的ADC通道,并设置了适当的采样时间和ADC转换速率,以确保能准确读取光敏电阻的模拟值。本次设计选择的A10,然后进行读取数据,一个字节为8位,进行一位一位读取,把当前读取的信息转换为数字量,换算成当前的电压值。先初始化adc引脚, adc开始读取数据ad_value_temp = Read_ADC (0); 读取转换后的数据,从最高位开始依次输出(D7~D0)for(i = 0;i < 8;i++) {dat <<= 1;//左移运算符,例如c<<=2就是 c=c<<2把c左移2位得度到的值给c。dat=dat<<1,把dat左移1位得度到的值给dat; dat |= ADDO;//C语言中的 |= 意思为:按位或后赋值.C语言中的 ^= 意思为:按位异或后赋值.C语言中的 &= 意思为:按位与后赋值

图4-2  光线检测流程图

4.3 PMW亮度调节的软件设计

首先,系统初始化部分包括PWM模块的配置。在此阶段,通过void  PWM_Init(void) 设置PWM频率和初始占空比,初始化PWM信号输出。系统利用STM32的定时器中断功能,来实现占空比的实时调整。

调节PWM的占空比可以改变输出信号的平均电平,从而控制LED灯的亮度

void Set_PWM_Duty_Cycle(uint8_t duty Cycle)。

此外,系统还实现了自动和手动两种模式下的亮度调节。在自动模式下,系统根据环境光线强度自动调整LED亮度,以达到节能的目的。而在手动模式下,用户可以通过按钮直接控制亮度,可以用这个void  Adjust_Brightness(void)实现

为了实现这些功能,系统中定义了相关的软件函数,包括PWM初始化函数、占空比设置函数、模式切换函数及亮度调节函数等。通过对这些函数的调用和管理,配合相应的硬件设备,完成了灯光调节的整个控制流程。

4.4 LCD显示器模块的软件设计

LCD显示器模块的软件设计核心在于通过一系列的函数来实现与LCD1602液晶显示屏的通信和信息展示。LCD1602能够显示16个字符,共2行,广泛应用于显示设备的信息输出。软件设计的首要步骤是通过LCD_Init函数初始化LCD显示器,设置其工作模式,如字符大小、显示行数等,并确保在开始使用前屏幕被清空。

void LCD_Init(void)

{

    // GPIO初始化代码省略...

    LCD_Write_Com(0x38); // 功能设置:8位数据接口,2行显示,5x7点阵字符。

    LCD_Write_Com(0x08); // 显示关闭

    LCD_Write_Com(0x01); // 显示清屏

    LCD_Write_Com(0x06); // 入口模式设置:光标移动方向增加,不移动显示。

    LCD_Write_Com(0x0C); // 显示开,光标关闭,不闪烁。

}

这一段代码负责初始化LCD1602显示模块,包括设置显示模式(两行显示,5x7点阵字符),清屏,以及设置显示开启但光标关闭。

显示信息到LCD上涉及到两类操作:命令操作和数据写入。命令操作,如屏幕清理、光标位置设置等,通过LCD_Write_Com函数实现,它通过特定的命令码与LCD通信。数据写入操作,即向屏幕写入要展示的字符,通过LCD_Write_Data函数执行。这两个函数都通过控制LCD的接口线(RS、RW、EN)和数据线来发送命令和数据。

void LCD_Write_Com(unsigned char com)

{

    // 设置RS、RW为适当值,EN为高再置低以发送命令

    // GPIO_Write用于设置数据线的值

    ...

}

此函数用于向LCD写入命令,如清屏、光标移动等操作。这是通过控制接口线(RS、RW、EN)和数据线来实现的。

void LCD_Write_String(unsigned char x, unsigned char y, unsigned char *s)

{

    if (y == 0)

    {

        LCD_Write_Com(0x80 + x); // 第一行

    }

    else

    {

        LCD_Write_Com(0xC0 + x); // 第二行

    }

    while (*s)

    {

        LCD_Write_Data(*s++); // 显示字符

    }

}

这一段代码用于在LCD上显示字符串。首先根据传入的行号选择是在第一行还是第二行显示,然后遍历字符串中的每一个字符并调用LCD_Write_Data函数显示出来。

此外,LCD_Clear函数提供了一种快速清除屏幕内容的方法,确保新的信息显示前屏幕没有信息。

void LCD_Clear(void)

{

    LCD_Write_Com(0x01); // 显示清屏命令

}

通过发送清屏命令0x01到LCD,实现清除屏幕上的所有显示内容。

LCD1602显示器具体流程图:

图4-3  液晶显示程序流程图

4.5蓝牙模块的软件设计

本设计使用的是HC-05蓝牙模块,该蓝牙模块都是封装好的,仅串口通信就可以使主控制器与该蓝牙模块建立联系。系统启动时,通过USART1初始化蓝牙模块,配置其工作参数如波特率和通信模式等,给蓝牙透传模块上电,此时led闪烁。单片机上的蓝牙模块也上电工作,蓝牙主要是通过串口进行数据传输,首先蓝牙初始化void uart_init(unsigned int baud);然后设置率为9600,打开总断EA = 1; 串口开始发送数据字符串 :void uart_send(unsigned char *bufs,unsigned char len) bufs为字符串,len是表示字符串长度;等待发送完成while (len--)

图4-4  蓝牙与单片机连接程序流程图

我们通过手机点“搜索位于有效范围内的设备”,系统将搜索蓝牙设备,默认设备名称“HC-05”,双击或者点击右键选择“添加蓝牙设备”, 输入配对密码(默认为“1234”)。点击“下一步”,如果密码正确,则单片机和手机之间则建立通信,在手机选择波特率9600,下图是HC-05蓝牙通信模块配对流程图:

图4-5  HC-05蓝牙通信流程图

4.6 LD3322语音识别模块的软件设计

LD3322语音识别模块的软件设计的首要步骤是初始化单片机的串口通信,确保与LD3320语音识别模块的通信波特率匹配。通过调用uart1_Init(9600);函数设置波特率为9600,这是因为LD3320模块默认的通信波特率为9600,这样设置可以保证两者之间的稳定通信。

为了能够实时响应LD3320模块发送过来的数据,需要配置串口的中断服务程序。当LD3320模块识别到特定的语音指令后,会通过串口发送相应的指令码给单片机。单片机通过中断服务程序USART1_IRQHandler接收这些数据。在该中断服务程序中,通过USART_ReceiveData(USART1);函数读取串口接收到的数据,并存储于command变量中,为下一步的命令解析做准备。

在串口中断服务程序中,根据接收到的命令(存储在command变量中),执行相应的操作。如:据指令开启或关闭LED灯,调整设备工作档位等。

switch(command)

{

    case(0x02): LED = 1; break; // 关灯

    case(0x03): RELAY1 = 0; break; // 一档

    case(0x04): RELAY1 = 1; break; // 二档

    case(0x05): RELAY2 = 0; break; // 三档

    // 更多命令的处理...

}

在执行了语音指令对应的操作之后,系统会通过LCD显示器或其他显示设备给用户反馈当前的设备状态。这一步通过调用displayState()函数实现,函数中根据当前的设备状态更新LCD显示内容,如显示LED灯当前的开关状态、设备的工作档位等。这样做不仅让用户能够直观地看到他们的操作结果,还提升了设备的交互友好性。

4.7本章小结

本章深入探讨了智能灯光控制系统的软件设计,包括开发环境的配置、整体软件架构以及关键模块的实现。通过选用Keil MDK5作为开发环境,本设计充分发挥了其对ARM Cortex-M系列单片机的支持,实现了高效编程。软件框架设计突出了系统启动后的初始化流程,确保了各模块的协同工作。具体到模块设计,蓝牙通信模块通过串口完成数据交互,实现远程控制;LCD显示器模块通过清晰的显示界面提高用户友好性;语音识别模块引入了便捷的交互方式;光线检测与PWM灯光调节模块共同完成了基于环境光线的智能亮度调整。整体而言,软件设计以其全面而细致的考量,确保了系统功能的实现和用户交互的便利性,体现了一个高效、便捷、智能的灯光控制解决方案的设计理念。

5 系统测试及结果

5.1测试 

整体的系统连接涉及到的模块有:STM32F103C8T6单片机、LCD显示模块、HC-05蓝牙模块、LD3322语音识别模块、1*4 矩阵按键模块、5528光敏电阻、喇叭。然后根据原理图将这些模块的引脚与STM32F103C8T6单片机的引脚进行连接,实物连接如图 5-1 所示:

图5-1  智能灯光控制系统的实物连接图

部分功能展示 :LCD屏幕显示的当前系统的各功能的状态,以及当环境光在不同亮度下的灯光状态。

图5-2  LCD屏显示功能

图5-3  在环境光暗的时候灯光状态为打开

5.2结果

经测试结果显示,该作品达到了预期的效果。

6 结论与展望

6.1结论 

随着科技的进步,现代人越来越追求智能化和便捷化的生活方式。智能家居作为科技发展的一个重要成果,已经逐渐走进我们的生活,其中智能灯光控制系统作为智能家居生态中不可或缺的一环,以其便捷的控制方式、舒适的照明体验吸引了众多用户的关注。通过本论文的研究与开发,不仅希望提供一个功能全面、操作简便的智能照明解决方案,更希望通过这一系统,使得科技的便捷之光照亮每个人的日常生活,让智能家居的理念更深入人心。

本论文介绍了基于STM32F103C8T6单片机的智能灯光控制系统的设计与实现。系统通过整合先进的技术模块,包括光线检测、PWM亮度调节、LCD显示、蓝牙通信和语音识别,构建了一个既高效又易于操作的智能照明方案。借助于精心设计的硬件架构和软件平台,这一系统不仅能够智能地调整光线,以适应环境的变化,还支持用户通过语音和远程控制进行互动,极大地提升了用户体验。

6.2展望

尽管该系统已经具备了丰富的功能和较好的用户体验,未来的研究和开发中仍然有很多值得探索的空间。例如,进一步提升系统的兼容性和互操作性,让它能够更加无缝地融入到更广泛的智能家居生态中去;或者通过引入更为直观的用户交互方式,如触摸屏和手势识别,使得控制更加便捷;此外,借助人工智能技术,探索更加智能化和个性化的照明调控策略,不仅能提升用户体验,更能助力节能减排,贡献于可持续发展的目标。

智能灯光控制系统的研究与开发,不仅是对现有技术的一次有效整合与应用,更是对未来智能家居技术发展方向的一次探索。随着技术的不断进步和用户需求的不断变化,智能灯光控制系统将持续演进,为创造更加智能、便捷、舒适的居住环境做出更多的贡献。

考文献

[1] 李梦瑶,张亚峰. 基于STM32的 智能灯 设计与实现. 2022

[2] 何运繁,罗俊. 多功能 智能灯 系统的设计与实现. 2021

[3] 陈晓航,夏彬阳. 基于智能家居系统的智能台灯设计与实践. 2016

[4] 王超宇,祝忠明. 何春燕. 基于 STM32 的多功能智能护眼台灯的设计. 2019

[5] 张启龙,陈湘萍. 基于 STM32 的智能互联台灯设计. 2019

[6] 周明,王振. 基于STM32 单片机的智能床围灯设计. 2020

[7] 杨显斌. 一种基于STM32的智能学习型台灯设计. 2019  

[8] 郑瑞旭,张炎生. 基于STM32的智能交通灯控制系统设计.

[9] 贺广博,承晓. 基于STM32F030F4的护眼台灯的设计. 2017

[10]赵继文. 传感器与应用电路设计[M ]. 北京: 科学业出版社, 2002.

[11]黄继昌. 电子元器件应用手册[M ]. 北京: 人民邮电出版社, 2004.

[12]何希才. 传感器及其应用电路[M ]. 北京: 电子工业出版社, 2001.

[13]陈晓阳. 基于STM32的智能灯控系统设计与实现. 2016

[14] Li G D, Zhang J F, Zheng H G, et al. U Nong Shu Cai Tong System - The Agricultural Expert System Based on U Disk[J]. Applied Mechanics & Materials, 2013, 397-400:2406-2411.

[15] Du B, Cai C, Zhang X. Flat control system based on free pendulum[C]// International Conference on Computer Science & Education. 2012.

[16] Wang,Ting. Design of Intelligent Wagon which Can Automatically Enter into Garage Based on STC89C52[J]. Applied Mechanics & Materials, 2015, 713-715:5

致  谢

在完成这篇论文的过程中,我衷心感谢骆晓鹏老师对我的研究工作和学术成长所给予的巨大支持和帮助。同时,也感谢所有参与本研究的同行及朋友们的鼓励和支持。骆晓鹏老师不仅在学术上给予了我宝贵的指导,还在研究方法和论文撰写上提供了大量的帮助和建议。老师的严谨学风和勤奋态度一直是我学习的榜样,老师的耐心指导和鼓励让我在遇到困难和挑战时能够保持信心,继续前进。

同时,我也要感谢所有参与本研究的同行和专家。在项目的实施过程中,他们提供了大量的专业知识和实践经验,对研究的成功完成起到了关键作用。他们的热心帮助和宝贵意见让我受益匪浅。

此外,我还要感谢我的朋友们。在我进行研究和撰写论文的日子里,他们给予了我无限的支持和帮助,是我完成研究的不竭动力。

最后,我要感谢所有直接或间接为本研究贡献力量的人。感谢学校提供的优良学习和研究环境,感谢图书馆和实验室提供的资源支持,感谢所有提供技术和学术支持的机构和个人。

每一份帮助和支持都是我完成这篇论文不可或缺的一部分,我将这份成果献给所有支持和帮助过我的人。谢谢你们!

附  录

程序代码:

Main主程序

#include "sys.h"

#include "adc.h"

#include "delay.h"

#include "lcd1602.h"

#include "usart1.h"

#include "usart3.h"

#include "timer.h"

#include "gpio.h"

#include "stdio.h"

#include "stdbool.h"

#include <string.h>

#define STM32_RX1_BUF       Usart1RecBuf

#define STM32_Rx1Counter    RxCounter

#define STM32_RX1BUFF_SIZE  USART1_RXBUFF_SIZE

bool mode = 0;               //0是自动模式,1是手动模式

unsigned char miao = 0;      //没有人的计时时间

unsigned char PWM_Val = 0xFF;//用于PWM调节

unsigned char GearTemp = 0;  //0~3档

u16 light=0;

unsigned char command = 0;

unsigned char STR_BUF[]={0x0e,0x0e,0x04,0x0e,0x15,0x04,0x0a,0x11};   //特殊图形

bool usart_send_flag = 0;

bool shuaxin = 0;

void AutoModeHandle(void)//自动模式处理函数,根据光线调节LED亮度

{

  u16 test_adc=0;

   /////////////获取光线值

   test_adc = Get_Adc_Average(ADC_Channel_9,10);//读取通道9的5次AD平均值

  light = test_adc*99/4096;//转换成0-99百分比

  light = light >= 99? 99: light;//最大只能到百分之99

   LCD_Write_Char(6,0,light/10+'0');

   LCD_Write_Char(7,0,light%10+'0');

   if(mode==0)//在自动模式下,根据光线调节档位

  {

     if(miao==0)GearTemp=0;//秒计时到0,说明没有人了,关闭LED

     else//否则根据光线调节

    {

      if(light>=85)GearTemp=0;

      if(light<85)GearTemp=1;

      if(light<55)GearTemp=2;

      if(light<25)GearTemp=3;

    }

  }

}

void BRIGHTNESS(u8 index)//调节亮度

{

  switch(index)

  {

    case(0):PWM_Val = 0xFF;PWM_LED = 0;break;

    case(1):PWM_Val = 0x46;break;  //70

    case(2):PWM_Val = 0x28;break;  //40

    case(3):PWM_Val = 0x00;PWM_LED = 1;break;

    default:PWM_Val = 0x00;PWM_LED = 1;break;

  }

  LCD_Write_Char(15,0,index+'0');

}

void keyscan(void)

{

 if(KEY1 == 0)//模式切换按键

 {

   delay_ms(10);//消抖

  if(KEY1 == 0)

  {

    while(KEY1 == 0);//等待按键松开

   mode = 0;

      LCD_Write_String(0,1,"    < AUTO >    ");

  }

 }

 if(KEY2 == 0)//模式切换按键

 {

   delay_ms(10);

  if(KEY2 == 0)

  {

       while(KEY2 == 0);

       mode = 1;

       LCD_Write_String(0,1,"    <Manual>    ");

  }

 }

 if(mode == 1)

 {

   if(KEY3 == 0)//加键

   {

    delay_ms(10);

    if(KEY3 == 0 )

    {

     while(KEY3 == 0);

     if(GearTemp < 3)GearTemp++;

    }

   }

   

   if(KEY4 == 0)//减键

   {

    delay_ms(10);

    if(KEY4 == 0 )

    {

     while(KEY4 == 0);

     if(GearTemp > 0)GearTemp--;

    }

   }

 }

}

void UsartSendReceiveData(void)

{

   if(STM32_Rx1Counter > 0)

  { 

     delay_ms(20);

   

    if(strstr(STM32_RX1_BUF,"auto_mode")!=NULL)

    {

       mode = 0;

      LCD_Write_String(0,1,"    < AUTO >    ");

    } 

    

    if(strstr(STM32_RX1_BUF,"manual_mode")!=NULL)

    {

      mode = 1;

      LCD_Write_String(0,1,"    <Manual>    ");

    } 

    if(mode == 1)

    {   

      if(strstr(STM32_RX1_BUF,"manual_off")!=NULL)

      {

        GearTemp = 0;

      }

      if(strstr(STM32_RX1_BUF,"gear_one")!=NULL)

      {

        GearTemp = 1;

      } 

      if(strstr(STM32_RX1_BUF,"gear_two")!=NULL)

      {

        GearTemp = 2;

      } 

            if(strstr(STM32_RX1_BUF,"gear_three")!=NULL)

      {

        GearTemp = 3;

      }       

    }

     memset(STM32_RX1_BUF, 0, STM32_RX1BUFF_SIZE);//清除缓存

      STM32_Rx1Counter = 0;       

  }

  if(usart_send_flag==1)    //1秒钟上传一次数据

  {

     usart_send_flag = 0;  

      

     printf("$light:%d#,$gear:%d#",(int)light,(int)GearTemp);

  }

}

int main(void)

  delay_init();     //延时函数初始化   

   NVIC_Configuration();

  delay_ms(500);       //上电瞬间加入一定延时在初始化

   Adc_Init();          //ADC初始化

   KEY_GPIO_Init();    //按键初始化

   uart1_Init(9600);

  LCD_Init();         //屏幕初始化

   LCD_Write_String(0,0,"light:00%    G:0");//显示字符串

   LCD_Write_String(0,1,"    < AUTO >    ");

   memset(STM32_RX1_BUF, 0, STM32_RX1BUFF_SIZE);//清除缓存

  STM32_Rx1Counter = 0;

   USART3_Init(9600);

   TIM2_Init(99,71);     //定时器初始化,定时100us

  TIM3_Init(499,7199);  //定时器初始化,定时50ms

   //Tout = ((arr+1)*(psc+1))/Tclk ;  

   //Tclk:定时器输入频率(单位MHZ)

   //Tout:定时器溢出时间(单位us)

  while(1)

  {  

    keyscan();

    if(command!=0)

    {

      delay_ms(10);

     switch(command)

     {

      case(0x01): mode = 0;LCD_Write_String(0,1,"    < AUTO >    ");  break;

      case(0x02): mode = 1;LCD_Write_String(0,1,"    <Manual>    ");  break;  

            case(0x03): mode = 1;LCD_Write_String(0,1,"    <Manual>    ");if(mode==1) GearTemp=0;    break; 

      case(0x04): mode = 1;LCD_Write_String(0,1,"    <Manual>    ");if(mode==1) GearTemp=1;    break; 

      case(0x05): mode = 1;LCD_Write_String(0,1,"    <Manual>    ");if(mode==1) GearTemp=2;    break; 

      case(0x06): mode = 1;LCD_Write_String(0,1,"    <Manual>    ");if(mode==1) GearTemp=3;    break; 

      default: break;

     }

     command=0;

    }

    if(shuaxin == 1)//延时一段时间执行以下函数

    {

       shuaxin = 0;

            AutoModeHandle();     

    } 

    UsartSendReceiveData();

    BRIGHTNESS(GearTemp);

    if(miao>0)Lcd_Custom_Char(0,10,4,STR_BUF); //有人则显示特殊图形

    else      LCD_Write_Char(10,0,' ');        //无人显示空白符

    delay_ms(1);

  } 

}

void USART3_IRQHandler(void)              //串口1中断服务程序,用于接收语音识别模块发送过来的数据   

{

     if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)  

     {   

        command = USART_ReceiveData(USART3);//接收模块的数据

     }

     if(USART_GetFlagStatus(USART3,USART_FLAG_ORE) == SET)

     {

         USART_ClearFlag(USART3,USART_FLAG_ORE);

     }

     USART_ClearITPendingBit(USART3, USART_IT_RXNE);

}

void TIM2_IRQHandler(void)//定时器2中断服务程序  

{

   static u8 timeCount = 0;

  if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源

  {

    TIM_ClearITPendingBit(TIM2, TIM_IT_Update); //清除中断标志位  

     timeCount++;

     if(timeCount > 100)timeCount = 0;          //10ms一个周期 ,频率为100Hz

    if(timeCount >= PWM_Val)PWM_LED = 1;      //占空比调节  

    else PWM_LED = 0;  

   }

}

void TIM3_IRQHandler(void)   //TIM3中断,50毫秒一次中断

{

  static u8 timeCount1 = 0;

   static u8 timeCount2 = 0;

   static u8 timeCount3 = 0;

  if(TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源

  {

    TIM_ClearITPendingBit(TIM3, TIM_IT_Update);  //清除TIMx的中断待处理位:TIM 中断源

        if(timeCount1++ >= 20)//1秒时间到

    {

      timeCount1 = 0;

      if(SR501==1)miao=10;//检测到有人,时间赋值10秒

       else

      {

        if(miao>0)miao--;//没有人,10秒倒计时

      }

    }

    

    timeCount2++;

    if(timeCount2 >= 10)

    {

      timeCount2 = 0;

       

       shuaxin = 1;

    }

    

    timeCount3++;

    if(timeCount3 >= 13)

    {

      timeCount3 = 0;

       

       usart_send_flag = 1;

    }

  }

}

Adc模数转换程序

#include "adc.h"

 #include "delay.h"

     

//初始化ADC

//这里我们仅以规则通道为例

//我们默认将开启通道0~3                    

void  Adc_Init(void)

{  

 ADC_InitTypeDef ADC_InitStructure;

 GPIO_InitTypeDef GPIO_InitStructure;

 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB |RCC_APB2Periph_ADC1 , ENABLE );   //使能ADC1通道时钟

 RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M

 //PB1 作为模拟通道输入引脚                         

 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;

 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;  //模拟输入引脚

 GPIO_Init(GPIOB, &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数据右对齐

 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规则组的转换结果

}

u16 Get_Adc_Average(u8 ch,u8 times)

{

 u32 temp_val=0;

 u8 t;

 for(t=0;t<times;t++)

 {

  temp_val+=Get_Adc(ch);

  delay_ms(5);

 }

 return temp_val/times;

}   

/***************************************************************************

     中位值平均滤波法(又称防脉冲干扰平均滤波法)

方法: 采一组队列去掉最大值和最小值后取平均值。

      相当于“中位值滤波法”+“算术平均滤波法”。

      连续采样N个数据,去掉一个最大值和一个最小值,

      然后计算N-2个数据的算术平均值。    

优点: 融合了“中位值滤波法”+“算术平均滤波法”两种滤波法的优点。

       对于偶然出现的脉冲性干扰,可消除由其所引起的采样值偏差。

       对周期干扰有良好的抑制作用。

       平滑度高,适于高频振荡的系统。

****************************************************************************/

#define N 500 //设置连续采样的次数

u16 Get_Adc_filter(u8 ch)

{

    u16  filter_buf[N]; //缓存N次采样值的存储变量

    u32  filter_temp,filter_sum;           

   u16  i,j;

    for(i = 0; i < N; i++)  //连续采样N个AD值

    {

      filter_buf[i] = Get_Adc(ch);

      delay_us(50);

    }

     // 采样值从小到大排列(冒泡法)

  for(j = 0; j < N - 1; j++)

  {

   for(i = 0; i < N - 1 - j; i++)

   {

    if(filter_buf[i] > filter_buf[i + 1])

    {

     filter_temp = filter_buf[i];

     filter_buf[i] = filter_buf[i + 1];

     filter_buf[i + 1] = filter_temp;

    }

   }

  }

   // 去除最大最小极值后求平均

   for(i = 1; i < N - 1; i++)

   {

    filter_sum += filter_buf[i];

     delay_us(50);

   }

     return (u16)(filter_sum/(N-2));

}

#ifndef __ADC_H

#define __ADC_H 

#include "sys.h"

void Adc_Init(void);

u16  Get_Adc(u8 ch);

u16 Get_Adc_Average(u8 ch,u8 times);

u16 Get_Adc_filter(u8 ch);

#endif

lcd1602液晶程序

#include "lcd1602.h"

#include "delay.h"

#include "sys.h"

u8 Dao_xu(u8 data)

{

    u8 i = 0 ,temp = 0;;

   

   for(i = 0; i < 8; i++)

  {

    temp += (((data >> i) & 0x01) << (7 - i));

  }

  return temp;

}

/*------------------------------------------------

              写入命令函数

------------------------------------------------*/

void LCD_Write_Com(unsigned char com)

{                              

  LCD1602_RS=0;  //命令

 delay_us(1);

  LCD1602_RW=0;

  delay_us(1);

  LCD1602_EN=1;                  

 delay_us(1);

  GPIO_Write(GPIOA,(GPIO_ReadOutputData(GPIOA)&0XFF00)+Dao_xu(com)); //在不影响A8-A15引脚的前提下,把数据写到A0-A7引脚     

 delay_ms(1);

  LCD1602_EN=0;

}

/*------------------------------------------------

              写入数据函数

------------------------------------------------*/

 void LCD_Write_Data(unsigned char Data)

{                                  

  LCD1602_RS=1;   //数据              

 delay_us(1);

  LCD1602_RW=0;

  delay_us(1); 

  LCD1602_EN=1;                  

 delay_us(1);

  GPIO_Write(GPIOA,(GPIO_ReadOutputData(GPIOA)&0XFF00)+Dao_xu(Data)); //在不影响A8-A15引脚的前提下,把数据写到A0-A7引脚   

 delay_ms(1);

  LCD1602_EN=0;

}

/*------------------------------------------------

              写入字符串函数

------------------------------------------------*/

 void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s)

 {     

 if (y == 0)

  {     

  LCD_Write_Com(0x80 + x);  //第一行   

  }

 else

  {     

  LCD_Write_Com(0xC0 + x);  //第二行   

  }        

 while (*s) //判断是否检测到结尾符

  {     

   LCD_Write_Data( *s);//显示字符     

   s ++;  //指针加1   

  }

 }

/*------------------------------------------------

              写入字符函数

------------------------------------------------*/

 void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data)

{     

 if (y == 0)

  {     

  LCD_Write_Com(0x80 + x);    //第一行    

  }    

 else

  {     

  LCD_Write_Com(0xC0 + x);  //第二行     

  }        

 LCD_Write_Data( Data); //显示字符      

}

/******************************************************************************/

// 自定义字符数据(CGRAM)

/******************************************************************************/

void Lcd_Custom_Char(unsigned char row, unsigned char col, unsigned char pos, unsigned char *customValueTable)

{

 unsigned char i = 0;

 for(i=0;i<8;i++){

  LCD_Write_Com(0x40+pos*8+i);//对CGRAM第一个自定义字符操作,若第二个则是0X48,其次类推

  LCD_Write_Data(*(customValueTable+i));//写入显示数据

 }

 if(row==0){

  LCD_Write_Com(0x00+0x80+col);//在第一行显示

  LCD_Write_Data(0x00+pos);//显示自定义字符(0x40对应第一个:0x00,以此类推)

 }else{

  LCD_Write_Com(0x40+0x80+col);//在第二行显示

  LCD_Write_Data(0x00+pos); 

 }

}

 /*------------------------------------------------

                清屏函数

------------------------------------------------*/

 void LCD_Clear(void)

{

 LCD_Write_Com(0x01);

 delay_ms(5);

}

/*------------------------------------------------*/

 void LCD_Init(void)

{

   GPIO_InitTypeDef GPIO_InitStructure;

   

   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC, ENABLE);  //开启GPIOA GPIOC 时钟

   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 |GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 |

    GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //输出速度50MHZ

    GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOA

   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 |GPIO_Pin_14 |GPIO_Pin_15;  // LCD1602 RS-RW-EN

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   //推挽输出

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   //输出速度50MHZ

    GPIO_Init(GPIOC, &GPIO_InitStructure);   //GPIOC

   LCD_Write_Com(0x38);

   delay_ms(5);  

  LCD_Write_Com(0x38);

   delay_ms(5);  

  LCD_Write_Com(0x38);

   delay_ms(5);  

   LCD_Write_Com(0x08);    /*显示关闭*/

   delay_ms(5);  

   LCD_Write_Com(0x01);    /*显示清屏*/

   delay_ms(5);  

   LCD_Write_Com(0x06);    /*显示光标移动设置*/

  delay_ms(5);

   LCD_Write_Com(0x0C);    /*显示开及光标设置*/

  delay_ms(5);

}

#ifndef __LCD1602_H

#define __LCD1602_H

#include "delay.h"

#include "sys.h"

#define LCD1602_RS PCout(13) //数据命令

#define LCD1602_RW PCout(14) //读写

#define LCD1602_EN PCout(15) //使能

 void LCD_Init(void);

 void LCD_Clear(void);

 void LCD_Write_Com(unsigned char com);

 void LCD_Write_Data(unsigned char Data);

 void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s);

 void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data);

 void Lcd_Custom_Char(unsigned char row, unsigned char col, unsigned char pos, unsigned char *customValueTable);

#endif

Timer定时器程序

#include "timer.h"

#include "delay.h"

//通用定时器中断初始化

//这里时钟选择为APB1的2倍,而APB1为36M

//arr:自动重装值。

//psc:时钟预分频数

//这里使用的是定时器2

void TIM2_Init(u16 arr,u16 psc)

{  

 TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

  NVIC_InitTypeDef NVIC_InitStructure;

 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //使能TIM2时钟

 //初始化定时器2  

 TIM_TimeBaseStructure.TIM_Period = arr; //设定计数器自动重装值

 TIM_TimeBaseStructure.TIM_Prescaler =psc;  //预分频器   

 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim

 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式

 TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位

  

 //中断分组初始化

 NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;  //TIM3中断

 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;  //先占优先级2级

 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;  //从优先级0级

 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能

 NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

 TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//允许更新中断 ,

  TIM_Cmd(TIM2,ENABLE );  //使能定时器2

}

//这里使用的是定时器3!

void TIM3_Init(u16 arr,u16 psc)

{

  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

 NVIC_InitTypeDef NVIC_InitStructure;

 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能

 TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值  计数到5000为500ms

 TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值  10Khz的计数频率  

 TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim

 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式

 TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位

 TIM_ITConfig(  //使能或者失能指定的TIM中断

  TIM3, //TIM3

  TIM_IT_Update ,

  ENABLE  //使能

  );

 NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断

 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;  //先占优先级0级

 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;  //从优先级2级

 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能

 NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

 TIM_Cmd(TIM3, ENABLE);  //使能TIMx外设       

}

#ifndef __TIMER_H

#define __TIMER_H

#include "sys.h"

void TIM2_Init(u16 arr,u16 psc);

void TIM3_Init(u16 arr,u16 psc);

#endif

Gpio引脚初始化程序

#include "gpio.h"

//////////////////////////////////////////////////////////////////////////////////  

//GPIO设置          

//////////////////////////////////////////////////////////////////////////////////     

void KEY_GPIO_Init(void)

{

  GPIO_InitTypeDef  GPIO_InitStructure;

  

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC, ENABLE);  //使能PB端口时钟

  

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;     // 端口配置

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;    

  GPIO_Init(GPIOB, &GPIO_InitStructure);   

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;     // 端口配置

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;    //推挽输出

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   //IO口速度为50MHz

  GPIO_Init(GPIOB, &GPIO_InitStructure);   

  GPIO_ResetBits(GPIOB,GPIO_Pin_8); //输出低电平

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;     // 端口配置

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;   

  GPIO_Init(GPIOB, &GPIO_InitStructure); 

}

#ifndef __GPIO_H

#define __GPIO_H  

#include "sys.h"

//////////////////////////////////////////////////////////////////////////////////  

#define PWM_LED PBout(8)

#define SR501 PBin(6)

#define KEY1 PBin(12)

#define KEY2 PBin(13)

#define KEY3 PBin(14)

#define KEY4 PBin(15)

void KEY_GPIO_Init(void);//初始化         

#endif

usart1串口1程序

#include <stm32f10x.h>

#include <stdio.h>

#include "usart1.h"

char Usart1RecBuf[USART1_RXBUFF_SIZE];//串口1接收数据缓存

unsigned int RxCounter = 0;   //串口1收到数据标志位

//////////////////////////////////////////////////////////////////

//加入以下代码,支持printf函数,而不需要选择use MicroLIB   

#if 1

#pragma import(__use_no_semihosting)             

//标准库需要的支持函数                 

struct __FILE

{

 int handle;

};

FILE __stdout;       

//定义_sys_exit()以避免使用半主机模式    

_sys_exit(int x)

{

 x = x;

}

//重定义fputc函数

int fputc(int ch, FILE *f)

{      

 while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   

    USART1->DR = (u8) ch;      

 return ch;

}

#endif

/****************************************************************************

描述:Usart1 初始化

   PA9: USART1_TX

   PA10: USART1_RX

参数:none

返回: none

****************************************************************************/

void uart1_Init(u32 bound)

{

    //GPIO端口设置

  GPIO_InitTypeDef GPIO_InitStructure;

  USART_InitTypeDef USART_InitStructure;

  NVIC_InitTypeDef NVIC_InitStructure;  

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO, ENABLE);

 USART_DeInit(USART1);  

     //USART1_TX   PA.9

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

  GPIO_Init(GPIOA, &GPIO_InitStructure);

   

    //USART1_RX   PA.10

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

  GPIO_Init(GPIOA, &GPIO_InitStructure);  

   //Usart1 NVIC 配置

  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0 ;

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能

  NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器USART1

  

   //USART 初始化设置

  USART_InitStructure.USART_BaudRate = bound;//一般设置为9600;

  USART_InitStructure.USART_WordLength = USART_WordLength_8b;

  USART_InitStructure.USART_StopBits = USART_StopBits_1;

  USART_InitStructure.USART_Parity = USART_Parity_No;

  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;

  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

  USART_Init(USART1, &USART_InitStructure);

   

  USART_Init(USART1, &USART_InitStructure);     //初始化串口1

  USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口1接受中断

  USART_ITConfig(USART1, USART_IT_IDLE, DISABLE);//使能串口1总线空闲中断/

  USART_Cmd(USART1, ENABLE);                    //使能串口1

}

void USART1_IRQHandler(void)                 //串口1中断服务程序

{

  if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断,可以扩展来控制

  {

     if(RxCounter >= USART1_RXBUFF_SIZE) RxCounter = 0;

    Usart1RecBuf[RxCounter++] =USART_ReceiveData(USART1);//接收模块的数据

    }

   USART_ClearITPendingBit(USART1, USART_IT_RXNE);

}

void uart1_SendStr(char*SendBuf)//串口1打印数据

{

 while(*SendBuf)

 {

   while((USART1->SR&0X40)==0);//等待发送完成

    USART1->DR = (u8) *SendBuf;

  SendBuf++;

 }

}

void uart1_send(unsigned char *bufs,unsigned char len)

{

   if(len != 0xFF)

  {

    while (len--)

    {

      while((USART1->SR&0X40)==0);//等待发送完成

      USART1->DR = (u8) *bufs;

      bufs ++;

    }

  }

  else//如果字长等于或超过255,不按用户写入字长发送

    {

        for (; *bufs != 0; bufs++)  //把字符逐个发送出去

     {

      while((USART1->SR&0X40)==0);//等待发送完成

      USART1->DR = (u8) *bufs;

    }

    }

}

#ifndef __usart1_H

#define __usart1_H  

#include "stm32f10x.h"

#define USART1_RXBUFF_SIZE   128

extern unsigned int RxCounter;          //外部声明,其他文件可以调用该变量

extern char Usart1RecBuf[USART1_RXBUFF_SIZE]; //外部声明,其他文件可以调用该变量

void uart1_Init(u32 bound);

void uart1_SendStr(char*SendBuf);

void uart1_send(unsigned char *bufs,unsigned char len);

           

#endif

usart3串口3程序

#include <stdio.h>

#include "usart3.h"

  

char Usart3RecBuf[USART3_RXBUFF_SIZE];//串口3接收数据缓存

unsigned int Rx3Counter = 0;   //串口3收到数据标志位

void USART3_Init(u32 baud)   

 {  

      USART_InitTypeDef USART_InitStructure;  

      NVIC_InitTypeDef NVIC_InitStructure;   

      GPIO_InitTypeDef GPIO_InitStructure;    

      RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE);

      RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);  

  

      // Configure USART3 Rx (PB.11) as input floating    

      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;  

      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  

      GPIO_Init(GPIOB, &GPIO_InitStructure);  

  

      // Configure USART3 Tx (PB.10) as alternate function push-pull  

      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;  

      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  

      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  

      GPIO_Init(GPIOB, &GPIO_InitStructure);  

  

      USART_InitStructure.USART_BaudRate = baud;  

      USART_InitStructure.USART_WordLength = USART_WordLength_8b;  

      USART_InitStructure.USART_StopBits = USART_StopBits_1;  

      USART_InitStructure.USART_Parity = USART_Parity_No;  

      USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;  

      USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;  

  

  

      // Configure USART3   

      USART_Init(USART3, &USART_InitStructure);

      // Enable USART3 Receive interrupts

      USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);  

      // Enable the USART3   

      USART_Cmd(USART3, ENABLE);

  

      //Configure the NVIC Preemption Priority Bits     

      NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);  

  

      // Enable the USART3 Interrupt   

      NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;   

      NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 1 ;

      NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;        

      NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  

      NVIC_Init(&NVIC_InitStructure);       

  }

void USART3_Sned_Char(u8 temp)        

 {  

     USART_SendData(USART3,(u8)temp);      

    while(USART_GetFlagStatus(USART3,USART_FLAG_TXE)==RESET);  

 }

void Uart3_SendStr(char*SendBuf)//串口3打印数据

{

 while(*SendBuf)

 {

   USART3_Sned_Char(*SendBuf);

  SendBuf++;

 }

}

void uart3_send(unsigned char *bufs,unsigned char len)

{

   if(len != 0xFF)

  {

    while (len--)

    {

      USART3_Sned_Char(*bufs);

      bufs ++;

    }

  }

  else//如果字长等于或超过255,不按用户写入字长发送

    {

        for (; *bufs != 0; bufs++)USART3_Sned_Char(*bufs);  //把字符逐个发送出去

    }

}

#ifndef __usart3_H

#define __usart3_H  

#include "stm32f10x.h"

#include "stm32f10x_usart.h"

#define USART3_RXBUFF_SIZE   128

extern unsigned int Rx3Counter;          //外部声明,其他文件可以调用该变量

extern char Usart3RecBuf[USART3_RXBUFF_SIZE]; //外部声明,其他文件可以调用该变量

void USART3_Init(u32 baud);

void USART3_Sned_Char(u8 temp);

void Uart3_SendStr(char*SendBuf);

void uart3_send(unsigned char *bufs,unsigned char len);

#endif

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐