wpppmlah 发表于 2026-3-3 09:37:58

LED调光-STC8H1K08A-驱动12V灯板

灯板灯珠是3V,4串3并,电源24V2A(很亮)。电路是JLC开源的,附件附带原作者的固件(无源码),可以直接使用。后又根据电路写了一个四档高光的代码并带有档位断电记忆功能,无温度开启风扇功能,有需要的可以自行修改代码加上。






//stc8g1k08a   EEPROM 空间为 4K(0000h~0FFFh)

#include "reg51.h"
#include "intrins.h"

sfr   CCON    =   0xd8;
sbit    CF      =   CCON^7;
sbit    CR      =   CCON^6;
sbit    CCF2    =   CCON^2;
sbit    CCF1    =   CCON^1;
sbit    CCF0    =   CCON^0;
sfr   CMOD    =   0xd9;
sfr   CL      =   0xe9;
sfr   CH      =   0xf9;
sfr   CCAPM0=   0xda;
sfr   CCAP0L=   0xea;
sfr   CCAP0H=   0xfa;
sfr   PCA_PWM0 =0xf2;
sfr   CCAPM1=   0xdb;
sfr   CCAP1L=   0xeb;
sfr   CCAP1H=   0xfb;
sfr   PCA_PWM1 =0xf3;
sfr   CCAPM2=   0xdc;
sfr   CCAP2L=   0xec;
sfr   CCAP2H=   0xfc;
sfr   PCA_PWM2 =0xf4;
sfr         P5          =         0xC8;
sfr   P0M1    =   0x93;
sfr   P0M0    =   0x94;
sfr   P1M1    =   0x91;
sfr   P1M0    =   0x92;
sfr   P2M1    =   0x95;
sfr   P2M0    =   0x96;
sfr   P3M1    =   0xb1;
sfr   P3M0    =   0xb2;
sfr   P4M1    =   0xb3;
sfr   P4M0    =   0xb4;
sfr   P5M1    =   0xc9;
sfr   P5M0    =   0xca;

sfr   IAP_DATA    =   0xC2;
sfr   IAP_ADDRH   =   0xC3;
sfr   IAP_ADDRL   =   0xC4;
sfr   IAP_CMD   =   0xC5;
sfr   IAP_TRIG    =   0xC6;
sfr   IAP_CONTR   =   0xC7;
sfr   IAP_TPS   =   0xF5;


//ADC sfr
sfr   ADC_CONTR   =   0xbc;
sfr   ADC_RES   =   0xbd;
sfr   ADC_RESL    =   0xbe;
sfr   ADCCFG      =   0xde;

sfr   P_SW2   =   0xba;
#define ADCTIM(*(unsigned char volatile xdata *)0xfea8)
#define ADC_POWER 0x80
#define ADC_START 0x40
char IapRead(int addr);//EEPROM读
void IapProgram(int addr, char dat);////EEPROM写
void IapErase(int addr);//EEPROM扇区擦除

#define uchar unsigned char
#define uint unsigned int

//定义按键引脚
sbit KEY_INC = P3^0;    //增加占空比按键
sbit KEY_DEC = P3^1;    //减小占空比按键
sbit PWM_IO =P5^4;

//定义PWM占空比档位(6个档位)
uchar pwm_level = 0;    //初始档位为0(0%占空比)

//占空比配置数组(8位PWM)
uint pwm_duty = {
    0xff,   // 0% 占空比 (8位PWM最大值)
    0xe9,   // 10% 占空比
    0xe0,   // 20% 占空比
    0xd0,   // 30% 占空比
   
    0x80    // 50% 占空比
};

//延时函数
void delay_ms(uint ms)
{
    unsigned char data i, j;
        unsigned int abcd;
    for (abcd = ms; abcd > 0; abcd--)
        {
                _nop_();
                _nop_();
                _nop_();
                i = 11;
                j = 190;
                do
                {
                        while (--j);
                } while (--i);
        }
}

//按键扫描函数
void key_scan()
{
    //检测增加按键
    if (KEY_INC == 0)
    {
      delay_ms(50);//去抖动
      if (KEY_INC == 0)
      {
            //单按操作:增加一个档位
            if (pwm_level < 4)//最大档位为4
            {
                pwm_level++;
                //更新PWM占空比
                CCAP2L = pwm_duty & 0xff;
                CCAP2H = pwm_duty & 0xff;
            }
            
            //检测是否为长按
            delay_ms(1000);//长按检测时间
            while (KEY_INC == 0)//如果按键仍然按下,进入长按模式
            {
                if (pwm_level < 4)//最大档位为4
                {
                  pwm_level++;
                  //更新PWM占空比
                  CCAP2L = pwm_duty & 0xff;
                  CCAP2H = pwm_duty & 0xff;
                  delay_ms(500);//调节间隔500ms
                }
                else
                {
                  //已达到最大档位,停止增加
                  delay_ms(500);//保持间隔时间
                }
            }
            
            //松开按键后保存当前占空比
            IapErase(0x0000);//先擦除扇区
            IapProgram(0x0000, pwm_level);
      }
    }
   
    //检测减小按键
    if (KEY_DEC == 0)
    {
      delay_ms(50);//去抖动
      if (KEY_DEC == 0)
      {
            //单按操作:减小一个档位
            if (pwm_level > 0)//最小档位为1(10%,不能为0)
            {
                pwm_level--;
                //更新PWM占空比
                CCAP2L = pwm_duty & 0xff;
                CCAP2H = pwm_duty & 0xff;
            }
            
            //检测是否为长按
            delay_ms(1000);//长按检测时间
            while (KEY_DEC == 0)//如果按键仍然按下,进入长按模式
            {
                if (pwm_level > 1)//最小档位为1(10%,不能为0)
                {
                  pwm_level--;
                  //更新PWM占空比
                  CCAP2L = pwm_duty & 0xff;
                  CCAP2H = pwm_duty & 0xff;
                  delay_ms(500);//调节间隔500ms
                }
                else
                {
                  //已达到最小档位,停止减小
                  delay_ms(500);//保持间隔时间
                }
            }
            
            //松开按键后保存当前占空比
            IapErase(0x0000);//先擦除扇区
            IapProgram(0x0000, pwm_level);
      }
    }
}
//unsigned intADCSCAN(void)
//{
//              ADC_CONTR |= 0x43;                      //启动AD转换 P3.3
//      _nop_();
//      _nop_();
//      while (!(ADC_CONTR & 0x20));            //查询ADC完成标志
//      ADC_CONTR &= ~0x20;                     //清完成标志
//      ADC_RES;                           //读取ADC结果

//}
unsigned intGetADCResult(BYTE ch)
{         
    unsigned int AdcTmp;
unsigned char         ADC_RES,ADC_RESL;
          AdcTmp=0;
      ADC_RES=0;
      ADC_RESL=0;
    ADC_CONTR = ADC_POWER| ch | ADC_START;
         Delay(500);
          while(~(ADC_CONTR|0xdf));//等待ADC转换完成
//                UartSend(ADC_RES);
//                UartSend(ADC_RESL);
    ADC_CONTR &= 0xdf;         //清完成标志
//      AdcTmp=(ADC_RES)<<2;
//      AdcTmp|=ADC_RESL;
        AdcTmp = ((u16)ADC_RES << 2) + (ADC_RESL & 0x03);
    return AdcTmp;               //返回ADC结果
      
}
void main()
{
    PWM_IO = 0;
        //配置端口模式
    P0M0 = 0x00;
    P0M1 = 0x00;
    P1M0 = 0x00;
    P1M1 = 0x00;
    P2M0 = 0x00;
    P2M1 = 0x00;
    P3M0 = 0x00;
    P3M1 = 0x08;//p33 高阻 ADC输入
    P4M0 = 0x00;
    P4M1 = 0x00;
//    P5M0 = 0x00;
//    P5M1 = 0x00;

   
    //配置P54引脚为推挽输出
    P5M1 &= ~(1 << 4);
    P5M0 |= (1 << 4);

    //从EEPROM读取占空比档位
    pwm_level = IapRead(0x0000);
    //检查读取值是否在有效范围内
    if (pwm_level > 5)
    {
      pwm_level = 0;//如果值无效,设置为默认值0(0%占空比)
      //保存默认值到EEPROM
      IapErase(0x0000);//先擦除扇区
      IapProgram(0x0000, pwm_level);
    }

    //初始化PCA模块2
    CCON = 0x00;
    CMOD = 0x08;                              //PCA时钟为系统时钟
    CL = 0x00;
    CH = 0x00;
   
    //配置PCA模块2为8位PWM模式(更稳定可靠)
    CCAPM2 = 0x42;                              //PCA模块2为PWM工作模式
    PCA_PWM2 = 0x00;                            //PCA模块2输出8位PWM
   
    //设置初始占空比
    CCAP2L = pwm_duty & 0xff;
    CCAP2H = pwm_duty & 0xff;
   
    CR = 1;                                     //启动PCA计时器
               
                //ADC INIT
    P_SW2 |= 0x80;                              //使能访问XFR
    ADCTIM = 0x3f;                              //设置ADC内部时序
    P_SW2 &= 0x7f;
    ADCCFG = 0x0f;                              //设置ADC时钟为系统时钟/2/16
    //ADC_CONTR = 0x80;                           //使能ADC模块


    while (1)
    {
      key_scan();//扫描按键
    }
}

void IapIdle()
{
    IAP_CONTR = 0;                              //关闭IAP功能
    IAP_CMD = 0;                              //清除命令寄存器
    IAP_TRIG = 0;                               //清除触发寄存器
    IAP_ADDRH = 0x80;                           //将地址设置到非IAP区域
    IAP_ADDRL = 0;
}

char IapRead(int addr)
{
    char dat;

    IAP_CONTR = 0x80;                           //使能IAP
    IAP_TPS = 12;                               //设置等待参数12MHz
    IAP_CMD = 1;                              //设置IAP读命令
    IAP_ADDRL = addr;                           //设置IAP低地址
    IAP_ADDRH = addr >> 8;                      //设置IAP高地址
    IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
    _nop_();
    dat = IAP_DATA;                           //读IAP数据
    IapIdle();                                  //关闭IAP功能

    return dat;
}

void IapProgram(int addr, char dat)
{
    IAP_CONTR = 0x80;                           //使能IAP
    IAP_TPS = 12;                               //设置等待参数12MHz
    IAP_CMD = 2;                              //设置IAP写命令
    IAP_ADDRL = addr;                           //设置IAP低地址
    IAP_ADDRH = addr >> 8;                      //设置IAP高地址
    IAP_DATA = dat;                           //写IAP数据
    IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
    _nop_();
    IapIdle();                                  //关闭IAP功能
}

void IapErase(int addr)
{
    IAP_CONTR = 0x80;                           //使能IAP
    IAP_TPS = 12;                               //设置等待参数12MHz
    IAP_CMD = 3;                              //设置IAP擦除命令
    IAP_ADDRL = addr;                           //设置IAP低地址
    IAP_ADDRH = addr >> 8;                      //设置IAP高地址
    IAP_TRIG = 0x5a;                            //写触发命令(0x5a)
    IAP_TRIG = 0xa5;                            //写触发命令(0xa5)
    _nop_();                                    //
    IapIdle();                                  //关闭IAP功能
}



重写代码:
原作者固件:
嘉利创专业版工程:
页: [1]
查看完整版本: LED调光-STC8H1K08A-驱动12V灯板