![]() |
这种断电换档的手电筒烂大街了,给你个思路,单片机的RAM数据可以在极低的电压下保持数据不变。断电后单片机不工作了,但是RAM数据还是能保存一会的。起不到精准控制,但是实现简单的手电筒换挡功能还行。 |
lkc8210 发表于 2024-8-22 09:20 您好,代码已经实现了. 想问下您, P32引脚那个电容需要怎么处理吗? P32 - 22uf电容- gnd 中间是否需要并联电阻? 减速掉电? 或者二极管之类的处理 |
lkc8210 发表于 2024-8-22 09:20 弄好了.我在P32加了个电容到负极. 现在可以实现我说的那个功能了 超强 ![]() |
lkc8210 发表于 2024-8-22 09:20 您的代码我之前不能换挡是因为没有加 eeprom擦除 现在在写前面加一句 IapErase(EEPROMId); 就好了 但是就一直换挡,关开一次就换一次档.不能保存当前档位 还有哪里需要纠正吗 |
lkc8210 发表于 2024-8-21 11:11 您这个是不是电路上还有要求啊? P32 我原本接的按键 |
lkc8210 发表于 2024-8-22 09:20 哥,我好像有一点点懂了. 我一直纠结程序上的问题. 刚刚我试了一个很垃圾的手电.好像不是代码上的问题. 就是那个电容的问题. 我那个垃圾手电,我把电容用铅笔涂黑了(就是短路了) 现在不能换挡,一直是那个档位. 好像换挡取决于那个电容.. 电容的大小决定关机再开机多久时间换挡. |
vb2002 发表于 2024-8-21 22:01 我那个只是示范,你还要加上之前的EEPRom循环读写的代码 |
vb2002 发表于 2024-8-21 22:51 我没写过这种代码,但是有了具体思路不是很简单的事情吗?按键判断的代码本站也有很多的 |
yaosongjin 发表于 2024-8-21 08:38 就是代码不会弄呢 可以给个代码吗? 实现半按换挡 我这个麻烦死了 |
lkc8210 发表于 2024-8-21 11:11 按您的代码现在一直是亮度5,可以点亮 但是不能换挡. 能帮看看吗? 是我没有上真机实验吗? 我用的开发板弄的
|
vb2002 发表于 2024-8-20 18:47 我的代码是检测P32脚电容的电平来判断掉电时间的 |
vb2002 发表于 2024-8-20 18:49 你可能没搞清楚程序运行的逻辑,按照这个电路来操作的话: 1.上电后MCU复位进入工作状态 2.当按下电源开关后MCU开始记录4脚电平保持的时间 3.假如维持的低电平为500MS又变高了,就切换模式或者亮度之类的功能并且写入内存 4.假如维持的电平超过500MS说明是手电要关机,就不再做任何处理 5.如果要做双击的话,同样在按键处理这一块想办法 |
yaosongjin 发表于 2024-8-20 17:39 主要是代码方面弄不好.
|
![]() |
vb2002 发表于 2024-8-20 16:51 MCU第4脚用于判断开关状态。 |
5fee380a84e8dab4c9fc65f1daf0e8ca.png (60.68 KB, 下载次数: 21)
vb2002 发表于 2024-8-20 16:42 为啥不加电容? |
yaosongjin 发表于 2024-8-20 15:55 如果设置睡眠模式,是不是10uf可以坚持很久很久? 甚至都不用eeprom都行了? 就是这个断电判断不会弄 |
倒不如关机后短按开机、开机后短按切换亮度、长按关机。。。 |
人中狼 发表于 2024-8-20 13:05 我能想通,但是代码搞不定. 标志位就是断电那个状态怎么读取出来. 之前有人发了一个帖子,,当时我还不懂啥意思,都已经断电了.为啥还要在断电的时候开启睡眠模式. 现在懂了.是让电容继续给单片机供电 |
咋看都象是一个按键实现开机、关机、调亮度的功能。。。 |
lkc8210 发表于 2024-8-20 14:22 试了,试出来就是普通的eeprom读写switch里面的循环. 没有加电容实现不了那个半按.. |
楼主可以在MCU供电脚串一个二极管,MCU供电加个几微法的大电容,加二极管的目的就是防止开关断开后电容给后级供电,只要满足电容只给MCU供电,即使外部电源断了,几微法的电容也可以维持几秒钟时间,这时候你就可以做些判断保存数据的动作 |
vb2002 发表于 2024-8-20 10:42 试了我的代码了吗? |
感觉你这个想复杂了吧,跟普通手电操作一样,只不过增加一个标志而已 |
vb2002 发表于 2024-8-20 10:42 断电了,单片机就没有用了,就没有"断电时间"这个概念了 如果要有记忆功能,就只能是重新关机开机,再关机开机换挡 没有别的选择了,除非换开关种类 |
Y_G_G 发表于 2024-8-19 13:03 手电开关有两种. 你说的那种是电子开关的.可以长期不断电.不设计eeprom也可以保存档位 我说的这个是机械开关,就是开关装在尾部,依靠断电通电来开关手电的 市面销售的开关逻辑是, 123档,现在我调到2档,关机,下次开机也是2档. 如果想换挡,就开机关机(时间低于500ms就换挡到3档) 如果超过500ms就还是2档 现在我能实现的就是,开机 2档,超过3秒就eeprom保存当前2档,,如果开机3秒内在关机开机.那就进行换挡. 虽然都能达到目的, 但是我这个有点麻烦,如果开机超过3秒后,需要换挡,必须重新关机开机,再关机开机换挡. 如果您感兴趣,发视频给您看看? |
首先,你要清楚你的要求是什么,在我的印象中,没有什么手电是对关机断电时长有要求的 按照正常的实际情况操作是这样的: 1,先看你18650是怎么接在电路上的,如果是焊线的,那就不需要用到EEPROM,直接保存到一个全局变量就可以了,如果涉及充电,这个变量就得有三个工作模式:1点灯,2充电,3关机 STC进入掉电模式,唤醒后全局变量的值是不会变的 2,如果电池是可以拿出来的那种,那就是每次按下按键,点灯模式切换后就把点灯模式保存到EEPROM,下次开机时,先读取EEPROM的模式,再进行点灯 但有一点要记得,STC的是"EEPROM"是FLASH,不是像24C01那种的,百度一下就知道了 |
明日之星8 发表于 2024-8-16 16:41 这个不符合实际情况啊 实际情况就是一个18650电池, 加一个灯珠,中间有个驱动. 再要去弄其他电池麻烦哦. |
本帖最后由 明日之星8 于 2024-8-16 17:38 编辑 加二极管和电池(比如2032电池),检测到无外接供电时单片机 就进入掉电模式,同时打开掉电唤醒定时器并计时。 比如STC8H1K08可以做到2微安,2032电池可以连续计时三到五年以上, 时间误差不到10% 有RTC功能的单片机(比如STC8H1K08T),外接32k晶振可以做到相对精确的计时。 |
飞云居士 发表于 2024-8-15 12:35 感觉这个像是ai写的. 而且里面提到的是3秒 |
根据提供的描述,我们需要编写一段C51代码来实现以下功能: 按下开关开机,再次按下关机,这个过程中PWM亮度保持不变,即只读取EEPROM中的值。 如果在开机状态下,半按(断电时间小于500ms)则进入下一个状态,切换PWM的占空比,实现4个档位的循环切换。 如果关机时长大于3秒,则写入当前的PWM占空比到EEPROM;如果小于3秒,则写入新的EEPROM值。 如果关机后马上开机,不进行任何操作。 下面是一段简化的C51代码示例,用于实现上述功能。请注意,这只是一个基础示例,实际应用中可能需要根据具体的硬件和EEPROM库进行调整。 #include <reg51.h> #define PWM_PIN P1 // 假设PWM控制引脚连接到P1端口 #define BUTTON_PIN P3_2 // 假设按钮连接到P3.2端口 #define EEPROM_ADDR 0x30 // 假设EEPROM写入地址 unsigned char pwm_duty = 10; // PWM占空比 unsigned char pwm_level = 0; // 当前PWM级别 unsigned char eeprom_value = 0; // 从EEPROM读取的值 bit is_power_on = 0; // 电源状态标志 void DelayMs(unsigned int ms) { // 延时函数,需要根据实际的晶振频率调整 // 这里只是一个示例,具体实现需要根据硬件来编写 } void SetPWM(unsigned char duty) { // 设置PWM占空比的函数 // 这里只是一个示例,具体实现需要根据硬件来编写 } void EEPROMWrite(unsigned char addr, unsigned char value) { // 写入EEPROM的函数 // 这里只是一个示例,具体实现需要根据EEPROM库来编写 EERDB = value; // 设置EEPROM数据寄存器 EEMPE = 1; // 允许EEPROM编程 EENH = 0; // 选择高8位地址 EEL = 1; // 选择低8位地址 EEAR = addr; // 设置EEPROM地址寄存器 EEWE = 1; // 写入使能 EEWE = 0; // 清除写入使能 } unsigned char EEPROMRead(unsigned char addr) { // 从EEPROM读取的函数 EEAR = addr; // 设置EEPROM地址寄存器 EEN2 = 1; // 启用EEPROM EEN1 = 1; EEN0 = 1; unsigned char value = EERDB; // 读取数据 EEN2 = 0; EEN1 = 0; EEN0 = 0; return value; } void main() { SetPWM(eeprom_value); // 初始设置PWM为EEPROM中的值 while(1) { if (!BUTTON_PIN) { // 检测按钮是否被按下 DelayMs(20); // 消抖 if (!BUTTON_PIN) { if (is_power_on) { // 关机操作 unsigned int shutdown_time = 0; while (!BUTTON_PIN) { shutdown_time++; if (shutdown_time > 3000) { // 大于3秒 EEPROMWrite(EEPROM_ADDR, pwm_duty); break; } } SetPWM(0); // 关闭PWM is_power_on = 0; } else { // 开机操作 is_power_on = 1; SetPWM(pwm_duty); // 根据EEPROM设置PWM } } } else { if (is_power_on) { // 半按操作,切换PWM占空比 DelayMs(500); // 等待500ms if (BUTTON_PIN) { pwm_level++; if (pwm_level > 3) { pwm_level = 0; } pwm_duty = (pwm_duty + 20) % 101; // 增加20%,循环4个级别 SetPWM(pwm_duty); } } } } } |
vb2002 发表于 2024-8-13 10:01
|
lkc8210 发表于 2024-8-12 10:30 能否提供一份代码? 我做的另一个手电是 要开机3秒才能判定是否eeprom保存 |
wufa1986 发表于 2024-8-12 08:09 可以提供一份代码给我吗? 谢谢 |
wufa1986 发表于 2024-8-12 08:09 用哪个比较方便呢? 我见很多手电用的都是九齐或者应广 |
如果要测关机时间就要加电容电阻来检测掉电时间 上电时引脚输入模式,检测电容电平, 检测完后引脚转为输出模式对电容充电 电容并联一个电阻来让电容在关电时放电 |
我做过电筒一段时间,这个需要硬件判断关机时间,STC做这种功能不是很方便,需要的硬件比较多 |