STM32-智能台灯项目
一、项目需求
1. 红外传感器检测是否有人,有人的话实时检测距离,过近则报警;同时计时,超过固定时间则报警;
2. 按键 1 切换工作模式:智能模式、按键模式、远程模式;
3. 智能模式下,根据光照强度自动调整光照档位(低亮、中亮、高亮),没人则自动光灯;
4. 按键模式下,按键 2 可以手动调整光照档位;
5. 远程模式下,可以通过蓝牙控制光照档位、计时等;
6. 按键 3 暂停/开始计时,按键 4 清零计时;
7. OLED 显示各项数据/状态。
二、项目框图
三、光敏电阻传感器
光照越强,电阻越小
四、项目实现
19-串口打印功能
adc重命名light_sensor----光敏电阻传感器
exti重命名ia_sensor-------红外传感器
别忘了把对应文件里面也要改
打开项目
加载文件
记得要添加
编译
将代码调到编译不出错
先从软柿子捏
4.1 beep.c文件
修改引脚
编译,不出错
4.2 bluetooch.c 文件
增加串口
因为需要接收从串口传递进来的数据
所以需要定义一个变量来接收的数据
注意:这里接收到的数据是字符类型的,虽然在这里是字符型还是数字的无所谓,需要注意一下。
话外拓展:如何将字符串类型的“123”,转变成数字的123?
代码如下:---来自心知天气的4.5 的代码
这里用的atoi函数的作用就是:将字符串转换为整数的函数
原型为:
新建一个函数,作用如下图的注释
下面的注释是:
直接return command;
和间接返回command的区别
别忘了把新写的代码添加到.h文件
编译,不出错之后,进行下一步
4.3 hcsr04.c文件
修改引脚
编译不出错
4.4 light_sensor.c文件
因为light_sensor文件是由adc.c文件重命名的,所以,在light_sensor里只有adc_init函数,所以需要对light_sensor重新初始化一个函数。
重新写一个函数,获取光敏电阻传感器函数
在这里,使用通道1传递数据,那么为什么是通道1呢?
首先,接光敏电阻传感器的引脚PA1
在产品书册中可以看到,PA1接的是通道1
因为ADC是12位的,所以可以得到的值的范围就是0-2^12 = 0-4096
得到的值太大了,所以想要把得到的值转化成0-100,并且随着光照越强,让得到的值越大
100-(adc_get_result(ADC_CHANNEL_1)* 100 % 4096)中
adc_get_result(ADC_CHANNEL_1)的取值范围是0-4096
adc_get_result(ADC_CHANNEL_1)* 100 % 4096的取值范围是0-100
现在依旧是光照越强,所得值越小,我们的目的是,让光照越强,所得值越大
所以用100-(adc_get_result(ADC_CHANNEL_1)* 100 % 4096)就可以达到效果
最后将所得值强转为uint8_t
4.5 oled.c文件
取模
取汉字
:模式、智能、按键、远程、有、无、人、亮度、高、中、低、关、计时
将这段代码
改成
在oled屏幕上显示汉字的界面代码如下:
4.5 led.c文件
先保存关闭项目
然后将
将原来的led文件删除,把新粘贴的pwm文件重命名为led,如下图
打开项目
打开led.c文件,修改头文件
将定时器4改成定时器3
TIM4->TIM3
修改下面几个地方
接下来就是增加函数了
代码如下:
//初始化led灯
void led_init(void)
{pwm_init(500-1,72-1);
}
//关灯
void led_off(void)
{pwm_compare_set(0);//将CCR的值设置为0,灯的亮度为0led_level = 0;//档位:关灯状态下为0oled_show_chinese(70, 2, 17);//显示oled当前的状态
}
//led灯低亮
void led_low(void)
{pwm_compare_set(150);//将CCR的值设置为0,灯的亮度为0led_level = 1;//档位:关灯状态下为0oled_show_chinese(70, 2, 14);//显示oled当前的状态
}
//led灯中亮
void led_medium(void)
{pwm_compare_set(300);//将CCR的值设置为0,灯的亮度为0led_level = 2;//档位:关灯状态下为0oled_show_chinese(70, 2, 15);//显示oled当前的状态
}
//led灯高亮
void led_high(void)
{pwm_compare_set(450);//将CCR的值设置为0,灯的亮度为0led_level = 3;//档位:关灯状态下为0oled_show_chinese(70, 2, 16);//显示oled当前的状态
}
//获取当前档位的值
uint8_t led_get_level(void)
{return led_level;
}
4.5 key.c文件
因为在key文件中需要修改的按键引脚很多,所以直接在.h文件中定义宏函数
代码如下:
设置一个按键状态标志和按键的值(默认取值0,赋值为其他值时,不同的值代表按下不同的按键)
使用一个if来判断,当按键标志为1时并且检测到某一按键的电平变低时,代表有按键被按下。
进入到if中时,代表有按键被按下,按键状态标志发生变化,所以这时候需要判断是哪一个按键被按下了
检测到对应按键被按下之后,将按键的返回值取对应按键编号。
否则,按键没有被按下,返回按键的值,用于后续处理。
static uint8_t key_up = 1; 这行代码中的 key_up 是一个静态变量,它会在函数调用之间保持其值。这意味着它只会在第一次调用 key_scan 函数时被初始化为1,之后的函数调用中它会保持上一次的值。这是用来检测按键是否被“新”按下的关键。
编译,不出错
4.6 ia_sensor.c 文件
红外传感器
这里红外传感器使用中断的方式来写,但是有一个问题会出现
如果用中断的方式,当从没有人到有人这个状态变化时,只会触发一次中断,后续这个人持续靠近,也不会触发响应。
所以,红外传感器这段代码不能使用中断的方式
修改如以下图所示
ia_sensor.h文件
4.7 timer.c文件
定时器主要是用来计时,不需要其他的功能,所以定时器4足够用
将定时器2改为定时器4
关于定时器,在智能台灯项目中,主要是当有人的时候,开始计时,人走开,计时清空0
新增函数:
将psc和arr的值修改成7200和10000就是一秒
编译。不出错
4.7 main.c文件
书写主函数的代码,重点就是按照流程图一步一步的写代码
代码如下:
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "uart1.h"
#include "beep.h"
#include "bluetooth.h"
#include "hcsr04.h"
#include "ia_sensor.h"
#include "key.h"
#include "light_sensor.h"
#include "oled.h"
#include "timer.h"
//设置一个枚举类型用于存放台灯的模式
enum lamp_mode
{AUTO_MODE = 0, //智能模式MANUAL_MODE, //按键模式REMOTE_MODE //远程模式
};int main(void)
{HAL_Init(); /* 初始化HAL库 */stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */uart1_init(115200);led_init();beep_init();bt_init(9600);//波特率hcsr04_init();ia_init();key_init();ls_init();oled_init();timer_init(10000-1,7200-1);printf("hello word!\r\n");oled_show_init();//显示当前oled的状态/*是否有人标志位:默认无人状态;是否第一次检测到有人: 默认是;距离变量 = 0显示距离变量给三个字符就够用了(因为代码定义的是uint32类型的变量,而oled上只能打印字符串类型的)人坐下的时间统计变量承接按下哪个按键的变量,默认0承接台灯模式的变量,默认智能模式承接光照的数值,默认0承接led灯的高中低关,默认关*/uint8_t person_flag = 0,first_loop =1,dis = 0,dis_str[3] = {0},sit_time_str[3] = {0},key_num = 0,mode = AUTO_MODE,light_value = 0, led_level = 0;while(1){ person_flag = ia_flag_get();if(person_flag == TRUE) //有人{oled_show_chinese(10, 4, 9);if(first_loop == 1){timer_start();//定时器打开first_loop = 0;}dis = hcsr04_get_lenght();//超声波测距if(dis < 10 || sit_timer_get() >= 5)//距离小于10,蜂鸣器响或者有人停留5秒,开始响beep_ON();elsebeep_OFF();}else //无人{oled_show_chinese(10, 4, 10);timer_stop(); //定时器停止计时sit_timer_set(0);//坐下的时间设置为0first_loop = 1;//检测是否第一次有人座置1beep_OFF();//蜂鸣器不响dis = 0;//距离为0}//这行代码将整数 dis 格式化为一个至少3位宽的十进制数,并将结果字符串存储在 dis_str 指向的内存位置。sprintf((char *)dis_str, "%3d", dis);//座的距离显示在oled屏幕上oled_show_string(60, 4, (char *)dis_str, 16);sprintf((char *)sit_time_str, "%3d", sit_timer_get());//将坐下的时间显示在oled屏幕上oled_show_string(60, 6, (char *)sit_time_str, 16);key_num = key_scan();//承接按键的值,根据不同的值,判断按下了哪个按键if(key_num == 1) //按键1,切换工作模式{if(mode++ > 1) //mode的取值有0,1,2,因为先使用mode的值在进行++,所以有三个值可取mode = AUTO_MODE;//mode取值为2的时候,就是智能模式}else if(key_num == 3)//按键3,手动切换灯的状态{timer_toggle();}else if(key_num == 4)//按键4,数据清0{timer_stop();sit_timer_set(0);}switch(mode){case AUTO_MODE:{oled_show_chinese(60, 0, 3); //智oled_show_chinese(75, 0, 4); //能if(person_flag == TRUE) //判断是否有人:有人才可以根据光照强度设置灯的亮度{light_value = ls_get_value(); //获取到光敏电阻的值if(light_value < 40)//光照强度小于40,亮度高一些led_high();else if(light_value >= 40 && light_value <= 70)//光照强度中等,亮度中等led_medium();else if(light_value > 70)//光照强度很强,亮度弱led_low();}else//没有人,直接关灯led_off();break;}case MANUAL_MODE:{oled_show_chinese(60, 0, 5); //按oled_show_chinese(75, 0, 6); //键if(key_num == 2){led_level = led_get_level();//获取光的挡位if(led_level++ > 2)//可以取值的范围是0,1,2,3led_level = 0; //当数值为3的时候,为关灯switch(led_level){case 0:led_off(); //关灯break;case 1:led_low();//低亮break;case 2:led_medium(); //中亮break;case 3:led_high(); //高亮break;default:break;}}break;}case REMOTE_MODE:{oled_show_chinese(60, 0, 7); //远oled_show_chinese(75, 0, 8); //程switch(bt_rx_get() - '0') //从蓝牙中获取的值是字符串类型的,需要减去字符串类型的0,就得到了数字{case 0: //数字0,关灯led_off();break;case 1: //数字1,低亮led_low();break;case 2: //数字2,中亮led_medium();break; case 3: //数字3,高亮led_high();break;case 4: //数字4,开始计时timer_start();break;case 5: //数字5,停止计时timer_stop();break;case 6: //数字6,停止计时并且将计数器清0timer_stop();sit_timer_set(0);break;default:break;}break;}default:break;}delay_ms(20);}
}
相关文章:

STM32-智能台灯项目
一、项目需求 1. 红外传感器检测是否有人,有人的话实时检测距离,过近则报警;同时计时,超过固定时间则报警; 2. 按键 1 切换工作模式:智能模式、按键模式、远程模式; 3. 智能模式下,根…...
c# —— StringBuilder 类
StringBuilder 类是 C# 和其他一些基于 .NET Framework 的编程语言中的一个类,它位于 System.Text 命名空间下。StringBuilder 类表示一个可变的字符序列,它是为了提供一种比直接使用字符串连接操作更加高效的方式来构建或修改字符串。 与 C# 中的 stri…...

Linux 核心架构与组件(2025更新中)
一、Linux 核心架构与组件 内核架构 核心职责: 管理进程生命周期、内存分配、硬件驱动交互及文件系统操作。 模块化设计支持动态加载硬件驱动(如modprobe加载内核模块),提升灵活性和扩展性。 内存管理:…...

Unity打包APK报错 using a newer Android Gradle plugin to use compileSdk = 35
Unity打包APK报错 using a newer Android Gradle plugin to use compileSdk 35 三个报错信息如下 第一个 WARNING:We recommend using a newer Android Gradle plugin to use compileSdk 35This Android Gradle plugin (7.1.2) was tested up to compileSdk 32This warning…...

陀螺匠·企业助手v1.8 产品介绍
陀螺匠企业助手是一套采用Laravel 9框架结合Swoole高性能协程服务与Vue.js前端技术栈构建的新型智慧企业管理与运营系统。该系统深度融合了客户管理、项目管理、审批流程自动化以及低代码开发平台,旨在为企业提供一站式、数字化转型的全方位解决方案,助力…...

文件包含-session2
[题目信息]: 题目名称题目难度文件包含-session22 [题目考点]: 由于网站功能需求,会让前端用户选择要包含的文件,而开发人员又没有对要包含的文件进行安全考虑,就导致攻击者可以通过修改文件的位置来让后台执行任意…...
GitHub免密操作与跨服务器通行:SSH密钥一站式配置指南
作为开发者,与GitHub的安全交互和远程服务器的高效管理是日常工作的核心技能。本文将从零开始,教你如何配置GitHub的SSH密钥认证,并实现免密码远程登录Linux服务器。 一、为什么需要SSH密钥? 更安全的认证方式:相比传统密码,密钥认证几乎无法被暴力破解操作便捷性:免去每…...

PHP入门基础学习四(PHP基本语法)
运算符 运算符,专门用于告诉程序执行特定运算或逻辑操作的符号。根据运算符的作用,可以将PHP语言中常见的运算符分为9类 算数运算符: 是用来处理加减乘除运算的符号 也是最简单和最常用的运算符号 赋值运算符 1. 是一个二元运算符&#x…...
模型蒸馏:让人工智能更智能、更小、更高效的艺术
你有没有想过,我们如何才能让一个需要巨大计算能力的庞大人工智能模型变得更精简、更快速、更强大?答案在于模型蒸馏,这是一种允许知识从大型、计算成本高昂的人工智能系统转移到较小、更高效的系统的技术,而不会牺牲智能。 什么是模型蒸馏 模型蒸馏是一种技术,其…...

git 小乌龟安装包及中文包
git 工具小乌龟不需要输入命令就可以提交,挺方便的,安装完之后鼠标右击就可以看到 链接: https://pan.baidu.com/s/1jqrcrFjKf-bKGcHesxs-YQ 提取码: 8888 复制这段内容后打开百度网盘手机App,操作更方便哦...
MySQL 主从集群同步延迟问题分析与解决方案
MySQL 主从复制(Replication)是构建高可用架构的核心技术,但在实际应用中,主从同步延迟(Replication Lag)是常见且棘手的问题。延迟会导致从库数据不一致、读请求返回旧数据,甚至引发业务逻辑错…...
用HTML5+CSS+JavaScript实现新奇挂钟动画
用HTML5+CSS+JavaScript实现新奇挂钟动画 引言 在技术博客中,如何吸引粉丝并保持他们的关注?除了干货内容,独特的视觉效果也是关键。今天,我们将通过HTML5、CSS和JavaScript实现一个新奇挂钟动画,并将其嵌入到你的网站中。这个动画不仅能让你的网站脱颖而出,还能展示你的…...

医疗AI领域中GPU集群训练的关键技术与实践经验探究(下)
五、医疗 AI 中 GPU 集群架构设计 5.1 混合架构设计 5.1.1 参数服务器与 AllReduce 融合 在医疗 AI 的 GPU 集群训练中,混合架构设计将参数服务器(Parameter Server)与 AllReduce 相结合,能够充分发挥两者的优势,提升训练效率和模型性能。这种融合架构的设计核心在于根…...

解决双系统开机显示gnu grub version 2.06 Minimal BASH Like Line Editing is Supported
找了好多教程都没有用,终于解决了!!我是因为ubuntu分区的时候出问题了 问题描述: 双系统装好,隔天开机找不到引导项,黑屏显示下列 因为我用的D盘划分出来的部分空闲空间,而不是全部,…...
sysbench压测pgsql数据库 —— 筑梦之路
这里主要使用sysbench工具对Pgsql数据库进行基准测试。 1. 创建数据库和用户名 # 创建用户和数据库CREATE USER sysbench WITH PASSWORD 123456;CREATE DATABASE sysbench owner sysbench;# 给用户授权访问 vim pg_hba.confhost sysbench sysbench 127…...

数字IC后端培训教程| 芯片后端实战项目中base layer drc violation解析
今天分享一个咱们社区IC后端训练营学员遇到的一个经典DRC案例。这个DRC Violation的名字为PP.S.9(这里的PP就是Plus P)。这一层是属于管子的base layer。更多关于base layer的介绍,可以查看下面这份教程。 https://alidocs.dingtalk.com/api/doc/transit?spaceId5…...

Android之APP更新(通过接口更新)
文章目录 前言一、效果图二、实现步骤1.AndroidManifest权限申请2.activity实现3.有版本更新弹框UpdateappUtilDialog4.下载弹框DownloadAppUtils5.弹框背景图 总结 前言 对于做Android的朋友来说,APP更新功能再常见不过了,因为平台更新审核时间较长&am…...
什么是 OCP 数据库专家
OCP 即 Oracle Certified Professional,Oracle 认证专业人员,代表持证人在 Oracle 数据库领域具备专业的技能和知识。获得 OCP 数据库专家认证意味着你在 Oracle 数据库管理、开发、优化等方面达到了较高的水平,能够独立承担复杂的数据库相关…...

基于AT89C51单片机的教室智能照明控制系统
点击链接获取Keil源码与Project Backups仿真图: https://download.csdn.net/download/qq_64505944/90419908?spm1001.2014.3001.5501 C16 部分参考设计如下: 摘 要 本项目的智能教室灯光控制系统通过合理的软硬件设计,有效地提升了教室…...
DIP的实际举例
SOLID原则。 依赖倒置原则(DIP)的核心是高层模块不应该依赖于低层模块,二者都应该依赖于抽象(接口或抽象类) 例如,随着业务的发展,订单总金额的计算规则可能需要根据不同的客户类型或促销活动…...

网络编程(Modbus进阶)
思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...

【Python】 -- 趣味代码 - 小恐龙游戏
文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...
React Native 开发环境搭建(全平台详解)
React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...

【WiFi帧结构】
文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成:MAC头部frame bodyFCS,其中MAC是固定格式的,frame body是可变长度。 MAC头部有frame control,duration,address1,address2,addre…...

AI Agent与Agentic AI:原理、应用、挑战与未来展望
文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例:使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例:使用OpenAI GPT-3进…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql
智慧工地管理云平台系统,智慧工地全套源码,java版智慧工地源码,支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求,提供“平台网络终端”的整体解决方案,提供劳务管理、视频管理、智能监测、绿色施工、安全管…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...
Cesium1.95中高性能加载1500个点
一、基本方式: 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...

大型活动交通拥堵治理的视觉算法应用
大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动(如演唱会、马拉松赛事、高考中考等)期间,城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例,暖城商圈曾因观众集中离场导致周边…...

Day131 | 灵神 | 回溯算法 | 子集型 子集
Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣(LeetCode) 思路: 笔者写过很多次这道题了,不想写题解了,大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...