|
发表于 2007-8-18 12:43:53
|
显示全部楼层
偶是菜鸟,这是我用TINNY13控制1W大功率LED手电的程序,AD检测电压,3.1V保护锂电,自动关灯,2个按键操作,亮度调节,暴闪.用了60%左右的FLASH空间,给楼主参考下,用05版的GCC编译的,makefile我就不发了.程序有点乱,需要花点时间看明白.
#include <avr/io.h>
#include <avr/signal.h>
#include <avr/interrupt.h>
#include <avr/delay.h>
#include <avr/eeprom.h>
#include <avr/wdt.h>
#define key1 PB1
#define key2 PB4
#define set_led_ddr DDRB|=_BV(PB0)
#define clr_led_ddr DDRB&=~_BV(PB0)
#define led_off PORTB&=~_BV(PB0)
#define led_on PORTB|=_BV(PB0)
#define uchar unsigned char
#define uint unsigned int
#define uint8 uint8_t
/* 定义全局变量 */
uint8 light=185; //灯亮度
uint8 inter_count=0; //开灯计数值
uchar adc_val; //电池电压值,低于3.1V时自动关灯
uint8 power=0; //电源控制位,1为开灯,0为关灯
uint8 cpu_sta=0x30; //cpu状态控制,0x00为开灯状态,0x30为关灯状态
uint8 flash_sign=0; //闪灯控制,为1时灯闪,0是灯长亮
uint8 flash_count=0; //按下按键时间长度计数
uint8 key1_count=0;
//********** 按键检测 **************
void key_check(void)
{
if(!(PINB&0X10)) power=0;
while(!(PINB&0X10));
}
//******* 电池电压检测 *************
void adc_check(void)
{
adc_val=ADCH;
if(adc_val<0x78) cpu_sta=0X30; //电池电压低于3.1V关灯,保护锂电
}
// ****** 灯状态扫描 **************
void flash_check(void)
{
if(!(PINB&0X10)) //长按按键灯闪烁
{
flash_count++;
if(flash_count>70) flash_sign=1;
}
else flash_count=0; //放开按键灯亮
if(flash_sign==1) //灯闪烁
{
TCCR0B=0X04;
OCR0A=205;
}
else //灯长亮
{
TCCR0B=0X01;
OCR0A=light;
}
}
//********** 开灯和关灯 ************
SIGNAL(SIG_INTERRUPT0)
{
inter_count++;
flash_sign=0;
if(inter_count==1) //开灯,配置寄存器
{
set_led_ddr;
PORTB=0X12; //配置端口
power=1; //电源标志,1为开灯,0为关灯
cpu_sta=0; //配置cpu
light=eeprom_read_byte(0);//读取亮度值
_delay_us(5);
OCR0A=light; //比较匹配值,灯亮度
TCNT0=0; //配置定时器
TCCR0A=0Xc3;
TCCR0B=0X01;
TIMSK0=0X02;
ADMUX=0X63; //配置AD
DIDR0=0X08;
ADCSRB=0X00;
ADCSRA=0Xe3;
while(!(PINB&0X02));
_delay_ms(2);
wdt_enable(WDTO_2S);//配置看门狗
}
if(inter_count>=2)
{
wdt_disable();
if(power==0) cpu_sta=0x30;//关灯
else
{
light+=30; //改变灯亮度
if(light>250) light=1; //灯由暗至亮,到最亮后循环变化
if(inter_count>250) inter_count=5;
}
while(!(PINB&0X02)); //按键不释放,在此停留
wdt_enable(WDTO_2S); //开看门狗
_delay_ms(1); //延时
}
}
//*********** 定时扫描,PWM ***********
SIGNAL(SIG_OVERFLOW0)
{
wdt_reset(); //喂狗
if(ADCSRA&0X10) adc_check();//电池电压检测
flash_check(); //灯状态扫描
}
//******* 主程序 **************
int main(void)
{
GIMSK=0X40;
PORTB=0x02; //配置端口
CLKPR=0X80; //系统时钟分频
CLKPR=0X02; //分频系数为8,Fosc=128KHz/8=16KHz
eeprom_write_byte(0,light);//保存初始亮度
_delay_us(10);
sei(); //开中断
while(1)
{
MCUCR=cpu_sta; //配置cpu状态
if(cpu_sta==0x30)
{
eeprom_write_byte(0,light);//关灯前保存亮度值
wdt_reset();
wdt_disable(); //关闭看门狗
TCCR0B=0; //关闭定时器
ADCSRA=0x00; //关闭AD
ADMUX=0x03;
DDRB=0X00; //配置端口
PORTB=0X02;
flash_count=0; //计数器清零
inter_count=0;
_delay_us(10);
asm("sleep"); //掉电模式,最大地省电
}
key_check(); //按键检测
}
} |
|