找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 964|回复: 13
打印 上一主题 下一主题
收起左侧

STC单片机程序问题请教 功能类似电蚊香加热器

[复制链接]
跳转到指定楼层
楼主
ID:1001745 发表于 2023-8-28 13:39 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
各位大神,现在从某开源平台找了一个开源案例DIY,功能类似电蚊香加热器。
现在问题是:这个产品一上电就会自动开启加热,我想改成手动开启加热,目前没有找到从程序哪个地方更改。
恳请大神帮忙看看。以下是源码
单片机源程序如下:
#include <STC8G.H>
#include <eeprom.h>
#include <ntc.h>

#define uint8_t unsigned char
#define uint16_t unsigned int
#define uint32_t unsigned long
#define int8_t char
#define int16_t int
#define int32_t int long

sbit KEY=P3^2;
sbit NTC=P3^3;
sbit LED=P5^4;
sbit PWM=P5^5;

uint8_t idata run_mode = 0;

void Timer0_Init(void)                //1毫秒@12.000MHz
{
        AUXR &= 0x7F;                        //定时器时钟12T模式
        TMOD &= 0xF0;                        //设置定时器模式
        TL0 = 0x18;                                //设置定时初始值
        TH0 = 0xFC;                                //设置定时初始值
        TF0 = 0;                                //清除TF0标志
        TR0 = 1;                                //定时器0开始计时
        ET0 = 1;                                //使能定时器0中断
}

void Timer1_Init(void)        //仅记录时间用于测温
{
        AUXR &= 0xBF;                //定时器时钟12T模式
        TMOD &= 0x0F;                //设置定时器模式
        TMOD |= 0x10;                //设置定时器模式
        TL1 = 0;                        //设置定时初始值
        TH1 = 0;                        //设置定时初始值
        TF1 = 0;                        //清除TF1标志
        ET1 = 1;                        //使能定时器0中断
}

void Int1_Init()
{
    IT1 = 1;                        //使能INT1下降沿中断
    EX1 = 1;                        //使能INT1中断
}

void GPIO_init()
{
        P3M1 = 0xFB;        //按键准双向
        
        P5M1 = 0xDF;        //LED开漏
        P5M0 = 0x30;        //PWM推挽
}

static uint16_t save_tick = 0;        //安全计时
void pwm_scan()
{
        static uint8_t i = 0;
        static uint8_t duty_cycle = 10;
        uint8_t ntc_temp;
        
        i++;
        if(i >= 200)//200分频,当100分频时部分充电宝因负载脉宽过小而休眠
                i = 0;
        
        if(run_mode != 1)//非运行状态
        {
                if(PWM == 0)
                {
                        PWM = 1;        //关机
                        TR1 = 1;        //定时器1开始计时
                }
                NTC_reset();
                return;
        }
        
        if(duty_cycle < 10)                        //最小占空比为5%
                duty_cycle = 10;
        if(duty_cycle > 190)                //最大占空比为95%
                duty_cycle = 190;
        
        if(i == 0)//启动
        {
                PWM = 0;
        }
        else if(i == 1)//开始1ms开始分段运行
        {
                ntc_temp = NTC_get_temp();
                if(ntc_temp < 10)
                        run_mode = 2;
                else if(ntc_temp < 85)
                        duty_cycle = 190;
                else if(ntc_temp < 95)
                        duty_cycle = 160;
                else if(ntc_temp < 105)
                        duty_cycle = 130;
                else if(ntc_temp < 120)
                {
                        duty_cycle = 50;
                        save_tick = 0;
                }
                else                                //大于120度,异常状况
                {
                        save_tick = 0;
                        run_mode = 2;
                }
                save_tick++;
                if(save_tick > 900)//持续3分钟达不到目标温度,异常状况
                {
                        save_tick = 0;
                        run_mode = 2;
                }
        }
        else if(i == duty_cycle)
        {
                if(PWM == 0)
                {
                        PWM = 1;        //关机
                        TR1 = 1;        //定时器1开始计时
                }
        }
}

uint8_t get_key_state()
{
        static uint16_t idata event_tick=0;
        static uint16_t idata sw_num=0;
        uint8_t out_temp=0;
        
        if(KEY==0)        //如果IO被拉低
        {
                sw_num++;
                if(sw_num==5)
                {
                        event_tick/=1000;
                        event_tick++;
                        event_tick*=1000;//保留千位
                        return 0xFE;        //按下事件
                }
        }
        else
        {
                if(sw_num>=5)
                {
                        sw_num=0;
                        return 0xFF;        //松开事件
                }
                sw_num=0;
        }
        
        if(event_tick)                        //连击事件处理
        {
                event_tick++;
                if(event_tick%1000==500)
                {
                        if(sw_num==0)        //松开时才会触发连击事件
                                out_temp=event_tick/1000;
                        event_tick=0;
                }
        }
        return out_temp;
}


uint8_t idata ms_tick=0;
void whit_ms()
{
        static uint8_t idata tick=0;
        
        while(tick == ms_tick)
                PCON |= 1;        //sleep
        tick++;
        
        pwm_scan();
}

void main()
{
        uint16_t idata sec_div1000 = 0;
        uint16_t idata sec_countdown = 0;
        uint8_t key_temp;
        
        GPIO_init();
        Timer0_Init();
        Timer1_Init();
        Int1_Init();
        
        EA=1;
        while(1)
        {
                whit_ms();
                key_temp = get_key_state();
                switch(key_temp)
                {
                        case 1:
                                if(run_mode)        //正在运行,则关机
                                {
                                        sec_countdown = 0;
                                        run_mode = 0;
                                }
                                else                        //读取历史记录
                                {
                                        sec_countdown = (get_new_data() + 2) * (2 * 60 *60);//对应4~12小时,还有一直运行
                                        run_mode = 1;
                                        save_tick = 0;
                                }
                                break;
                        case 2:
                        case 3:
                        case 4:
                        case 5:
                        case 6:
                        case 7:
                                save_new_data(key_temp - 2);        //保存数据
                        
                                sec_countdown = key_temp * (2 * 60 *60);//对应4~12小时,还有一直运行
                                run_mode = 1;
                                break;
                }
               
                sec_div1000++;
                if(sec_div1000>=1000)//每秒执行一次
                {
                        sec_div1000=0;
                        if(sec_countdown > 0 && sec_countdown < 50000)//0~13小时内则倒计时
                        {
                                sec_countdown--;
                                if(sec_countdown == 0)//倒计时结束
                                {
                                        run_mode = 0;
                                }
                        }
                }
                switch(run_mode)
                {
                        case 0:        //停止关灯
                                LED = 1;
                                break;
                        case 1:        //运行常亮
                                LED = 0;
                                break;
                        case 2:        //错误闪烁
                                LED = sec_div1000 > 500 ? 1: 0;
                                break;
                }
        }
}

void Timer0_Isr() interrupt 1
{
        ms_tick++;
}

void INT1_Isr() interrupt 2
{
        TR1 = 0;        //定时器1停止计时
        
    NTC_updata((TH1 << 8) | TL1);
        
        TL1 = 0;
        TH1 = 0;        //清零时间计数
}

void Timer1_Isr() interrupt 3
{
        TF1 = 0;                //清除TF1标志
        TR1 = 0;                //定时器1停止计时
        run_mode = 2;        //正常测温不会进入T1中断
}

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:1040201 发表于 2023-8-28 16:02 | 只看该作者
有原理图才好分析,我看PWM=1时 是关机,你在GPIO初始化的时候 赋值一下。
回复

使用道具 举报

板凳
ID:1006814 发表于 2023-8-28 16:35 | 只看该作者

是立创开源广场里的STC电热蚊香加热器吗?
回复

使用道具 举报

地板
ID:1006814 发表于 2023-8-28 16:38 | 只看该作者
貌似按了一次开关后,才能工作。
回复

使用道具 举报

5#
ID:123289 发表于 2023-8-28 16:48 | 只看该作者
1、找到加热的接口(IO)。
2、做一个控制输出的标记KZ。
3、当KZ=1时,让IO口恒定输出为关逻辑。当KZ=0时,让IO口为原定的输出,即加热。
4、做一个选择键,根据健入状态,决定KZ值。

回复

使用道具 举报

6#
ID:276663 发表于 2023-8-28 17:48 | 只看该作者
程序如果上电是运行,按一下按键是关闭的话,你可以把输出脚做个电平取反电路。
回复

使用道具 举报

7#
ID:1001745 发表于 2023-8-29 08:40 | 只看该作者
liucan2020 发表于 2023-8-28 16:02
有原理图才好分析,我看PWM=1时 是关机,你在GPIO初始化的时候 赋值一下。

是的,用的是PMOS,PWM=1才是关机。
回复

使用道具 举报

8#
ID:1001745 发表于 2023-8-29 08:41 | 只看该作者
hb_lhw 发表于 2023-8-28 16:35
是立创开源广场里的STC电热蚊香加热器吗?

是的,就是这个。V1.0版本应该是需要开关开启才工作的。可是我写进去之后一上电就开启加热了
回复

使用道具 举报

9#
ID:1001745 发表于 2023-8-29 08:41 | 只看该作者
hb_lhw 发表于 2023-8-28 16:38
貌似按了一次开关后,才能工作。

实际却是一上电就开启加热了
回复

使用道具 举报

10#
ID:1001745 发表于 2023-8-29 08:42 | 只看该作者
yzwzfyz 发表于 2023-8-28 16:48
1、找到加热的接口(IO)。
2、做一个控制输出的标记KZ。
3、当KZ=1时,让IO口恒定输出为关逻辑。当KZ=0 ...

好的,我来试试
回复

使用道具 举报

11#
ID:1001745 发表于 2023-8-29 08:45 | 只看该作者
IdeaMing 发表于 2023-8-28 17:48
程序如果上电是运行,按一下按键是关闭的话,你可以把输出脚做个电平取反电路。

if(PWM == 0)
                {
                        PWM = ~1;        //关机
                        TR1 = 1;        //定时器1开始计时
                }
是这样吗?
回复

使用道具 举报

12#
ID:276663 发表于 2023-8-30 10:43 | 只看该作者
mcuhui 发表于 2023-8-29 08:45
if(PWM == 0)
                {
                        PWM = ~1;        //关机

硬件非门电路
回复

使用道具 举报

13#
ID:1092275 发表于 2023-8-30 13:47 | 只看该作者
hb_lhw 发表于 2023-8-28 16:38
貌似按了一次开关后,才能工作。

实际却是一上电就开启加热了
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表