基于ATtiny13的手电筒(头灯)控制电路和程序
- 格式:doc
- 大小:146.50 KB
- 文档页数:10
基于ATtiny13的无级调光手电筒程序市面上的头灯一般有强光、弱光、爆闪三个挡位,一个按钮来控制开/关和换挡,顺序是:开(强光)-〉弱光->闪烁->关,每次开/关灯需要按三次,非常不方便。
两年前改造的五挡调光头灯一直用的很好,操作简便又人性化。
近来比较空闲,突发DIY一个有无级调光功能的头灯想法。
于是在网上搜索合适DIY的头灯,搜索原则是散热性能好、能变焦、尽量是装两节18650电池的灯。
本人喜欢变焦灯,因为照射范围可调又均匀。
第一次购买的灯完全失败,散热极差,为了节省成本居然灯头的重要部件用的是硬塑料,直接丢掉。
第二次买的还好,惊喜的是他的控制芯片用的是CX2812,它的引脚与ATTiny13单片机类似,替换控制芯片,稍微改动电路板的布线就可以利用原配的控制板,避免了从头开始做控制板,省去了最繁琐的印刷电路板的制作了。
通过ATtiny13a单片机的编程实现了一下功能:1、按一次开灯,再按一次就关灯,解决了按三次关灯的不方便的问题。
2、开关灯保留了逐步亮和逐步暗的功能,此功能非常人性化,本人很喜欢。
具体实现如下:开灯的时候PWM信号的占空比从0开始逐步加到设定的亮度,关灯时候占空比逐步减到0。
3、无级调光:在灯亮状态下按住按钮,LED灯亮度增加或减少,亮度达到100%或10%时闪烁三次来提醒亮度已经达到了全亮或最暗,松开按钮就停止调光,一直按住就循环调光。
程序中利用了ATtiny13a的PWM、外部中断(PCINT0)、睡眠、看门狗和EEPROM的读写功能,基本上每一行都加了注释,对于初次接触ATtiny13的人来说应该有帮助。
图片1:头灯图片2:头灯控制板(此控制板网上也有卖的)图片3:程序调试电路图图片4:用面包板搭建程序调试电路图片5:基于ATTiny13A的控制板电路图图片6:修改后的ATTiny13A控制板图片7:18650电池下的待机电流为0.26uA。
程序编辑和编译工具用了CodeVisionAVR 2.04.4a,烧写工具用了progisp1.72。
基于ATtiny13的手电筒(头灯)控制电路和程序本人有一个用一节18650电池、带变焦的头灯,该头灯有强光、弱光和闪烁三个档,用Q5 LED,一个按钮来控制开/关和换档,顺序是:开(强光)-〉弱光->闪烁->关。
但功能和档位不太满意,于是用A Ttiny13单片机制作一个控制电路替换原有的控制器。
通过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的读写功能,基本上每一行都加了注释,对于初次接触A Ttiny13的人来说应该有帮助的。
流程图:程序源代码:/*********************************************************************** 名称:LED控制程序* 描述:调光设置功能* MCU :ATTiny13A* 晶振:RC 9.6MHz* 编译环境:CodeVisionA VR 2.04.4a* 版本:3.0 KEY用外部中断方式、增加睡眠功能、修改看门狗,8分频(4.6875KHz)***********************************************************************/#include <tiny13.h>//#include <delay.h>#define uchar unsigned char#define uint unsigned int#define KEY PINB.1 //tiny13第6脚,INT0 外部中断#define LEDDRV PORTB.0 //tiny13第5脚#define LEDDRV2 PORTB.2 //tiny13第7脚(指示灯)#define MAX_STA TE 5u //最多档位数#define LONG_KEY 15 //长按键的时间#define ADDRESS 0x01 //保存档位的地址/********** 变量定义**********************************************///uchar pwm[]={0x20,0x40,0x60,0x80,0xA0,0xC0,0xE0,0xFF};uchar pwm[]={0x20,0x40,0x80,0xC0,0xFF}; //亮度值uchar pwmVal = 0; //亮度档位uchar status = 0; //0为LED OFF,1为LED ONuchar mode = 0; //0为使用模式,1为设置模式uint keytime = 0; //按键时间/*********************************************************************** 描述:软件延时函数(RC 9.6MHz)* 输入:延时毫秒数***********************************************************************/ void delayMs(uint n){uint i;uint j;for (i=0; i<n; i++)for (j=0; j<137 ; j++) //RC 9.6MHz时候延时1MS#asm("nop")}/*********************************************************************** 名称: init_devices()* 功能: 端口、定时器、PWM初始化* 输入:无* 输出:无***********************************************************************/ void init_devices(void){// Crystal Oscillator division factor: 8#pragma optsize-CLKPR=0x80;CLKPR=0x03;#ifdef _OPTIMIZE_SIZE_#pragma optsize+#endif// I/O口的初始化DDRB = 0x01; // PB.0输出(P5),PB.1输入(P6),PB.2输出(P7), PB.3输入(P2) PORTB = 0x00; // PB.2输出// PWM 初始化// TCCR0A BIT 7 6 5 4 3 2 1 0// COM0A1 COM0A0 COM0B1 COM0B0 - - WGM01 WGM00//TCCR0A=0x83; // 开启PWM, 比较匹配发生时OC0A 清零//TCCR0A = 0x03; // 关闭PWMTCCR0A |= (1<<COM0A1)|(0<<COM0A0)|(1<<WGM01)|(1<<WGM00); //TCCR0A=0x83;TCCR0B |= (0<<WGM02)|(0<<CS02)|(1<<CS01)|(0<<CS00); //8分频(4.6875KHz)//TCCR0B=0x01; // 无预分频OCR0A = 0x00;TCNT0 = 0x00; // T/C0计数寄存器初值TCCR0A = 0x03; // 关闭PWM// 外部中断初始化设置//MCUCR = 0x02; // INT0 为下降沿时产生中断请求//MCUCR |= (1<<ISC01)|(0<<ISC00); // INT0 为下降沿时产生中断请求//GIMSK = 0x40; // 允许INT0 产生中断GIMSK |= (1<<INT0); // 允许INT0 产生中断//TIMSK0=(0<<OCIE0B)|(0<<OCIE0A)|(0<<TOIE0);//#asm("sei")// 睡眠模式初始化MCUCR|=(1<<SM1)|(0<<SM0); // 掉电模式MCUCR|=(1<<SE); // 睡眠使能//GIMSK |=(1<<INT0);//#asm("sei")//#asm ("sleep") // 睡眠}/************************************************************************ 描述:开启看门狗* 参数:无************************************************************************/void WDT_on(void){// 看门狗设置//#asm("cli") // 关闭全局中断#asm("WDR") // 看门狗复位指令WDR用来复位看门狗定时器WDTCR=0x18; // 启动时序WDTCR |= (1<<WDCE) | (1<<WDE);//WDTCR=0x28; // 看门狗定时4s WDTCR = (1<<WDP3) | (1<<WDE);WDTCR = (1<<WDP3) | (1<<WDE); // 看门狗定时4s//WDTCR = 0x00; // 关闭WDT//#asm("sei") // 开启全局中断}/************************************************************************ 描述:关闭看门狗* 参数:无************************************************************************/ void WDT_off(void){// 看门狗设置//#asm("cli") // 关闭全局中断#asm("WDR") // 看门狗复位指令WDR用来复位看门狗定时器MCUSR &= ~(1<<WDRF); // 清除MCUSR 寄存器中WDRF/* 在WDCE 与WDE 中写逻辑1,保持旧预分频器设置防止无意暂停*/WDTCR |= (1<<WDCE) | (1<<WDE);WDTCR = 0x00; // 关闭WDT//#asm("sei") // 开启全局中断}/*********************************************************************** * 描述:进入睡眠* 参数:无************************************************************************/ void sleep(void){WDT_off(); // 关闭WDT(关闭看门狗)// 睡眠模式初始化//MCUCR|=(1<<SM1)|(0<<SM0); // 掉电模式//MCUCR|=(1<<SE); // 睡眠使能//GIMSK |=(1<<INT0);#asm("sei") // 开启全局中断#asm("nop")#asm ("sleep") // 睡眠#asm("nop")#asm("cli") // 关闭全局中断WDT_on(); // 启动看门狗}/********************************************************************** * 描述:eeprom写一个字节数据* 参数:address--地址data--数据***********************************************************************/ void eeprom_write(uchar address,uchar data){//等待上一次写操作结束while(EECR&(1<<EEPE));//设置编程模式EECR=(0<<EEPM1)|(0>>EEPM0);//设置地址和数据寄存器EEAR = address;EEDR = data;//置位EEMPEEECR |= (1<<EEMPE);//置位EEWE,启动写操作EECR |= (1<<EEPE);}/*********************************************************************** * 描述:eeprom读一个字节数据* 参数:address--地址************************************************************************/ uchar eeprom_read(uchar address){//等待上一次写操作结束while(EECR&(1<<EEPE));//设置地址寄存器EEAR=address;//设置EERE以启动读操作EECR |= (1<<EERE);//自数据寄存器返回数据return(EEDR);}/*********************************************************************** * 描述:LED ON 开灯* 参数:无***********************************************************************/ void led_on(void){uchar i;TCCR0A = 0x83; //开启PWMfor (i=0; i<pwm[pwmVal]; i++){OCR0A = i; //更改占空比delayMs(4);}//全亮时候PWM Offif (pwm[pwmVal] == 0xff){TCCR0A = 0x03;LEDDRV = 1;}/*********************************************************************** * 描述:LED OFF 关灯* 参数:无************************************************************************/ void led_off(void){uchar i;if (TCCR0A == 0x03)TCCR0A = 0x83; //开启PWMfor (i=pwm[pwmVal]; i>0; i--){OCR0A = i; //更改占空比delayMs(5);}TCCR0A = 0x03; //关闭PWMLEDDRV = 0;sleep(); // 关灯进入睡眠}/*********************************************************************** * 描述:LED Flicker 闪烁* 参数:无************************************************************************/ void led_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] void int0_isr(void){//函数体}/********************************************************************** * 名称: Main()* 功能:* 输入:无* 输出:无***********************************************************************/ void main(void){init_devices(); //调用初始化函数// 读取eeprom中的亮度档位数据delayMs(10); //延时10mspwmVal = eeprom_read(ADDRESS); //读取eeprom里的数据delayMs(10);if (pwmVal >= MAX_STA TE) //eeprom无数据的话设为最高档位pwmVal = MAX_STA TE - 1;sleep(); // 进入睡眠while(1){#asm("WDR") //喂狗if ((PINB&0x02)) //判断是否按下键,KEY接到VCC{delayMs(10); //防抖延时for (keytime=0; ((PINB&0x02)) && keytime<LONG_KEY; keytime++){keytime++;delayMs(100); // 100ms}delayMs(10);//按键处理if (keytime > LONG_KEY && status == 1) //长按逻辑处理{if (mode == 0) //进入设置模式{if (TCCR0A == 0x03) //PWM Off 的话PWM 设为ONTCCR0A = 0x83;mode = 1;//LEDDRV2 = 1;led_flicker();}else //退出设置模式{mode = 0;//LEDDRV2 = 0;eeprom_write(ADDRESS, pwmVal); //写eeprom里的数据delayMs(10);led_flicker();delayMs(10);//退出设置模式后全亮的话PWM Off,LED灯亮if (pwm[pwmVal] == 0xff){TCCR0A = 0x03;LEDDRV = 1;}}}else if (keytime > 0 && keytime < LONG_KEY) //短按逻辑处理{if (mode == 0 && status == 0) // LED NO{status = 1;led_on(); //开灯}else if (mode == 0 && status == 1) // LED OFF{status = 0;led_off(); //关灯}else if (mode == 1 && status == 1) //设置模式下的短按{pwmVal++;if (pwmVal >= MAX_STA TE) //循环pwmVal = 0;OCR0A = pwm[pwmVal]; //更改占空比}}}// LEDDRV2 = ~LEDDRV2;// delayMs(50);} // end while}。
原理简单非常实用的自制高亮LED手电筒
DIY:高亮LED手电筒,原理简单非常实用自制高亮LED手电筒,从工作原理、电路图、焊接稳流芯片和LED到充电,一览全过程。
利用电子工程师手中的废料,轻松制作一个独一无二的高亮LED手电筒,顺便复习一下LED手电筒的电路知识吧,很亮哦!
1 自制LED手电筒工作原理
7135IC的厂家提供的电路
电路图2 接线
3 安装蓄电池
充电插座的正极焊上二极管,然后套上热收缩管绝缘。
电池正极线接在二极管的输出端,另一条线接充电插座正极线。
在充电插座的正极输出线接上一颗350欧姆的电阻,套上热缩管,把LED用胶水贴在开关的指示灯孔(开关内部是带指示灯的,把开关原来的指示灯拆掉,把这个装上去就可。
充电时候透过开关的半透明红色外壳可以看到这颗LED的亮光)。
电阻的另一脚接上LED指示灯的正极,套好热缩管。
现在全部线都接好了,把充电插座伸出之前打好的充电孔用AB胶固定。
最后就是在开关上涂上AB胶,按进不锈钢管等待胶水固化。
这种开关自带指示灯,它的功能是打开开关这个灯就会亮,但是我们作为一只手电筒是不需要的,所以就把另一个回路上的充电指示
灯接到原来开关带灯的位置上了。
4 测试
2米距离照在墙上,呈现比较圆比较亮的光斑,就大功告成啦!。
钓鱼的手电筒灯光调节原理
钓鱼的手电筒通常使用LED(发光二极管)作为光源,它的亮度调节原理是通过改变电流的大小来控制LED 发出的光线强度。
大多数手电筒都采用电池供电。
当电池连接到电路中时,电流将流经电路。
电路中的一个关键组件是稳流电路,该电路可以确保电流以恒定的强度流过LED。
稳流电路通常由电流驱动芯片、电阻器和其他元件组成。
在手电筒的开关部分,通常有一个多个档位的亮度调节开关。
通过调整开关的位置,可以改变电流驱动芯片的控制信号,从而改变输出的电流强度。
不同的电流强度会使LED 发出不同强度和亮度的光线。
简而言之,通过调整手电筒的亮度调节开关,可以改变电流流经LED 的强度,进而控制LED 的亮度,实现手电筒灯光的调节。
项目三搭建可调光手电筒电路一、项目应用可调光手电筒如图3-1所示,电源采用直流稳压电源,加入了色环电阻和可调电阻(电位器)。
接通电路后,调节可调电阻(电位器)可调节小灯珠亮度。
本项目主要学习认识相关元器件,完成电路的搭建,并学会使用数字万用表测量电路中的主要参数电压、电流和电位。
二、项目原理(一)电阻的串联如图3-2所示,将两个或两个以上电阻依次连接的电路称为电阻的串联。
串联电路的特点:1、电阻特点:总电阻为各串联电阻之和。
321R R R R ++=2、电流特点:串联电路中电流处处相等。
321I I I I ===3、电压特点:串联电路的总电压等于各串联电阻电压降之和。
R 1+ U 1 -R 2R 3+ U 2 -+ U 3 -图3-2 电阻的串联图3-1 可调光手电筒321U U U U ++=4、功率特点:串联电路的总功率等于各串联电阻的功率之和321P P P P ++=例题3-1:若有两个电阻串联,其中R 1=2K Ω,R 2=3K Ω,如图3-3所示,总电阻为多少?若将它们连接到5V 电源上,电路中的电流及R 1、R 2两端的电压分别是多少?R 1上消耗的功率是多少? 解:5K Ω3K ΩK Ω221=+=+=R R R1mA 5K Ω5V===R U I 2V 2K ΩmA 111=⨯==IR U 3V 3K ΩmA 122=⨯==IR U 2W 0001mA 2V 11.I U P =⨯==从上述例题可知串联电路有分压的作用,两个电阻串联时的分压公式为:UR R R U 2111+=UR R R U 2122+=(二)认识电位电路中某点的电位是指该点与电位参考点之间的电压。
电位参考点又称零电位点,规定该点的电位为零。
在电力工程中规定大地为零电位的参考点,在电子线路中,通常以与机壳连接的公共导线为参考点,并用接机壳的符号“┷”表示,称之为“地”,如图3-4所示。
电位通常用大写字母V 加下标表示,如图3-4中a 点的电位,用“V a ”表示。
专利名称:手电筒控制电路以及相应的手电筒专利类型:发明专利
发明人:周明杰,黄世侠
申请号:CN201210049909.7
申请日:20120229
公开号:CN103298187A
公开日:
20130911
专利内容由知识产权出版社提供
摘要:本发明涉及一种手电筒控制电路及相应的手电筒,其中包括电池;用于发出PWM信号的控制电路;用于恒流驱动LED的恒流驱动电路;以及用于根据PWM信号调整恒流驱动电路的电流大小的开关电路;电池分别与控制电路和开关电路连接,控制电路与开关电路连接,开关电路与恒流驱动电路连接;控制电路包括:用于检测手电筒活动状况的水银开关电路;以及用于根据水银开关电路的信号开启或关闭所述控制电路的控制芯片。
本发明的手电筒控制电路以及相应的手电筒在手电筒不使用时可以自动切断电源从而关闭手电筒,避免了现有的手电筒控制电路以及相应的手电筒常常由于使用者的不注意造成没有使用时一直耗电,从而导致使用时无电可用的缺陷。
申请人:海洋王照明科技股份有限公司,深圳市海洋王照明工程有限公司
地址:518052 广东省深圳市南山区南海大道海王大厦A座22层
国籍:CN
代理机构:深圳市顺天达专利商标代理有限公司
代理人:郭伟刚
更多信息请下载全文后查看。
手电筒原理图手电筒,又称电筒、手提电筒,是一种便携式照明设备,通常由电池、灯泡和外壳组成。
它的设计原理是利用电能转化为光能,从而实现照明的功能。
在本文中,我们将详细介绍手电筒的原理图及其工作原理。
手电筒的原理图主要包括电池、开关、导线、灯泡和外壳等部分。
电池是手电筒的能量来源,它通过导线与灯泡连接,将电能传递给灯泡。
开关则起到控制电路通断的作用,当开关闭合时,电路通电,灯泡发光;当开关断开时,电路断电,灯泡熄灭。
外壳则起到保护内部电路和灯泡的作用,同时也方便用户携带和使用。
手电筒的工作原理是利用电池产生的直流电流,通过电路传递到灯泡,使其发光。
当手电筒开关闭合时,电路形成闭合环路,电流流经导线进入灯泡,激发灯泡内的发光材料,从而产生可见光。
而当开关断开时,电路中断,电流无法流通,灯泡停止发光。
在手电筒的原理图中,电池的正极通过导线连接到灯泡的一端,而电池的负极则通过导线连接到开关的一端,另一端的开关与灯泡的另一端通过导线连接起来,形成一个闭合电路。
当开关闭合时,电流可以流通,灯泡发光;当开关断开时,电路中断,灯泡停止发光。
手电筒的原理图设计简单,但其工作原理却十分精妙。
通过电能转化为光能,实现了照明的功能,方便人们在黑暗环境中获取光源。
同时,手电筒的便携性也使其成为一种常用的照明工具,被广泛应用于户外、家庭、工业等领域。
总的来说,手电筒的原理图及其工作原理是基于电能转化为光能的原理,通过简单的电路设计实现照明功能。
它在日常生活中发挥着重要作用,为人们提供了便利和安全。
希望本文能够帮助读者更好地理解手电筒的原理图及其工作原理,进一步加深对这一便捷照明工具的认识。
基于AT Tiny13的智能点火控制器设计凌锋【期刊名称】《电子测试》【年(卷),期】2017(000)007【摘要】本文介绍以AT Tiny13单片机为核心设计了小型汽油发动机使用的低成本的点火控制器,并进行硬件及软件结合设计,达到精确地控制点火提前角.此系统解决了无触点磁电机电容放电点火系统(CDI)和无触点蓄电池式晶体管点火系统低速断火和高速失火问题,并且具有降低油耗、降低成本优点.%This paper introduces the AT Tiny13 microcontroller as the core design of the ignition controller of low cost small gasoline engine used, and combined with the design of hardware and software, to achieve precise control of ignition advance angle. The system solves the problem of low speed fire and high speed misfire of contactless magnetic capacitor discharge ignition system (CDI) and contactless battery type transistor ignition system, and has the advantages of reducing fuel consumption and reducing cost.【总页数】2页(P27-28)【作者】凌锋【作者单位】丽水学院工学院,浙江丽水,323000【正文语种】中文【相关文献】1.基于si1000无线微控制器的智能家居控制器方案设计 [J], 李双胜2.一种基于倍福控制器的点火控制系统设计 [J], 孟翔宇;蔡惠华;徐超;吴永红;姜祝3.基于si1000无线微控制器的智能家居控制器方案设计 [J], 李双胜4.基于PIC16C711的燃气灶脉冲点火控制器设计 [J], 周洪强5.基于Matlab的CNG/汽油发动机点火提前角控制器设计 [J], 许棚搏;赵奔;刘落实;因版权原因,仅展示原文概要,查看原文内容请购买。
基于ATtiny13的手电筒(头灯)控制电路和程序本人有一个用一节18650电池、带变焦的头灯,该头灯有强光、弱光和闪烁三个档,用Q5 LED,一个按钮来控制开/关和换档,顺序是:开(强光)-〉弱光->闪烁->关。
但功能和档位不太满意,于是用A Ttiny13单片机制作一个控制电路替换原有的控制器。
通过ATtiny13a单片机的编程实现了一下功能:1、按一次开灯,再按一次就关灯,解决了按三次关灯的问题。
2、开灯后长按秒以上并进入设定亮度模式,闪烁三次来提示。
3、亮度设定共有5个档位,20%、40%、60%、80%、100% 每按一次加一个档,到头再按循环。
4、在设定模式下长按秒以上便推出设定模式,闪烁三次来提示。
5、退出设定模式时候亮度值保存在EEPROM,这样就拿掉电池也不怕丢设定值,下次开灯直接就是上次设定值了。
6、开灯时亮度逐渐变亮到设定值,关灯时亮度逐渐变暗,最终灭掉,此功能为独创,是为了减少对眼睛的刺激。
设定值为100%亮度的时候,约1秒内亮度从0%开始逐渐达到100%的亮度,关灯相反、约1秒内亮度从100%开始逐渐减到0%。
手电筒控制电路如下:以下是程序,利用了ATtiny13a的PWM、外部中断、睡眠、看门狗和EEPROM的读写功能,基本上每一行都加了注释,对于初次接触A Ttiny13的人来说应该有帮助的。
流程图:程序源代码:/********************************************************************** * 名称:LED控制程序* 描述:调光设置功能* MCU :ATTiny13A* 晶振:RC* 编译环境:CodeVisionA VR 2.04.4a* 版本:KEY用外部中断方式、增加睡眠功能、修改看门狗,8分频()***********************************************************************/ #include <>//#include <>#define uchar unsigned char#define uint unsigned int#define KEY //tiny13第6脚,INT0 外部中断#define LEDDRV //tiny13第5脚#define LEDDRV2 //tiny13第7脚(指示灯)#define MAX_STA TE 5u //最多档位数#define LONG_KEY 15 //长按键的时间#define ADDRESS 0x01 //保存档位的地址/********** 变量定义**********************************************///uchar pwm[]={0x20,0x40,0x60,0x80,0xA0,0xC0,0xE0,0xFF};uchar pwm[]={0x20,0x40,0x80,0xC0,0xFF}; //亮度值uchar pwmVal = 0; //亮度档位uchar status = 0; //0为LED OFF,1为LED ONuchar mode = 0; //0为使用模式,1为设置模式uint keytime = 0; //按键时间/********************************************************************** * 描述:软件延时函数(RC* 输入:延时毫秒数***********************************************************************/ void delayMs(uint n){uint i;uint j;for (i=0; i<n; i++)for (j=0; j<137 ; j++) //RC 时候延时1MS#asm("nop")}/********************************************************************** * 名称: init_devices()* 功能: 端口、定时器、PWM初始化* 输入:无* 输出:无***********************************************************************/ void init_devices(void){// Crystal Oscillator division factor: 8#pragma optsize-CLKPR=0x80;CLKPR=0x03;#ifdef _OPTIMIZE_SIZE_#pragma optsize+#endif// I/O口的初始化DDRB = 0x01; // 输出(P5),输入(P6),输出(P7), 输入(P2)PORTB = 0x00; // 输出// PWM 初始化// TCCR0A BIT 7 6 5 4 3 2 1 0// COM0A1 COM0A0 COM0B1 COM0B0 - - WGM01 WGM00//TCCR0A=0x83; // 开启PWM, 比较匹配发生时OC0A 清零//TCCR0A = 0x03; // 关闭PWMTCCR0A |= (1<<COM0A1)|(0<<COM0A0)|(1<<WGM01)|(1<<WGM00); //TCCR0A=0x83;TCCR0B |= (0<<WGM02)|(0<<CS02)|(1<<CS01)|(0<<CS00); //8分频()//TCCR0B=0x01; // 无预分频OCR0A = 0x00;TCNT0 = 0x00; // T/C0计数寄存器初值TCCR0A = 0x03; // 关闭PWM// 外部中断初始化设置//MCUCR = 0x02; // INT0 为下降沿时产生中断请求//MCUCR |= (1<<ISC01)|(0<<ISC00); // INT0 为下降沿时产生中断请求//GIMSK = 0x40; // 允许INT0 产生中断GIMSK |= (1<<INT0); // 允许INT0 产生中断//TIMSK0=(0<<OCIE0B)|(0<<OCIE0A)|(0<<TOIE0);//#asm("sei")// 睡眠模式初始化MCUCR|=(1<<SM1)|(0<<SM0); // 掉电模式MCUCR|=(1<<SE); // 睡眠使能//GIMSK |=(1<<INT0);//#asm("sei")//#asm ("sleep") // 睡眠}/************************************************************************ 描述:开启看门狗* 参数:无************************************************************************/void WDT_on(void){// 看门狗设置//#asm("cli") // 关闭全局中断#asm("WDR") // 看门狗复位指令WDR用来复位看门狗定时器WDTCR=0x18; // 启动时序WDTCR |= (1<<WDCE) | (1<<WDE);//WDTCR=0x28; // 看门狗定时4s WDTCR = (1<<WDP3) | (1<<WDE);WDTCR = (1<<WDP3) | (1<<WDE); // 看门狗定时4s//WDTCR = 0x00; // 关闭WDT//#asm("sei") // 开启全局中断}/************************************************************************ 描述:关闭看门狗* 参数:无************************************************************************/ void WDT_off(void){// 看门狗设置//#asm("cli") // 关闭全局中断#asm("WDR") // 看门狗复位指令WDR用来复位看门狗定时器MCUSR &= ~(1<<WDRF); // 清除MCUSR 寄存器中WDRF/* 在WDCE 与WDE 中写逻辑1,保持旧预分频器设置防止无意暂停*/WDTCR |= (1<<WDCE) | (1<<WDE);WDTCR = 0x00; // 关闭WDT//#asm("sei") // 开启全局中断}/*********************************************************************** * 描述:进入睡眠* 参数:无************************************************************************/ void sleep(void){WDT_off(); // 关闭WDT(关闭看门狗)// 睡眠模式初始化//MCUCR|=(1<<SM1)|(0<<SM0); // 掉电模式//MCUCR|=(1<<SE); // 睡眠使能//GIMSK |=(1<<INT0);#asm("sei") // 开启全局中断#asm("nop")#asm ("sleep") // 睡眠#asm("nop")#asm("cli") // 关闭全局中断WDT_on(); // 启动看门狗}/********************************************************************** * 描述:eeprom写一个字节数据* 参数:address--地址data--数据***********************************************************************/ void eeprom_write(uchar address,uchar data){//等待上一次写操作结束while(EECR&(1<<EEPE));//设置编程模式EECR=(0<<EEPM1)|(0>>EEPM0);//设置地址和数据寄存器EEAR = address;EEDR = data;//置位EEMPEEECR |= (1<<EEMPE);//置位EEWE,启动写操作EECR |= (1<<EEPE);}/*********************************************************************** * 描述:eeprom读一个字节数据* 参数:address--地址************************************************************************/ uchar eeprom_read(uchar address){//等待上一次写操作结束while(EECR&(1<<EEPE));//设置地址寄存器EEAR=address;//设置EERE以启动读操作EECR |= (1<<EERE);//自数据寄存器返回数据return(EEDR);}/*********************************************************************** * 描述:LED ON 开灯* 参数:无***********************************************************************/ void led_on(void){uchar i;TCCR0A = 0x83; //开启PWMfor (i=0; i<pwm[pwmVal]; i++){OCR0A = i; //更改占空比delayMs(4);}//全亮时候PWM Offif (pwm[pwmVal] == 0xff){TCCR0A = 0x03;LEDDRV = 1;}}/*********************************************************************** * 描述:LED OFF 关灯* 参数:无************************************************************************/ void led_off(void){uchar i;if (TCCR0A == 0x03)TCCR0A = 0x83; //开启PWMfor (i=pwm[pwmVal]; i>0; i--){OCR0A = i; //更改占空比delayMs(5);}TCCR0A = 0x03; //关闭PWMLEDDRV = 0;sleep(); // 关灯进入睡眠}/*********************************************************************** * 描述:LED Flicker 闪烁* 参数:无************************************************************************/ void led_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] void int0_isr(void){//函数体}/********************************************************************** * 名称: Main()* 功能:* 输入:无* 输出:无***********************************************************************/ void main(void){init_devices(); //调用初始化函数// 读取eeprom中的亮度档位数据delayMs(10); //延时10mspwmVal = eeprom_read(ADDRESS); //读取eeprom里的数据delayMs(10);if (pwmVal >= MAX_STA TE) //eeprom无数据的话设为最高档位pwmVal = MAX_STA TE - 1;sleep(); // 进入睡眠while(1){#asm("WDR") //喂狗if ((PINB&0x02)) //判断是否按下键,KEY接到VCC{delayMs(10); //防抖延时for (keytime=0; ((PINB&0x02)) && keytime<LONG_KEY; keytime++){keytime++;delayMs(100); // 100ms}delayMs(10);//按键处理if (keytime > LONG_KEY && status == 1) //长按逻辑处理{if (mode == 0) //进入设置模式{if (TCCR0A == 0x03) //PWM Off 的话PWM 设为ONTCCR0A = 0x83;mode = 1;//LEDDRV2 = 1;led_flicker();}else //退出设置模式{mode = 0;//LEDDRV2 = 0;eeprom_write(ADDRESS, pwmVal); //写eeprom里的数据delayMs(10);led_flicker();delayMs(10);//退出设置模式后全亮的话PWM Off,LED灯亮if (pwm[pwmVal] == 0xff){TCCR0A = 0x03;LEDDRV = 1;}}}else if (keytime > 0 && keytime < LONG_KEY) //短按逻辑处理{if (mode == 0 && status == 0) // LED NO{status = 1;led_on(); //开灯}else if (mode == 0 && status == 1) // LED OFF{status = 0;led_off(); //关灯}else if (mode == 1 && status == 1) //设置模式下的短按{pwmVal++;if (pwmVal >= MAX_STA TE) //循环pwmVal = 0;OCR0A = pwm[pwmVal]; //更改占空比}}}// LEDDRV2 = ~LEDDRV2;// delayMs(50);} // end while}。