基于ATtiny13的手电筒头灯控制电路和程序资料.docx
《基于ATtiny13的手电筒头灯控制电路和程序资料.docx》由会员分享,可在线阅读,更多相关《基于ATtiny13的手电筒头灯控制电路和程序资料.docx(16页珍藏版)》请在冰豆网上搜索。
![基于ATtiny13的手电筒头灯控制电路和程序资料.docx](https://file1.bdocx.com/fileroot1/2023-2/21/2c181980-749c-4fe2-ae65-e763575f930b/2c181980-749c-4fe2-ae65-e763575f930b1.gif)
基于ATtiny13的手电筒头灯控制电路和程序资料
基于ATtiny13的手电筒(头灯)控制电路和程序
本人有一个用一节18650电池、带变焦的头灯,该头灯有强光、弱光和闪烁三个档,
用Q5LED,一个按钮来控制开/关和换档,顺序是:
开(强光)-〉弱光->闪烁->关。
但功能和档位不太满意,于是用ATtiny13单片机制作一个控制电路替换原有的控制器。
通过ATtiny13a单片机的编程实现了一下功能:
1、按一次开灯,再按一次就关灯,解决了按三次关灯的问题。
2、开灯后长按1.5秒以上并进入设定亮度模式,闪烁三次来提示。
3、亮度设定共有5个档位,20%、40%、60%、80%、100%每按一次加一个档,到头再按循环。
4、在设定模式下长按1.5秒以上便推出设定模式,闪烁三次来提示。
5、退出设定模式时候亮度值保存在EEPROM,这样就拿掉电池也不怕丢设定值,下次开灯直接就是上次设定值了。
6、开灯时亮度逐渐变亮到设定值,关灯时亮度逐渐变暗,最终灭掉,此功能为独创,是为了减少对眼睛的刺激。
设定值为100%亮度的时候,约1秒内亮度从0%开始逐渐达到100%的亮度,关灯相反、约1秒内亮度从100%开始逐渐减到0%。
手电筒控制电路如下:
以下是程序,利用了ATtiny13a的PWM、外部中断、睡眠、看门狗和EEPROM的读写功能,基本上每一行都加了注释,对于初次接触ATtiny13的人来说应该有帮助的。
流程图:
程序源代码:
/**********************************************************************
*名称:
LED控制程序
*描述:
调光设置功能
*MCU:
ATTiny13A
*晶振:
RC9.6MHz
*编译环境:
CodeVisionAVR2.04.4a
*版本:
3.0KEY用外部中断方式、增加睡眠功能、修改看门狗,8分频(4.6875KHz)
***********************************************************************/
#include
//#include
#defineucharunsignedchar
#defineuintunsignedint
#defineKEYPINB.1//tiny13第6脚,INT0外部中断
#defineLEDDRVPORTB.0//tiny13第5脚
#defineLEDDRV2PORTB.2//tiny13第7脚(指示灯)
#defineMAX_STATE5u//最多档位数
#defineLONG_KEY15//长按键的时间
#defineADDRESS0x01//保存档位的地址
/**********变量定义**********************************************/
//ucharpwm[]={0x20,0x40,0x60,0x80,0xA0,0xC0,0xE0,0xFF};
ucharpwm[]={0x20,0x40,0x80,0xC0,0xFF};//亮度值
ucharpwmVal=0;//亮度档位
ucharstatus=0;//0为LEDOFF,1为LEDON
ucharmode=0;//0为使用模式,1为设置模式
uintkeytime=0;//按键时间
/**********************************************************************
*描述:
软件延时函数(RC9.6MHz)
*输入:
延时毫秒数
***********************************************************************/
voiddelayMs(uintn)
{
uinti;
uintj;
for(i=0;ifor(j=0;j<137;j++)//RC9.6MHz时候延时1MS
#asm("nop")
}
/**********************************************************************
*名称:
init_devices()
*功能:
端口、定时器、PWM初始化
*输入:
无
*输出:
无
***********************************************************************/
voidinit_devices(void)
{
//CrystalOscillatordivisionfactor:
8
#pragmaoptsize-
CLKPR=0x80;
CLKPR=0x03;
#ifdef_OPTIMIZE_SIZE_
#pragmaoptsize+
#endif
//I/O口的初始化
DDRB=0x01;//PB.0输出(P5),PB.1输入(P6),PB.2输出(P7),PB.3输入(P2)
PORTB=0x00;//PB.2输出
//PWM初始化
//TCCR0ABIT76543210
//COM0A1COM0A0COM0B1COM0B0--WGM01WGM00
//TCCR0A=0x83;//开启PWM,比较匹配发生时OC0A清零
//TCCR0A=0x03;//关闭PWM
TCCR0A|=(1<TCCR0B|=(0<//TCCR0B=0x01;//无预分频
OCR0A=0x00;
TCNT0=0x00;//T/C0计数寄存器初值
TCCR0A=0x03;//关闭PWM
//外部中断初始化设置
//MCUCR=0x02;//INT0为下降沿时产生中断请求
//MCUCR|=(1<//GIMSK=0x40;//允许INT0产生中断
GIMSK|=(1<//TIMSK0=(0<//#asm("sei")
//睡眠模式初始化
MCUCR|=(1<MCUCR|=(1<//GIMSK|=(1<//#asm("sei")
//#asm("sleep")//睡眠
}
/***********************************************************************
*描述:
开启看门狗
*参数:
无
************************************************************************/
voidWDT_on(void)
{
//看门狗设置
//#asm("cli")//关闭全局中断
#asm("WDR")//看门狗复位指令WDR用来复位看门狗定时器
WDTCR=0x18;//启动时序WDTCR|=(1<//WDTCR=0x28;//看门狗定时4sWDTCR=(1<WDTCR=(1<//WDTCR=0x00;//关闭WDT
//#asm("sei")//开启全局中断
}
/***********************************************************************
*描述:
关闭看门狗
*参数:
无
************************************************************************/
voidWDT_off(void)
{
//看门狗设置
//#asm("cli")//关闭全局中断
#asm("WDR")//看门狗复位指令WDR用来复位看门狗定时器
MCUSR&=~(1</*在WDCE与WDE中写逻辑1,保持旧预分频器设置防止无意暂停*/
WDTCR|=(1<WDTCR=0x00;//关闭WDT
//#asm("sei")//开启全局中断
}
/***********************************************************************
*描述:
进入睡眠
*参数:
无
************************************************************************/
voidsleep(void)
{
WDT_off();//关闭WDT(关闭看门狗)
//睡眠模式初始化
//MCUCR|=(1<//MCUCR|=(1<//GIMSK|=(1<#asm("sei")//开启全局中断
#asm("nop")
#asm("sleep")//睡眠
#asm("nop")
#asm("cli")//关闭全局中断
WDT_on();//启动看门狗
}
/**********************************************************************
*描述:
eeprom写一个字节数据
*参数:
address--地址data--数据
***********************************************************************/
voideeprom_write(ucharaddress,uchardata)
{
//等待上一次写操作结束
while(EECR&(1<//设置编程模式
EECR=(0<>EEPM0);
//设置地址和数据寄存器
EEAR=address;
EEDR=data;
//置位EEMPE
EECR|=(1<//置位EEWE,启动写操作
EECR|=(1<}
/***********************************************************************
*描述:
eeprom读一个字节数据
*参数:
address--地址
************************************************************************/
uchareeprom_read(ucharaddress)
{
//等待上一次写操作结束
while(EECR&(1<//设置地址寄存器
EEAR=address;
//设置EERE以启动读操作
EECR|=(1<//自数据寄存器返回数据
return(EEDR);
}
/***********************************************************************
*描述:
LEDON开灯
*参数:
无
***********************************************************************/
voidled_on(void)
{
uchari;
TCCR0A=0x83;//开启PWM
for(i=0;i{
OCR0A=i;//更改占空比
delayMs(4);
}
//全亮时候PWMOff
if(pwm[pwmVal]==0xff)
{
TCCR0A=0x03;
LEDDRV=1;
}
}
/***********************************************************************
*描述:
LEDOFF关灯
*参数:
无
************************************************************************/
voidled_off(void)
{
uchari;
if(TCCR0A==0x03)
TCCR0A=0x83;//开启PWM
for(i=pwm[pwmVal];i>0;i--)
{
OCR0A=i;//更改占空比
delayMs(5);
}
TCCR0A=0x03;//关闭PWM
LEDDRV=0;
sleep();//关灯进入睡眠
}
/***********************************************************************
*描述:
LEDFlicker闪烁
*参数:
无
************************************************************************/
voidled_flicker(void)
{
OCR0A=0x00;
delayMs(200);
OCR0A=pwm[pwmVal];
delayMs(200);
OCR0A=0x00;
delayMs(200);
OCR0A=pwm[pwmVal];
delayMs(200);
OCR0A=0x00;
delayMs(200);
OCR0A=pwm[pwmVal];
}
/**********************************************************************
*名称:
外部中断服务程序
*功能:
*输入:
无
*输出:
无
***********************************************************************/
interrupt[EXT_INT0]voidint0_isr(void)
{
//函数体
}
/**********************************************************************
*名称:
Main()
*功能:
*输入:
无
*输出:
无
***********************************************************************/
voidmain(void)
{
init_devices();//调用初始化函数
//读取eeprom中的亮度档位数据
delayMs(10);//延时10ms
pwmVal=eeprom_read(ADDRESS);//读取eeprom里的数据
delayMs(10);
if(pwmVal>=MAX_STATE)//eeprom无数据的话设为最高档位
pwmVal=MAX_STATE-1;
sleep();//进入睡眠
while
(1)
{
#asm("WDR")//喂狗
if((PINB&0x02))//判断是否按下键,KEY接到VCC
{
delayMs(10);//防抖延时
for(keytime=0;((PINB&0x02))&&keytime{
keytime++;
delayMs(100);//100ms
}
delayMs(10);
//按键处理
if(keytime>LONG_KEY&&status==1)//长按逻辑处理
{
if(mode==0)//进入设置模式
{
if(TCCR0A==0x03)//PWMOff的话PWM设为ON
TCCR0A=0x83;
mode=1;
//LEDDRV2=1;
led_flicker();
}
else//退出设置模式
{
mode=0;
//LEDDRV2=0;
eeprom_write(ADDRESS,pwmVal);//写eeprom里的数据
delayMs(10);
led_flicker();
delayMs(10);
//退出设置模式后全亮的话PWMOff,LED灯亮
if(pwm[pwmVal]==0xff)
{
TCCR0A=0x03;
LEDDRV=1;
}
}
}
elseif(keytime>0&&keytime{
if(mode==0&&status==0)//LEDNO
{
status=1;
led_on();//开灯
}
elseif(mode==0&&status==1)//LEDOFF
{
status=0;
led_off();//关灯
}
elseif(mode==1&&status==1)//设置模式下的短按
{
pwmVal++;
if(pwmVal>=MAX_STATE)//循环
pwmVal=0;
OCR0A=pwm[pwmVal];//更改占空比
}
}
}
//LEDDRV2=~LEDDRV2;
//delayMs(50);
}//endwhile
}