• 回复
  • 收藏
  • 点赞
  • 分享
  • 发新帖

高山云----自制一款带记忆的开关

前些天在自己的车上改装了一个音频切换电路,由于音频信号是双声道,就必须要一个双刀双掷的开关来进行切换,但现在双刀双掷的开关已经很少了,再者安装不方便于是就有了这个小电路。花了20分钟写了个小程序,测试了一下效果很不错,价格也和好点的双刀双掷开关差不太多。

电路:

实际电路:

来个背面图,简洁小巧

功能:上电先调用上次单片机内部EEPROM中的数据控制继电器是开或关,按键按下后把数据取反送入内部EEPROM进行保存,方便下次开机调用。

全部回复(5)
正序查看
倒序查看
2014-10-28 13:57

程序如下:

#include "reg51.h"
#include "intrins.h"

typedef unsigned char BYTE;
typedef unsigned int WORD;
/*---------------------------------------------------------------------*/
/*--   端口定义                 ---------------------------------------*/
/*---------------------------------------------------------------------*/
sbit SWITCH = P3^2;
sbit LED    = P3^4;
/*---------------------------------------------------------------------*/
/*--   变量定义                 ---------------------------------------*/
/*---------------------------------------------------------------------*/
bit flag,BUTTON_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 看门狗控制寄存器

#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 BUTTON_ADDRESS  0x0100		        //测试地址

/*----------------------------
关闭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 char i, j,k;
	for(k=z;k>0;k--)
	{
		_nop_();
		_nop_();
		_nop_();
		i = 11;
		j = 190;
		do
		{
			while (--j);
		} while (--i);
	}
}


/*---------------------------------------------------------------------*/
/*--   主程序                   ---------------------------------------*/
/*---------------------------------------------------------------------*/

void main()
{
	flag=0;
	WDT_CONTR = 0x35;	   //启动看门狗	
	while (1)
	{
		WDT_CONTR = 0x35;	   //启动看门狗
		if(flag==0)
		{
			if(IapReadByte(BUTTON_ADDRESS)==0)
			{
				LED=1;	
			}
			else if(IapReadByte(BUTTON_ADDRESS)==1)
				LED=0;
			else
			{
				IapEraseSector(BUTTON_ADDRESS);
    			IapProgramByte(BUTTON_ADDRESS,BUTTON_TEMP);  
			}
			flag=1;	
		}
		
		if(SWITCH==0)
		{
			DELAY_1MS(20);
		    if(SWITCH==0)
			{
				while(!SWITCH);
				flag=0;
				BUTTON_TEMP=!BUTTON_TEMP;
				IapEraseSector(BUTTON_ADDRESS);
			    IapProgramByte(BUTTON_ADDRESS,BUTTON_TEMP);  
			}
		}					
	}
}

0
回复
2014-10-28 16:39
@yueyunno1
程序如下:#include"reg51.h"#include"intrins.h"typedefunsignedcharBYTE;typedefunsignedintWORD;/*---------------------------------------------------------------------*//*--端口定义---------------------------------------*//*---------------------------------------------------------------------*/sbitSWITCH=P3^2;sbitLED=P3^4;/*---------------------------------------------------------------------*//*--变量定义---------------------------------------*//*---------------------------------------------------------------------*/bitflag,BUTTON_TEMP;//-----------------------------------------------sfrIAP_DATA=0xC2;//IAP数据寄存器sfrIAP_ADDRH=0xC3;//IAP地址寄存器高字节sfrIAP_ADDRL=0xC4;//IAP地址寄存器低字节sfrIAP_CMD=0xC5;//IAP命令寄存器sfrIAP_TRIG=0xC6;//IAP命令触发寄存器sfrIAP_CONTR=0xC7;//IAP控制寄存器sfrWDT_CONTR=0xC1;//0000,0000看门狗控制寄存器#defineCMD_IDLE0//空闲模式#defineCMD_READ1//IAP字节读命令#defineCMD_PROGRAM2//IAP字节编程命令#defineCMD_ERASE3//IAP扇区擦除命令#defineENABLE_IAP0x83//ifSYSCLK>8;//设置IAP高地址IAP_TRIG=0x5a;//写触发命令(0x5a)IAP_TRIG=0xa5;//写触发命令(0xa5)_nop_();//等待ISP/IAP/EEPROM操作完成dat=IAP_DATA;//读ISP/IAP/EEPROM数据IapIdle();//关闭IAP功能returndat;//返回}/*----------------------------写一字节数据到ISP/IAP/EEPROM区域----------------------------*/voidIapProgramByte(WORDaddr,BYTEdat){IAP_CONTR=ENABLE_IAP;//使能IAPIAP_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();}/*----------------------------扇区擦除----------------------------*/voidIapEraseSector(WORDaddr){IAP_CONTR=ENABLE_IAP;//使能IAPIAP_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();}/*---------------------------------------------------------------------*//*--延时子程序---------------------------------------*//*---------------------------------------------------------------------*/voidDELAY_1MS(unsignedintz){unsignedchari,j,k;for(k=z;k>0;k--){_nop_();_nop_();_nop_();i=11;j=190;do{while(--j);}while(--i);}}/*---------------------------------------------------------------------*//*--主程序---------------------------------------*//*---------------------------------------------------------------------*/voidmain(){flag=0;WDT_CONTR=0x35;//启动看门狗while(1){WDT_CONTR=0x35;//启动看门狗if(flag==0){if(IapReadByte(BUTTON_ADDRESS)==0){LED=1;}elseif(IapReadByte(BUTTON_ADDRESS)==1)LED=0;else{IapEraseSector(BUTTON_ADDRESS);IapProgramByte(BUTTON_ADDRESS,BUTTON_TEMP);}flag=1;}if(SWITCH==0){DELAY_1MS(20);if(SWITCH==0){while(!SWITCH);flag=0;BUTTON_TEMP=!BUTTON_TEMP;IapEraseSector(BUTTON_ADDRESS);IapProgramByte(BUTTON_ADDRESS,BUTTON_TEMP);}}}}
乐老师,你又有好东西
0
回复
2014-10-28 21:13
@电源网-娜娜姐
乐老师,你又有好东西[图片]
哈哈,我的车车没有蓝牙,自己给车车改装了蓝牙。
0
回复
2015-01-20 13:34
云哥,什么时候专门开个帖子,讲讲:RAM,SRAM,DRAM,FRAM;还有ROM,PROM,EPROM,EEPROM,FLASH~~
0
回复
03-06 09:51

点赞

0
回复