|
这是一个以前做的小玩意,看到现在有人发LED灯的电路就拿出来给需要的参考一下。
电路功能:单锂3WLED恒流驱动,3.0V-4.2V全程恒流,最大可输出700mA(实际可达1000mA);
四种档位模式:1.三档调光+暴闪+慢闪+SOS+信标;
2.三档调光+暴闪+SOS;
3.二档调光;
4.六档调光+暴闪+慢闪+SOS+信标;
有记忆功能;
只有一个电源开关控制,关机关电源,完全不耗电;
电池过放保护,电压低于3V进入应急模式自动切换到30mA,电压低于2.7V进入休眠模式。
(原文件名:3454.jpg)
有两种不同的代码,开机记忆或关机记忆
/*****************************************************
Chip type : ATtiny13
Clock frequency : 4.800000 MHz
Memory model : Tiny
External SRAM size : 0
Data Stack size : 16
四组档位模式,关闭2秒记忆
*****************************************************/
//#define DEBUG2
//#define debug
#include <tiny13.h>
#include <delay.h>
#define CHANGE_WAITING 62
#define MAX_CURRENT 920
#define VOLTAGE_LIMIT_TO_30mA 5233 //5233=3.2V 4812=3.0V
#define VOLTAGE_OUT_OFF 4331 //4331=2.7V
#define VOLTAGE_CHANGE 1000 //定义开机后是否变换档位的电压值,如大于此值则变换档位,否则用上次关机时的档位
#define K1 318682 //由于3454在压控恒流模式工作时输出电流会随电池电压降低而升高,为了做到真正的恒流,引入K1、K2根据电池电压对控制电压进行修正。
#define K2 341
#define XINGBIAO 3
#define MAX_DANGWEI 9
#define ADEN ADCSRA.7
#define ADSC ADCSRA.6
#define EN_30mA PORTB.5
#define EN_PWM PORTB.1
#define WDCE 4
#define WDE 3
eeprom unsigned char null;
eeprom unsigned char circle=2;
flash unsigned char time_set[3][18]=
{
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, // bao frash
{16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16}, // flash
{4,8,4,8,4,25,12,8,12,8,12,25,4,8,4,8,4,50} // sos 亮(0.5秒)-〉暗(1秒)-〉亮(0.5秒)-〉暗(1秒)-〉亮(0.5秒)-〉暗(3.5秒)-〉亮(1.5秒)-〉暗(1秒)-〉亮(1.5秒)-〉暗(1秒)-〉亮(1.5秒)-〉暗(3.5秒)-〉亮(0.5秒)-〉暗(1秒)-〉亮(0.5秒)-〉暗(1秒)-〉亮(0.5秒)-〉暗(3.5秒)
};
flash unsigned int i_set[MAX_DANGWEI+1]=
{
920,
700,
700,
50, //xingbiao
920,
700,
480,
348,
135,
20
};
bit flashing_on_off;
bit adc_busy;
bit check_change_circle;
unsigned char temp;
unsigned char lower_times;
unsigned char time_flash,frash_count;
// Watchdog timeout interrupt service routine
interrupt [WDT] void wdt_timeout_isr(void)
{
if( temp!=XINGBIAO)
{
time_flash++;
WDTCR|=0x40;
if( temp<3)
{
if(time_flash>time_set[temp][frash_count])
{
time_flash=0;
frash_count++;
if(frash_count>17)
{
frash_count=0;
flashing_on_off=1;
}
else
flashing_on_off=~flashing_on_off;
}
}
}
}
#ifndef DEBUG2
// ADC interrupt service routine
interrupt [ADC_INT] void adc_isr(void)
{
unsigned int adc_result;
adc_result=10*ADCW;
if(check_change_circle==1)
{
check_change_circle=0;
if(adc_result>VOLTAGE_CHANGE)
{
temp++;
switch (PINB&0x18)
{
case 0x08: //PB4 接地,三档调光+暴闪+慢闪+SOS+信标
{
if(temp>4)
temp++;
}break;
case 0x10: //PB3 接地, 三档调光+暴闪+SOS
{
temp++;
}break;
case 0x00: //PB3、PB4 接地,二档调光
{
temp=temp==5?7:4;
}break;
default: break; //没有连接,六档调光+暴闪+慢闪+SOS+信标
}
if(temp>MAX_DANGWEI)
temp=0;
circle=temp;
}
}
if(adc_result<VOLTAGE_OUT_OFF)
{
EN_PWM=0;
#ifndef debug
EN_30mA=0;
#endif
}
else
{
if(adc_result<VOLTAGE_LIMIT_TO_30mA)
{
lower_times++;
if(lower_times>10)
{
TCCR0B=0x00;
EN_PWM=0;
#ifndef debug
EN_30mA=flashing_on_off;
#endif
}
}
else
{
lower_times=0;
EN_PWM=flashing_on_off;
#ifndef debug
EN_30mA=0;
#endif
OCR0A=(unsigned char)((K1-(unsigned long)K2*i_set[temp])/(adc_result));
}
}
adc_busy=0;
}
#endif
// Timer 0 output compare A interrupt service routine
interrupt [TIM0_COMPA] void timer0_compa_isr(void)
{
if(adc_busy==0)
{
ADSC=1;
adc_busy=1;
}
}
void main(void)
{
#pragma optsize-
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
//PORTB=0x19;
//DDRB=0x23;
flashing_on_off=1;
lower_times=0;
time_flash=0;
frash_count=0;
#asm("sei")
temp=circle;
TIMSK0=0x04;
DIDR0=0x0F;
ADMUX=0x41;
ADCSRA=0x8D;
#pragma optsize-
WDTCR |= (1<<WDCE) | (1<<WDE);
WDTCR=0x41; //64ms
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
OCR0A=200;
TCCR0A=0x83;
TCCR0B=0x01;
check_change_circle=1;
ADSC=1;
adc_busy=1;
while(check_change_circle==1)
;
delay_ms(1);
while (1)
{
if(temp==XINGBIAO)
{
EN_30mA=1;
delay_ms(50);
EN_30mA=0;
#pragma optsize-
WDTCR |= (1<<WDCE) | (1<<WDE);
WDTCR=0x60; //4s
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
MCUCR=0x20;
#asm("sleep");
#asm("NOP");
}
}
}
/*****************************************************
Chip type : ATtiny13
Clock frequency : 4.800000 MHz
Memory model : Tiny
External SRAM size : 0
Data Stack size : 16
四组档位模式,两秒连续内按开关换档,点亮超过2秒记忆当前档,
*****************************************************/
//#define DEBUG2
//#define debug
#include <tiny13.h>
#include <delay.h>
#define CHANGE_WAITING 62
#define MAX_CURRENT 920
#define VOLTAGE_LIMIT_TO_30mA 5233 //5233=3.2V 4812=3.0V
#define VOLTAGE_OUT_OFF 4331 //4331=2.7V
#define K1 333167 //由于3454在压控恒流模式工作时输出电流会随电池电压降低而升高,为了做到真正的恒流,引入K1、K2根据电池电压对控制电压进行修正。
#define K2 292
#define XINGBIAO 3
#define MAX_DANGWEI 9
#define ADEN ADCSRA.7
#define ADSC ADCSRA.6
#define EN_30mA PORTB.5
#define EN_PWM PORTB.1
#define WDCE 4
#define WDE 3
eeprom unsigned char null;
eeprom unsigned char change_needed=0;
eeprom unsigned char circle=2;
flash unsigned char time_set[3][18]=
{
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, // bao frash
{16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16}, // flash
{4,8,4,8,4,25,12,8,12,8,12,25,4,8,4,8,4,50} // sos 亮(0.5秒)-〉暗(1秒)-〉亮(0.5秒)-〉暗(1秒)-〉亮(0.5秒)-〉暗(3.5秒)-〉亮(1.5秒)-〉暗(1秒)-〉亮(1.5秒)-〉暗(1秒)-〉亮(1.5秒)-〉暗(3.5秒)-〉亮(0.5秒)-〉暗(1秒)-〉亮(0.5秒)-〉暗(1秒)-〉亮(0.5秒)-〉暗(3.5秒)
};
flash unsigned int i_set[MAX_DANGWEI+1]=
{
650,
650,
650,
50, //xingbiao
1000,
750,
520,
350,
180,
50
};
bit flashing_on_off;
bit adc_busy;
unsigned char temp;
unsigned char time,lower_times;
unsigned char time_flash,frash_count;
// Watchdog timeout interrupt service routine
interrupt [WDT] void wdt_timeout_isr(void)
{
if( temp!=XINGBIAO)
{
time_flash++;
WDTCR|=0x40;
if(time<CHANGE_WAITING)
time++;
else
{
if(change_needed!=0)
change_needed=0;
}
if( temp<3)
{
if(time_flash>time_set[temp][frash_count])
{
time_flash=0;
frash_count++;
if(frash_count>17)
{
frash_count=0;
flashing_on_off=1;
}
else
{
flashing_on_off=~flashing_on_off;
}
}
}
}
}
#ifndef DEBUG2
// ADC interrupt service routine
interrupt [ADC_INT] void adc_isr(void)
{
unsigned int adc_result;
adc_result=10*ADCW;
{
if(adc_result<VOLTAGE_OUT_OFF)
{
EN_PWM=0;
#ifndef debug
EN_30mA=0;
#endif
}
else
{
if(adc_result<VOLTAGE_LIMIT_TO_30mA)
{
lower_times++;
if(lower_times>10)
{
TCCR0B=0x00;
EN_PWM=0;
#ifndef debug
EN_30mA=flashing_on_off;
#endif
}
}
else
{
lower_times=0;
EN_PWM=flashing_on_off;
#ifndef debug
EN_30mA=0;
#endif
if(flashing_on_off==0)
{
OCR0A=200;
}
else
{
OCR0A=(unsigned char)((K1-(unsigned long)K2*i_set[temp])/(adc_result));
}
}
}
}
adc_busy=0;
}
#endif
// Timer 0 output compare A interrupt service routine
interrupt [TIM0_COMPA] void timer0_compa_isr(void)
{
if(adc_busy==0)
{
ADSC=1;
adc_busy=1;
}
}
void main(void)
{
#pragma optsize-
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
//PORTB=0x19;
//DDRB=0x23;
TCCR0A=0x83;
flashing_on_off=1;
time=0;
lower_times=0;
time_flash=0;
frash_count=0;
#asm("sei")
temp=circle;
if(change_needed==0)
{
change_needed=1;
}
else
{
temp++;
switch (PINB&0x18)
{
case 0x08: //PB4 接地,三档调光+暴闪+慢闪+SOS+信标
{
if(temp>4)
temp++;
}break;
case 0x10: //PB3 接地, 三档调光+暴闪+SOS
{
temp++;
}break;
case 0x00: //PB3、PB4 接地,二档调光
{
temp=temp==5?7:4;
}break;
default: break; //没有连接,六档调光+暴闪+慢闪+SOS+信标
}
if(temp>MAX_DANGWEI)
temp=0;
circle=temp;
}
if(temp!=XINGBIAO)
{
//GIMSK=0x20;
//PCMSK=0x10;
//GIFR=0x20;
TIMSK0=0x04;
DIDR0=0x0F;
ADMUX=0x41;
ADCSRA=0x8D;
#pragma optsize-
WDTCR |= (1<<WDCE) | (1<<WDE);
WDTCR=0x41; //64ms
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
OCR0A=250;
TCCR0B=0x01;
delay_ms(5);
adc_busy=0;
}
while (1)
{
if(temp==XINGBIAO)
{
EN_30mA=1;
delay_ms(100);
EN_30mA=0;
#pragma optsize-
WDTCR |= (1<<WDCE) | (1<<WDE);
WDTCR=0x60; //4s
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
MCUCR=0x20;
#asm("sleep");
#asm("NOP");
}
}
}
程序中系数K1、K2计算:
(原文件名:1.jpg)
再来一个应急充,
功能:手机充电,1.0V到4.5V电池通吃
可以电池过放保护,也可以取消保护榨干干电池。
还可以测量电池电压并显示。
不计成本,效果绝非地摊上能买到的可比。
(原文件名:sch.jpg)
源码,读以下就可以知道操作方法了
/*****************************************************
This program was produced by the
CodeWizardAVR V2.03.9 Standard
Automatic Program Generator
?Copyright 1998-2008 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com
Project :
Version :
Date : 2009-4-3
Author : user
Company : Dell
Comments:
Chip type : ATtiny13
AVR Core Clock frequency: 4.800000 MHz
Memory model : Tiny
External RAM size : 0
Data Stack size : 24
REF=1.07V
*****************************************************/
#include <tiny13.h>
#include <delay.h>
#define DEBUG 0
#define OUT_ENABLE PORTB.0
#define KEY_CHECK PINB.2
#define BOOST_ENABLE PORTB.3
#define OUTPUT_VOLTAGE_SELECT PORTB.1
#if !DEBUG
#define LED_OUT PORTB.5
#define LED_ON 0
#define LED_OFF 1
#endif
#define WDCE 4
#define WDE 3
#define ADEN ADCSRA.7
#define ADSC ADCSRA.6
volatile unsigned char temp_v[16];
volatile unsigned char Count;
volatile unsigned char Real_voltage;
volatile unsigned char System_states;
unsigned char Shut_up_voltage;
unsigned int Worked_timer_count;
bit adc_busy;
bit enable_lower_voltage_protect;
unsigned char Lower_voltage_checked_times;
interrupt [PCINT0] void pin_change_isr(void)
{
unsigned char i=0;
while(KEY_CHECK==0)
{
i++;
delay_ms(10);
if(i==250)//if(KEY_CHECK==1||i==250)
{
break;
}
}
if(i>=200) //按钮按下时间大于2秒 ,启动或关闭输出
{
if(System_states!=2)
{
System_states=2;
Worked_timer_count=0;
}
else
{
System_states=0;
}
}
else //按钮按下时间小于2秒 ,启动或关闭放电低电压保护,并显示空载电压值及低电压保护值
{
if(i>=5)
{
if(System_states!=2)
{
System_states=1;
enable_lower_voltage_protect=~enable_lower_voltage_protect;
}
}
}
}
// Watchdog timeout interrupt service routine
//interrupt [WDT] void wdt_timeout_isr(void)
// Timer 0 output compare A interrupt service routine
interrupt [TIM0_COMPA] void timer0_compa_isr(void)
{
if(adc_busy==0)
{
ADSC=1;
adc_busy=1;
}
}
// ADC interrupt service routine
interrupt [ADC_INT] void adc_isr(void)
{
unsigned char i;
unsigned int temp;
temp_v[Count]=ADCH;
Count++;
if(Count>15)
{
Worked_timer_count++;
Count=0;
temp=0;
for(i=0;i<16;i++)
{
temp+=(unsigned int)temp_v;
}
Real_voltage=(unsigned char)(((unsigned long )temp*1531)/100000);
if(Real_voltage<Shut_up_voltage||Worked_timer_count>=22500) //电池电压低或约一小时后关闭输出
{
Lower_voltage_checked_times++;
if(Lower_voltage_checked_times>3) //连续三次采样都低于保护值
{
System_states=0;
BOOST_ENABLE =0;
OUT_ENABLE=1;
#if !DEBUG
LED_OUT=LED_OFF;
#endif
}
}
else
{
Lower_voltage_checked_times=0;
}
}
adc_busy=0;
}
//************************************************
//显示数值,长闪次数为十位数值,短闪次数为个位数值
//************************************************
void display_value(unsigned char value)
{
#if !DEBUG
unsigned char i;
unsigned char temp;
temp=value/10;
for(i=0;i<temp;i++)
{
LED_OUT=LED_OFF;
delay_ms(200);
LED_OUT=LED_ON;
delay_ms(500);
}
temp=value%10;
for(i=0;i<temp;i++)
{
LED_OUT=LED_OFF;
delay_ms(500);
LED_OUT=LED_ON;
delay_ms(100);
}
LED_OUT=LED_OFF;
#endif
}
void main(void)
{
// Input/Output Ports initialization
// Port B initialization
// Func5=Out Func4=In Func3=Out Func2=In Func1=Out Func0=Out
// State5=1 State4=T State3=0 State2=P State1=0 State0=1
PORTB=0x25;
DDRB=0x2B;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=FFh
// OC0A output: Disconnected
// OC0B output: Disconnected
// actual value: 10.027mSec (-0.3%)
OCR0A = 0xBB;
TCCR0A = 0x02;
TCCR0B = 0x04; //start timer
TIMSK0 = 0x04; //timer interrupt sources
// External Interrupt(s) initialization
// INT0: Off
// Interrupt on any change on pins PCINT0-5: On
GIMSK=0x20;
MCUCR=0x00;
PCMSK=0x04;
GIFR=0x20;
DIDR0|=0x10;
ADMUX=0x62;
//ADMUX=0x22;
ADCSRA=0x8D;
// Analog Comparator initialization
// Analog Comparator: Off
ACSR=0x80;
ADCSRB=0x00;
#asm("sei")
System_states=1;
enable_lower_voltage_protect=0;
while (1)
{
switch(System_states)
{
case 1:
{
Count=0;
OUTPUT_VOLTAGE_SELECT=0;
BOOST_ENABLE = 1;
OUT_ENABLE=1;
#if !DEBUG
LED_OUT=LED_ON;
#endif
delay_ms(1000);
display_value(Real_voltage); //显示电池空载电压(实际带载约10mA)
if(!enable_lower_voltage_protect)
{
if(Real_voltage>=31) //大于3.1V,低电压保护值设为2.8V(带载时),用于锂电池过放保护
{
Shut_up_voltage=28;
}
else
{
if(Real_voltage>=20) //大于2.0V,低电压保护值设为1.0V(带载时), 用于2x镍电池过放保护
{
Shut_up_voltage=10;
}
else
{
Shut_up_voltage=4; //小于2.0V,低电压保护值设为0.4V(带载时), 用于1x镍电池过放保护
}
}
}
else
{
Shut_up_voltage=0; //如果不启用过放保护,低电压保护值设为0.0V,用于非可充电池
}
delay_ms(1000);
display_value(Shut_up_voltage); //显示低电压保护值
System_states=0;
}break;
case 2:
{
OUTPUT_VOLTAGE_SELECT=1;
BOOST_ENABLE =1;
OUT_ENABLE=0;
display_value(Real_voltage); //显示带载电池电压
delay_ms(3000);
}break;
default: //未启动输出,进入休眠
{
Worked_timer_count=0;
BOOST_ENABLE =0;
OUT_ENABLE=1;
#if !DEBUG
LED_OUT=LED_OFF;
#endif
#pragma optsize-
MCUCR=0x20;
#asm("sleep");
#asm("NOP");
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
}break;
}
};
} |
|