微软公司宣布不再支持你正在使用的 IE浏览器,这会严重影响浏览网页,请使用微软最新的Edge浏览器
您好, 登录| 注册|

【原创】高山云----STC单片机改调光台灯

  • 2014-05-29 14:27
  • yueyunno1

    LV.2
  • 1.0w

    浏览

  • 45

    回复

  • 1

    获赞

  • 很多现有的台灯都不具备调光的功能,只有一个电源开关,现用STC15F104E/STC15F104W等8脚芯片进行改造。利用单片机内部的EEPROM功能进行数据的掉电保存。

    项目设计要求:

         1.通过台灯适配器上的电源开关来进行调光切换。

         2.调光分成4个档位,分别对应pwm占空比的:25%,50%,75%,100%

         3.程序带记忆功能,上电时间超过6秒钟单片机将记住此时的亮度数据(及占空比),关灯后下次打开依旧为上次的亮度

         4.调光切换,上电后在6秒钟以内,每开关一次,亮度将向后变化一次,如果当前为100%,下次切换后为25%的亮度

    有了以上的设计要求后就可以自己写代码和搭硬件电路了。

    同是电子工程师,请一定不要吝啬你的赞!

    1人已赞

    编辑 举报

    LV.1

    4098602

    1492603

    50

    399457

    说说你的看法

  • LV.

    @

    编辑

    删除

    举报

    #该内容仅管理员可见#

    #回复内容已被删除#

    #该内容正在审核#

    回复:

    取消
    发送
  • 现在还没有回复呢,说说你的想法

    现在还没有回复呢,说说你的想法

    全部回复(45)

  • yueyunno1

    LV.1

    2014-05-29 14:55

    @

    台灯适配器图片:

    1

    台灯开关,增加的电路会装在这个开关中

    2

    最暗时候的灯珠亮度

    3

    最暗时候的PWM波形

    4

    实际调试的电路

    5

    一下是原理图,方块内部的部分电路最后全部装到适配器上的开关里

    6

    0

    设为最佳答案

    置顶

    编辑

    删除

    举报

    #该内容仅管理员可见#

    #回复内容已被删除#

    #该内容正在审核#

    回复:

    4098606

    1492603

    50

    399457

    取消
    发送
    2
  • yueyunno1

    LV.1

    2014-05-29 15:06

    @yueyunno1

    台灯适配器图片:

    1

    台灯开关,增加的电路会装在这个开关中

    2

    最暗时候的灯珠亮度

    3

    最暗时候的PWM波形

    4

    实际调试的电路

    5

    一下是原理图,方块内部的部分电路最后全部装到适配器上的开关里

    6

    #include "reg51.h"
    #include "intrins.h"
    
    typedef bit BOOL;
    typedef unsigned char BYTE;
    typedef unsigned int WORD;
    
    #define T1MS (65536-500) //12T模式
    
    sfr AUXR = 0x8e;                    //Auxiliary register
    
    /*---------------------------------------------------------------------*/
    /*--   端口定义                 ---------------------------------------*/
    /*---------------------------------------------------------------------*/
    #define PORT_3 P3
    #define HIGH 1
    #define LOW	 0
    
    sbit PWM_OUT_PORT   = P3^2;		   //	LED_RED	 LED_GREEN
    sbit LED   = P3^3;
    /*---------------------------------------------------------------------*/
    /*--   变量定义                 ---------------------------------------*/
    /*---------------------------------------------------------------------*/
    BYTE i,j;
    BYTE test_num;
    BYTE POWER_ON_TEMP_f;
    BYTE POWER_ON_TIME;
    BYTE READ_POWER_ON_TIME;
    BOOL ON_OFF_Flag;
    
    unsigned long POWER_ON_TEMP;
    
    //-----------------------------------------------
    sfr IAP_DATA    =   0xC2;               //IAP数据寄存器
    sfr IAP_ADDRH   =   0xC3;               //IAP地址寄存器高字节
    sfr IAP_ADDRL   =   0xC4;               //IAP地址寄存器低字节
    sfr IAP_CMD     =   0xC5;               //IAP命令寄存器
    sfr IAP_TRIG    =   0xC6;               //IAP命令触发寄存器
    sfr IAP_CONTR   =   0xC7;               //IAP控制寄存器
    
    sfr WDT_CONTR   =   0xC1;               //0000,0000 看门狗控制寄存器
    
    sfr P3M0        =   0xB2;   //0000,0000 端口3模式寄存器0
    sfr P3M1        =   0xB1;   //0000,0000 端口3模式寄存器1
    
    #define CMD_IDLE    0                   //空闲模式
    #define CMD_READ    1                   //IAP字节读命令
    #define CMD_PROGRAM 2                   //IAP字节编程命令
    #define CMD_ERASE   3                   //IAP扇区擦除命令
    #define ENABLE_IAP 0x83                 //if SYSCLK<12MHz
    
    #define IAP_ADDRESS  0x0100		        //测试地址
    #define OFF_TIME_ADD 0x0300		        //测试地址
    /*----------------------------
    关闭IAP
    ----------------------------*/
    void IapIdle()
    {
        IAP_CONTR = 0;                  //关闭IAP功能
        IAP_CMD = 0;                    //清除命令寄存器
        IAP_TRIG = 0;                   //清除触发寄存器
        IAP_ADDRH = 0x80;               //将地址设置到非IAP区域
        IAP_ADDRL = 0;
    }
    
    /*----------------------------
    从ISP/IAP/EEPROM区域读取一字节
    ----------------------------*/
    BYTE IapReadByte(WORD addr)
    {
        BYTE dat;                       //数据缓冲区
        IAP_CONTR = ENABLE_IAP;         //使能IAP
        IAP_CMD = CMD_READ;             //设置IAP命令
        IAP_ADDRL = addr;               //设置IAP低地址
        IAP_ADDRH = addr >> 8;          //设置IAP高地址
        IAP_TRIG = 0x5a;                //写触发命令(0x5a)
        IAP_TRIG = 0xa5;                //写触发命令(0xa5)
        _nop_();                        //等待ISP/IAP/EEPROM操作完成
        dat = IAP_DATA;                 //读ISP/IAP/EEPROM数据
        IapIdle();                      //关闭IAP功能
        return dat;                     //返回
    }
    
    /*----------------------------
    写一字节数据到ISP/IAP/EEPROM区域
    ----------------------------*/
    void IapProgramByte(WORD addr, BYTE dat)
    {
        IAP_CONTR = ENABLE_IAP;         //使能IAP
        IAP_CMD = CMD_PROGRAM;          //设置IAP命令
        IAP_ADDRL = addr;               //设置IAP低地址
        IAP_ADDRH = addr >> 8;          //设置IAP高地址
        IAP_DATA = dat;                 //写ISP/IAP/EEPROM数据
        IAP_TRIG = 0x5a;                //写触发命令(0x5a)
        IAP_TRIG = 0xa5;                //写触发命令(0xa5)
        _nop_();                        //等待ISP/IAP/EEPROM操作完成
        IapIdle();
    }
    
    /*----------------------------
    扇区擦除
    ----------------------------*/
    void IapEraseSector(WORD addr)
    {
        IAP_CONTR = ENABLE_IAP;         //使能IAP
        IAP_CMD = CMD_ERASE;            //设置IAP命令
        IAP_ADDRL = addr;               //设置IAP低地址
        IAP_ADDRH = addr >> 8;          //设置IAP高地址
        IAP_TRIG = 0x5a;                //写触发命令(0x5a)
        IAP_TRIG = 0xa5;                //写触发命令(0xa5)
        _nop_();                        //等待ISP/IAP/EEPROM操作完成
        IapIdle();
    }
    
    /*---------------------------------------------------------------------*/
    /*--   延时子程序               ---------------------------------------*/
    /*---------------------------------------------------------------------*/
    void DELAY_1MS(unsigned int z)
    {
    	unsigned int x,y;
    	for(x=z;x>0;x--)
    		for(y=123;y>0;y--); 
    }
    /*---------------------------------------------------------------------*/
    /*--   主程序                   ---------------------------------------*/
    /*---------------------------------------------------------------------*/
    
    void main()
    {
    	PORT_3=0X00;
    	P3M0=0xFF;
    	P3M1=0x00;
    	ON_OFF_Flag=0;
    	POWER_ON_TIME=0;
    	READ_POWER_ON_TIME=0;
    
        AUXR |= 0x80;                   //定时器0为1T模式
    //    AUXR &= 0x7f;                   //定时器0为12T模式
        TMOD = 0x00;                    //设置定时器为模式0(16位自动重装载)
        TL0 = T1MS;                     //初始化计时值
        TH0 = T1MS >> 8;
        TR0 = 1;                        //定时器0开始计时
        ET0 = 1;                        //使能定时器0中断
        EA = 0;
    	POWER_ON_TEMP=0;
    	POWER_ON_TEMP_f=0;
    	j=0;
    	i=100;
    
    	DELAY_1MS(100);
    
    	WDT_CONTR = 0x35;	   //启动看门狗
    	while (1)
    	{
    		WDT_CONTR = 0x35;	   //启动看门狗	    
    		if(ON_OFF_Flag==0)	   //上电标志,上电只执行一次
    		{
    			ON_OFF_Flag=1;
    			READ_POWER_ON_TIME=IapReadByte(OFF_TIME_ADD);	  //////////////////////////////
    
    			if(READ_POWER_ON_TIME!=4)   //上电时间监测,小于4切换模式
    			{
    				test_num=IapReadByte(IAP_ADDRESS);			  //////////////////////////////
    				if(test_num<3)		 //	LED_RED	 LED_GREEN
    				{
    				   	test_num++;
    					IapEraseSector(IAP_ADDRESS);
    					IapProgramByte(IAP_ADDRESS,test_num);					
    				}
    				else 
    				{
    					test_num=0;
    					IapEraseSector(IAP_ADDRESS);
    					IapProgramByte(IAP_ADDRESS,test_num);
    				}
    			}
    
    			else					  //上电时间监测,大于4模式记忆
    			{
    				test_num=IapReadByte(IAP_ADDRESS);		  /////////////////////////////////
    				if(test_num>3)		 //	LED_RED	 LED_GREEN 
    				{
    				   	test_num=0;
    					IapEraseSector(IAP_ADDRESS);
    					IapProgramByte(IAP_ADDRESS,test_num);
    				}	
    			}
    			IapEraseSector(OFF_TIME_ADD);
    		}
    		/*---------------------------------------------------------------------*/
    		EA = 1;
    		if(test_num==0)
    		{
    			j=4;
    		}
    		else if(test_num==1)
    		{
    			j=20;			
    		}
    		else if(test_num==2)
    		{
    			j=50;			
    		}
    		else if(test_num==3)
    		{
    			j=99;			
    		}	
    	}
    }
    
    //-----------------------------------------------
    
    /* Timer0 interrupt routine */
    void tm0_isr() interrupt 1 using 1
    {
    	if(i>0)
    	{
    		i--;
    		if(j
    0

    设为最佳答案

    置顶

    编辑

    删除

    举报

    #该内容仅管理员可见#

    #回复内容已被删除#

    #该内容正在审核#

    回复:

    4098608

    1492603

    50

    399457

    取消
    发送
    3
  • yueyunno1

    LV.1

    2014-05-29 15:07

    @yueyunno1

    #include "reg51.h"
    #include "intrins.h"
    
    typedef bit BOOL;
    typedef unsigned char BYTE;
    typedef unsigned int WORD;
    
    #define T1MS (65536-500) //12T模式
    
    sfr AUXR = 0x8e;                    //Auxiliary register
    
    /*---------------------------------------------------------------------*/
    /*--   端口定义                 ---------------------------------------*/
    /*---------------------------------------------------------------------*/
    #define PORT_3 P3
    #define HIGH 1
    #define LOW	 0
    
    sbit PWM_OUT_PORT   = P3^2;		   //	LED_RED	 LED_GREEN
    sbit LED   = P3^3;
    /*---------------------------------------------------------------------*/
    /*--   变量定义                 ---------------------------------------*/
    /*---------------------------------------------------------------------*/
    BYTE i,j;
    BYTE test_num;
    BYTE POWER_ON_TEMP_f;
    BYTE POWER_ON_TIME;
    BYTE READ_POWER_ON_TIME;
    BOOL ON_OFF_Flag;
    
    unsigned long POWER_ON_TEMP;
    
    //-----------------------------------------------
    sfr IAP_DATA    =   0xC2;               //IAP数据寄存器
    sfr IAP_ADDRH   =   0xC3;               //IAP地址寄存器高字节
    sfr IAP_ADDRL   =   0xC4;               //IAP地址寄存器低字节
    sfr IAP_CMD     =   0xC5;               //IAP命令寄存器
    sfr IAP_TRIG    =   0xC6;               //IAP命令触发寄存器
    sfr IAP_CONTR   =   0xC7;               //IAP控制寄存器
    
    sfr WDT_CONTR   =   0xC1;               //0000,0000 看门狗控制寄存器
    
    sfr P3M0        =   0xB2;   //0000,0000 端口3模式寄存器0
    sfr P3M1        =   0xB1;   //0000,0000 端口3模式寄存器1
    
    #define CMD_IDLE    0                   //空闲模式
    #define CMD_READ    1                   //IAP字节读命令
    #define CMD_PROGRAM 2                   //IAP字节编程命令
    #define CMD_ERASE   3                   //IAP扇区擦除命令
    #define ENABLE_IAP 0x83                 //if SYSCLK<12MHz
    
    #define IAP_ADDRESS  0x0100		        //测试地址
    #define OFF_TIME_ADD 0x0300		        //测试地址
    /*----------------------------
    关闭IAP
    ----------------------------*/
    void IapIdle()
    {
        IAP_CONTR = 0;                  //关闭IAP功能
        IAP_CMD = 0;                    //清除命令寄存器
        IAP_TRIG = 0;                   //清除触发寄存器
        IAP_ADDRH = 0x80;               //将地址设置到非IAP区域
        IAP_ADDRL = 0;
    }
    
    /*----------------------------
    从ISP/IAP/EEPROM区域读取一字节
    ----------------------------*/
    BYTE IapReadByte(WORD addr)
    {
        BYTE dat;                       //数据缓冲区
        IAP_CONTR = ENABLE_IAP;         //使能IAP
        IAP_CMD = CMD_READ;             //设置IAP命令
        IAP_ADDRL = addr;               //设置IAP低地址
        IAP_ADDRH = addr >> 8;          //设置IAP高地址
        IAP_TRIG = 0x5a;                //写触发命令(0x5a)
        IAP_TRIG = 0xa5;                //写触发命令(0xa5)
        _nop_();                        //等待ISP/IAP/EEPROM操作完成
        dat = IAP_DATA;                 //读ISP/IAP/EEPROM数据
        IapIdle();                      //关闭IAP功能
        return dat;                     //返回
    }
    
    /*----------------------------
    写一字节数据到ISP/IAP/EEPROM区域
    ----------------------------*/
    void IapProgramByte(WORD addr, BYTE dat)
    {
        IAP_CONTR = ENABLE_IAP;         //使能IAP
        IAP_CMD = CMD_PROGRAM;          //设置IAP命令
        IAP_ADDRL = addr;               //设置IAP低地址
        IAP_ADDRH = addr >> 8;          //设置IAP高地址
        IAP_DATA = dat;                 //写ISP/IAP/EEPROM数据
        IAP_TRIG = 0x5a;                //写触发命令(0x5a)
        IAP_TRIG = 0xa5;                //写触发命令(0xa5)
        _nop_();                        //等待ISP/IAP/EEPROM操作完成
        IapIdle();
    }
    
    /*----------------------------
    扇区擦除
    ----------------------------*/
    void IapEraseSector(WORD addr)
    {
        IAP_CONTR = ENABLE_IAP;         //使能IAP
        IAP_CMD = CMD_ERASE;            //设置IAP命令
        IAP_ADDRL = addr;               //设置IAP低地址
        IAP_ADDRH = addr >> 8;          //设置IAP高地址
        IAP_TRIG = 0x5a;                //写触发命令(0x5a)
        IAP_TRIG = 0xa5;                //写触发命令(0xa5)
        _nop_();                        //等待ISP/IAP/EEPROM操作完成
        IapIdle();
    }
    
    /*---------------------------------------------------------------------*/
    /*--   延时子程序               ---------------------------------------*/
    /*---------------------------------------------------------------------*/
    void DELAY_1MS(unsigned int z)
    {
    	unsigned int x,y;
    	for(x=z;x>0;x--)
    		for(y=123;y>0;y--); 
    }
    /*---------------------------------------------------------------------*/
    /*--   主程序                   ---------------------------------------*/
    /*---------------------------------------------------------------------*/
    
    void main()
    {
    	PORT_3=0X00;
    	P3M0=0xFF;
    	P3M1=0x00;
    	ON_OFF_Flag=0;
    	POWER_ON_TIME=0;
    	READ_POWER_ON_TIME=0;
    
        AUXR |= 0x80;                   //定时器0为1T模式
    //    AUXR &= 0x7f;                   //定时器0为12T模式
        TMOD = 0x00;                    //设置定时器为模式0(16位自动重装载)
        TL0 = T1MS;                     //初始化计时值
        TH0 = T1MS >> 8;
        TR0 = 1;                        //定时器0开始计时
        ET0 = 1;                        //使能定时器0中断
        EA = 0;
    	POWER_ON_TEMP=0;
    	POWER_ON_TEMP_f=0;
    	j=0;
    	i=100;
    
    	DELAY_1MS(100);
    
    	WDT_CONTR = 0x35;	   //启动看门狗
    	while (1)
    	{
    		WDT_CONTR = 0x35;	   //启动看门狗	    
    		if(ON_OFF_Flag==0)	   //上电标志,上电只执行一次
    		{
    			ON_OFF_Flag=1;
    			READ_POWER_ON_TIME=IapReadByte(OFF_TIME_ADD);	  //////////////////////////////
    
    			if(READ_POWER_ON_TIME!=4)   //上电时间监测,小于4切换模式
    			{
    				test_num=IapReadByte(IAP_ADDRESS);			  //////////////////////////////
    				if(test_num<3)		 //	LED_RED	 LED_GREEN
    				{
    				   	test_num++;
    					IapEraseSector(IAP_ADDRESS);
    					IapProgramByte(IAP_ADDRESS,test_num);					
    				}
    				else 
    				{
    					test_num=0;
    					IapEraseSector(IAP_ADDRESS);
    					IapProgramByte(IAP_ADDRESS,test_num);
    				}
    			}
    
    			else					  //上电时间监测,大于4模式记忆
    			{
    				test_num=IapReadByte(IAP_ADDRESS);		  /////////////////////////////////
    				if(test_num>3)		 //	LED_RED	 LED_GREEN 
    				{
    				   	test_num=0;
    					IapEraseSector(IAP_ADDRESS);
    					IapProgramByte(IAP_ADDRESS,test_num);
    				}	
    			}
    			IapEraseSector(OFF_TIME_ADD);
    		}
    		/*---------------------------------------------------------------------*/
    		EA = 1;
    		if(test_num==0)
    		{
    			j=4;
    		}
    		else if(test_num==1)
    		{
    			j=20;			
    		}
    		else if(test_num==2)
    		{
    			j=50;			
    		}
    		else if(test_num==3)
    		{
    			j=99;			
    		}	
    	}
    }
    
    //-----------------------------------------------
    
    /* Timer0 interrupt routine */
    void tm0_isr() interrupt 1 using 1
    {
    	if(i>0)
    	{
    		i--;
    		if(j                                                                    
    以上是程序代码!C程序调试OK
    0

    设为最佳答案

    置顶

    编辑

    删除

    举报

    #该内容仅管理员可见#

    #回复内容已被删除#

    #该内容正在审核#

    回复:

    4098609

    1492603

    50

    399457

    取消
    发送
    4
  • 电源网-娜娜姐

    LV.1

    2014-05-29 15:47

    @yueyunno1

    台灯适配器图片:

    1

    台灯开关,增加的电路会装在这个开关中

    2

    最暗时候的灯珠亮度

    3

    最暗时候的PWM波形

    4

    实际调试的电路

    5

    一下是原理图,方块内部的部分电路最后全部装到适配器上的开关里

    6

    乐工新帖 支持!~~~
    0

    设为最佳答案

    置顶

    编辑

    删除

    举报

    #该内容仅管理员可见#

    #回复内容已被删除#

    #该内容正在审核#

    回复:

    4098622

    1492603

    50

    144589

    取消
    发送
    5
  • yueyunno1

    LV.1

    2014-05-29 16:21

    @电源网-娜娜姐

    乐工新帖 支持!~~~
    感谢师长支持
    0

    设为最佳答案

    置顶

    编辑

    删除

    举报

    #该内容仅管理员可见#

    #回复内容已被删除#

    #该内容正在审核#

    回复:

    4098629

    1492603

    50

    399457

    取消
    发送
    6
  • daihui713

    LV.1

    2014-05-29 16:38

    @yueyunno1

    以上是程序代码!C程序调试OK

    通电时间大于6S,断电再开电时EEP数据不加1,保持当前亮度,小于6S内切换,断电开电EEP数据加1,亮度递增。乐云兄是这样不

    0

    设为最佳答案

    置顶

    编辑

    删除

    举报

    #该内容仅管理员可见#

    #回复内容已被删除#

    #该内容正在审核#

    回复:

    4098631

    1492603

    50

    312503

    取消
    发送
    7
  • yueyunno1

    LV.1

    2014-05-29 17:13

    @daihui713

    通电时间大于6S,断电再开电时EEP数据不加1,保持当前亮度,小于6S内切换,断电开电EEP数据加1,亮度递增。乐云兄是这样不

    对就是这个思路!
    0

    设为最佳答案

    置顶

    编辑

    删除

    举报

    #该内容仅管理员可见#

    #回复内容已被删除#

    #该内容正在审核#

    回复:

    4098634

    1492603

    50

    399457

    取消
    发送
    8
  • cltwolf

    LV.1

    2014-05-30 11:46

    @yueyunno1

    感谢师长支持

    继续支持

    0

    设为最佳答案

    置顶

    编辑

    删除

    举报

    #该内容仅管理员可见#

    #回复内容已被删除#

    #该内容正在审核#

    回复:

    4098734

    1492603

    50

    561083

    取消
    发送
    9
  • yueyunno1

    LV.1

    2014-05-30 11:56

    @cltwolf

    继续支持

    0

    设为最佳答案

    置顶

    编辑

    删除

    举报

    #该内容仅管理员可见#

    #回复内容已被删除#

    #该内容正在审核#

    回复:

    4098736

    1492603

    50

    399457

    取消
    发送
    10
  • mingquan23

    LV.1

    2014-06-24 09:37

    @

    你好,现在的LED有开关调光的IC,这样就能满足你说的这种调光方式。还有你这样会导致电源不停的工作在空载跟满载之间,有的电源的开路保护电压(OVP)设置过高很容易导致烧坏负载灯珠。你这个PWM的频率好像不高吧用手机会不会看到频闪啊?
    0

    设为最佳答案

    置顶

    编辑

    删除

    举报

    #该内容仅管理员可见#

    #回复内容已被删除#

    #该内容正在审核#

    回复:

    4100335

    1492603

    50

    458806

    取消
    发送
    11
  • 现在还没有回复呢,说说你的想法

    1 2 3 4 5  
  • 回复

  • 收藏

  • 点赞

  • 举报有害信息

  • 已超出发布时间24小时,无法编辑与删除
    关于我们 联系方法 广告服务 会议服务 电子星球APP 网站地图 不良信息举报 热线:400-003-2006
    © 2002-2021 Netbroad(网博互动)公司版权所有 津ICP备 11006234号-2 联网备案号:12010402000747 增值电信业务经营许可证:津B2-20120058