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]