24C02

 

bit  write=0;           //写24C02的标志;
sbit sda=P2^0;                         
sbit scl=P2^1;
void delay0()
{ ;; }
void start()  //开始信号
{	
	sda=1;
	delay0();
	scl=1;
	delay0();
	sda=0;
	delay0();
}
void stop()   //停止
{
	sda=0;
	delay0();
	scl=1;
	delay0();
	sda=1;
	delay0();
}
void respons()  //应答
{
	uchar i;
	scl=1;
	delay0();
	while((sda==1)&&(i<250))i++;
	scl=0;
	delay0();
}
void init_24c02()//IIC初始化函数
{
	sda=1;
	delay0();
	scl=1;
	delay0();
}
void write_byte(uchar date)//写一个字节函数
{
	uchar i,temp;
	temp=date;
	for(i=0;i<8;i++)
	{
		temp=temp<<1;
		scl=0;
	    delay0();
		sda=CY;
		delay0();
		scl=1;
		delay0();
	}
	scl=0;
	delay0();
	sda=1;
	delay0();
}
uchar read_byte()//读一个字节函数
{
	uchar i,k;
	scl=0;
	delay0();
	sda=1;
	delay0();
	for(i=0;i<8;i++)
	{
		scl=1;
		delay0();	
		k=(k<<1)|sda;
		scl=0;
		delay0();	
	}
	return k;
}
void write_add(uchar address,uchar date)//指定地址写一个字节
{
	start();
	write_byte(0xa0);
	respons();
	write_byte(address);
	respons();
	write_byte(date);
	respons();
	stop();
}
char read_add(uchar address)//指定地址读一个字节
{
	uchar date;
	start();
	write_byte(0xa0);
	respons();
	write_byte(address);
	respons();
	start();
	write_byte(0xa1);
	respons();
	date=read_byte();
	stop();
	return date;
}

 

DS12C887

 

 

#include<reg52.h>
#include<define.h>
void delay(uint z)//延时函数
{
	uint x,y;
	for(x=z;x>0;x--)
		for(y=110;y>0;y--);
}
void di() //蜂鸣器报警声音
{
	beep=0;
	delay(100);
	beep=1;
}
void write_com(uchar com)
{//写液晶命令函数
	rs=0;
	lcden=0;
	P0=com;
	delay(3);
	lcden=1;
	delay(3);
	lcden=0;	
}
void write_date(uchar date)
{//写液晶数据函数
	rs=1;
	lcden=0;
	P0=date;
	delay(3);
	lcden=1;
	delay(3);
	lcden=0;	
}
void init()
{//初始化函数
	uchar num;
	EA=1;//打开总中断
	EX1=1;//开外部中断1
	IT1=1;//设置负跳变沿触发中断
	flag1=0;//变量初始化
	t0_num=0;
	s1num=0;
	week=1;
	dula=0;//关闭数码管显示
	wela=0;
	lcden=0;
	rd=0;
/*以下几行在首次设置DS12C887时使用,以后不必再写入
	write_ds(0x0A,0x20);//打开振荡器
	write_ds(0x0B,0x26);//设置24小时模式,数据二进制格式
						//开启闹铃中断
	set_time();//设置上电默认时间
-----------------------------------------------------*/
	write_com(0x38);//1602液晶初始化
	write_com(0x0c);
	write_com(0x06);
	write_com(0x01);
	write_com(0x80);
	for(num=0;num<15;num++)//写入液晶固定部分显示
		{
			write_date(table[num]);
			delay(1);
		}
	write_com(0x80+0x40);
	for(num=0;num<11;num++)
		{
			write_date(table1[num]);
			delay(1);
		}
}
void write_sfm(uchar add,char date)
{//1602液晶刷新时分秒函数4为时,7为分,10为秒
	char shi,ge;
	shi=date/10;
	ge=date%10;
	write_com(0x80+0x40+add);
	write_date(0x30+shi);
	write_date(0x30+ge);
}
void write_nyr(uchar add,char date)
{//1602液晶刷新年月日函数3为年,6为分,9为秒
	char shi,ge;
	shi=date/10;
	ge=date%10;
	write_com(0x80+add);
	write_date(0x30+shi);
	write_date(0x30+ge);
}
void write_week(char we)
{//写液晶星期显示函数
	write_com(0x80+12);
	switch(we)
	{
		case 1:	write_date('M');delay(5);
				write_date('O');delay(5);
				write_date('N');
				break;
		case 2:	write_date('T');delay(5);
				write_date('U');delay(5);
				write_date('E');
				break;
		case 3:	write_date('W');delay(5);
				write_date('E');delay(5);
				write_date('D');
				break;
		case 4:	write_date('T');delay(5);
				write_date('H');delay(5);
				write_date('U');
				break;
		case 5:	write_date('F');delay(5);
				write_date('R');delay(5);
				write_date('I');
				break;
		case 6:	write_date('S');delay(5);
				write_date('A');delay(5);
				write_date('T');
				break;
		case 7:	write_date('S');delay(5);
				write_date('U');delay(5);
				write_date('N');
				break;
	}
}
void keyscan()
{
	if(flag_ri==1)
	{//这里用来取消闹钟报警,任一键取消报警
		if((s1==0)||(s2==0)||(s3==0)||(s4==0))
		{	
			delay(5);
			if((s1==0)||(s2==0)||(s3==0)||(s4==0))
			{
				while(!(s1&&s2&&s3&&s4));
                di();
				flag_ri=0;//清除报警标志
			}	 	
		}
	}	
	if(s1==0)//检测S1
	{
		delay(5);
		if(s1==0)
		{	
			s1num++;//记录按下次数
			if(flag1==1)
				if(s1num==4)
					s1num=1;
			flag=1;
			while(!s1);di();
			switch(s1num)
			{//光标闪烁点定位
				case 1: write_com(0x80+0x40+10);
					    write_com(0x0f);
						break;
				case 2: write_com(0x80+0x40+7);
						break;
				case 3: write_com(0x80+0x40+4);
						break;
				case 4: write_com(0x80+12);
						break;
				case 5: write_com(0x80+9);
						break;
				case 6: write_com(0x80+6);
						break;
				case 7: write_com(0x80+3);
						break;
				case 8: s1num=0;
						write_com(0x0c);
						flag=0;
						write_ds(0,miao);
						write_ds(2,fen);
						write_ds(4,shi);
						write_ds(6,week);
						write_ds(7,day);
						write_ds(8,month);
						write_ds(9,year);
						break;
			}	
		}
	}
	if(s1num!=0)//只有当S1按下后,才检测S2和S3
	{
		if(s2==0)
		{
			delay(1);
			if(s2==0)
			{
				while(!s2);di();
				switch(s1num)
				{//根据功能键次数调节相应数值
					case 1:	miao++;
							if(miao==60)
								miao=0;
							write_sfm(10,miao);
							write_com(0x80+0x40+10); 
							break;
					case 2:	fen++;
							if(fen==60)
								fen=0;
							write_sfm(7,fen);
							write_com(0x80+0x40+7); 
							break;
					case 3:	shi++;
							if(shi==24)
								shi=0;
							write_sfm(4,shi);
							write_com(0x80+0x40+4); 
							break;
					case 4:	week++;
							if(week==8)
								week=1;
							write_week(week);
							write_com(0x80+12);
							break;
					case 5:	day++;
							if(day==32)
								day=1;
							write_nyr(9,day);
							write_com(0x80+9);
							break;
					case 6:	month++;
							if(month==13)
								month=1;
							write_nyr(6,month);
							write_com(0x80+6);
							break;
					case 7:	year++;
							if(year==100)
								year=0;
							write_nyr(3,year);
							write_com(0x80+3);
							break;
				}
			}
		}
		if(s3==0)
		{
			delay(1);
			if(s3==0)
			{
				while(!s3);di();
				switch(s1num)
				{//根据功能键次数调节相应数值
					case 1:	miao--;
							if(miao==-1)
								miao=59;
							write_sfm(10,miao);
							write_com(0x80+0x40+10);
							break; 
					case 2:	fen--;
							if(fen==-1)
								fen=59;
							write_sfm(7,fen);
							write_com(0x80+0x40+7);
							break;
					case 3:	shi--;
							if(shi==-1)
								shi=23;
							write_sfm(4,shi);
							write_com(0x80+0x40+4);
							break;
					case 4:	week--;
							if(week==0)
								week=7;
							write_week(week);
							write_com(0x80+12);
							break;
					case 5:	day--;
							if(day==0)
								day=31;
							write_nyr(9,day);
							write_com(0x80+9);
							break;
					case 6:	month--;
							if(month==0)
								month=12;
							write_nyr(6,month);
							write_com(0x80+6);
							break;
					case 7:	year--;
							if(year==-1)
								year=99;
							write_nyr(3,year);
							write_com(0x80+3);
							break;
				}
			}
		}
	}
	if(s4==0)//检测S4
	{
		delay(5);
		if(s4==0)
		{	
			flag1=~flag1;
			while(!s4);di();
			if(flag1==0)
			{//退出闹钟设置时保存数值
				flag=0;
				write_com(0x80+0x40);
				write_date(' ');
				write_date(' ');
				write_com(0x0c);
				write_ds(1,miao);
				write_ds(3,fen);
				write_ds(5,shi);				
			}
			else
			{//进入闹钟设置
				read_alarm();//读取原始数据
				miao=amiao;//重新赋值用以按键调节
				fen=afen;
				shi=ashi;
				write_com(0x80+0x40);
				write_date('R');//显示标志
				write_date('i');
				write_com(0x80+0x40+3);
				write_sfm(4,ashi);//送液晶显示闹钟时间
				write_sfm(7,afen);
				write_sfm(10,amiao);
			}			
		}
	}
}

void write_ds(uchar add,uchar date)
{//写12C887函数
	dscs=0;
	dsas=1;
	dsds=1;
	dsrw=1;
	P0=add;//先写地址
	dsas=0;
	dsrw=0;
	P0=date;//再写数据
	dsrw=1;
	dsas=1;
	dscs=1;				
}

uchar read_ds(uchar add)
{//读12C887函数
 	uchar ds_date;
	dsas=1;
	dsds=1;
	dsrw=1;
	dscs=0;
	P0=add;//先写地址
	dsas=0;
	dsds=0;
	P0=0xff;
	ds_date=P0;//再读数据
	dsds=1;
	dsas=1;
	dscs=1;
	return ds_date;	
}
/*---首次操作12C887时给予寄存器初始化---
void set_time()
{//首次上电初始化时间函数
	write_ds(0,0);
	write_ds(1,0);
	write_ds(2,0);
	write_ds(3,0);
	write_ds(4,0);
	write_ds(5,0);
	write_ds(6,0);
	write_ds(7,0);
	write_ds(8,0);
	write_ds(9,0);	
}
----------------------------------------*/
void read_alarm()
{//读取12C887闹钟值
	amiao=read_ds(1);
	afen=read_ds(3);
	ashi=read_ds(5);
}
void main()//主函数
{
	init();//调用初始化函数
	while(1)
	{
		keyscan();//按键扫描
		if(flag_ri==1)//当闹钟中断时进入这里
		{
			di();
			delay(100);
			di();
			delay(500);
		}	
		if(flag==0&&flag1==0)//正常工作时进入这里
		{
			keyscan();//按键扫描
			year=read_ds(9);//读取12C887数据
			month=read_ds(8);	
			day=read_ds(7);
			week=read_ds(6);
			shi=read_ds(4);
			fen=read_ds(2);
			miao=read_ds(0);	
			write_sfm(10,miao);//送液晶显示
			write_sfm(7,fen);
			write_sfm(4,shi);
			write_week(week);
			write_nyr(3,year);
			write_nyr(6,month);
			write_nyr(9,day);
		}
	}
}

void exter() interrupt 2//外部中断1服务程序
{	uchar c; //进入中断表示闹钟时间到,
	flag_ri=1; //设置标志位,用以大程序中报警提示
	c=read_ds(0x0c);//读取12C887的C寄存器表示响应了中断
}


 

DS18B20

 

 

#include <reg52.h>
#include <stdio.h>
#define  uchar unsigned char
#define  uint  unsigned int
sbit ds=P2^2;     //温度传感器信号线
sbit dula=P2^6;   //数码管段选线
sbit wela=P2^7;   //数码管位选线
sbit beep=P2^3;   //蜂鸣器

uint temp;
float f_temp;
uint warn_l1=260;
uint warn_l2=250;
uint warn_h1=300;
uint warn_h2=320;

sbit led0=P1^0;
sbit led1=P1^1;
sbit led2=P1^2;
sbit led3=P1^3;

unsigned char code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0xbf,0x86,
0xdb,0xcf,0xe6,0xed,
0xfd,0x87,0xff,0xef};     //不带小数点的编码

void delay(uint z)//延时函数
{
	uint x,y;
	for(x=z;x>0;x--)
		for(y=110;y>0;y--);
}



void dsreset(void)    //18B20复位,初始化函数
{
  uint i;
  ds=0;
  i=103;
  while(i>0)i--;
  ds=1;
  i=4;
  while(i>0)i--;
}

bit tempreadbit(void)   //读1位函数
{
   uint i;
   bit dat;
   ds=0;i++;          //i++ 起延时作用
   ds=1;i++;i++;
   dat=ds;
   i=8;while(i>0)i--;
   return (dat);
}

uchar tempread(void)   //读1个字节
{
  uchar i,j,dat;
  dat=0;
  for(i=1;i<=8;i++)
  {
    j=tempreadbit();
    dat=(j<<7)|(dat>>1);   //读出的数据最低位在最前面,这样刚好一个字节在DAT里
  }
  return(dat);
}

void tempwritebyte(uchar dat)   //向18B20写一个字节数据
{
  uint i;
  uchar j;
  bit testb;
  for(j=1;j<=8;j++)
  {
    testb=dat&0x01;
    dat=dat>>1;
    if(testb)     //写 1
    {
      ds=0;
      i++;i++;
      ds=1;
      i=8;while(i>0)i--;
    }
    else
    {
      ds=0;       //写 0
      i=8;while(i>0)i--;
      ds=1;
      i++;i++;
    }

  }
}

void tempchange(void)  //DS18B20 开始获取温度并转换
{
  dsreset();
  delay(1);
  tempwritebyte(0xcc);  // 写跳过读ROM指令
  tempwritebyte(0x44);  // 写温度转换指令
}

uint get_temp()         //读取寄存器中存储的温度数据
{
  uchar a,b;

  dsreset();
  delay(1);
  tempwritebyte(0xcc);
  tempwritebyte(0xbe);
  a=tempread();         //读低8位
  b=tempread();         //读高8位
  temp=b;
  temp<<=8;            //两个字节组合为1个字
  temp=temp|a;
  f_temp=temp*0.0625;      //温度在寄存器中为12位 分辨率位0.0625°
  temp=f_temp*10+0.5;    //乘以10表示小数点后面只取1位,加0.5是四舍五入
  f_temp=f_temp+0.05; 
  return temp;         //temp是整型
}


////////////////////显示程序//////////////////////////
void display(uchar num,uchar dat)
{
  uchar i;
  dula=0;
  P0=table[dat];
  dula=1;
  dula=0;

  wela=0;
  i=0XFF;
  i=i&(~((0X01)<<(num)));
  P0=i;
  wela=1;
  wela=0;    
  delay(1);
}

void dis_temp(uint t)
{
  uchar i;
  i=t/100;
  display(0,i);
  i=t%100/10;
  display(1,i+10);
  i=t%100%10;
  display(2,i);
}
//////////////////////////////////////////////
void warn(uint s,uchar led)   //蜂鸣器报警声音 ,s控制音调
{
    uchar i;i=s;
    dula=0;
    wela=0;
 
	beep=0;
    P1=~(led);
    while(i--)
    {
      dis_temp(get_temp());
    }   
	beep=1;
    P1=0XFF;  
    i=s;  
     while(i--)
    {
      dis_temp(get_temp());
    }  
}
void deal(uint t)
{
  uchar i;
  if((t>warn_l2)&&(t<=warn_l1)) //大于25度小于27度
	{
       warn(40,0x01);
       
	}
  else if(t<=warn_l2)                   //小于25度 
	{
       warn(10,0x03);
	}
  else if((t<warn_h2)&&(t>=warn_h1)) //小于32度大于30度
    {
       warn(40,0x04);
	}
  else if(t>=warn_h2)                   //大于32度
	{
       warn(10,0x0c);
	}
  else
    {
       i=40;
       while(i--)
       {
        dis_temp(get_temp());
       } 
    }
}

void init_com(void)
{
     TMOD = 0x20;
     PCON = 0x00;
     SCON = 0x50;
     TH1 = 0xFd;
     TL1 = 0xFd;
     TR1 = 1;
}

void comm(char *parr)         
{
	do
	{
	 SBUF = *parr++;                                                           //发送数据                          
     while(!TI);                                                               //等待发送完成标志为1
	 TI =0;                                                                    //标志清零
	}while(*parr);                                                             //保持循环直到字符为'\0'
}

void main()
{
  uchar buff[4],i;
  dula=0;
  wela=0;
  init_com();
  while(1)
 {    
      tempchange();
      for(i=10;i>0;i--)
     {
      dis_temp(get_temp());}
      deal(temp); 

      sprintf(buff,"%f",f_temp);

    for(i=10;i>0;i--)
     {
      dis_temp(get_temp());}

      comm(buff);

     for(i=10;i>0;i--)
     {
      dis_temp(get_temp());}
    
 }
}

 

EEPROM

 

 

/*
extern void SectorErase(uint sector_addr);	// 扇区擦除
extern uchar byte_read(uint byte_addr);		// byte读
extern void byte_write(uint byte_addr, uchar original_data);	// byte写
extern uchar byte_write_verify(uint byte_addr, uchar original_data);// byte写并校验
extern uchar ArrayWrite(uint begin_addr, uint len, uchar code *array);	// byte数组写并校验
extern void ArrayRead(uint begin_addr, uchar len);		// 读出, 保存在Ttotal[]中
*/
#define RdCommand		0x01
#define PrgCommand		0x02
#define EraseCommand     	0x03
#define Error   1
#define Ok      0
#define WaitTime	0x01
#define PerSector		512
/* ================ 打开 ISP,IAP 功能 ================= */
void ISP_IAP_enable(void)
{
	EA	=	0;							/* 关中断 		*/
	ISP_CONTR =	ISP_CONTR & 0x18;       /* 0001,1000	*/
	ISP_CONTR =	ISP_CONTR | WaitTime;	/* 写入硬件延时	*/
	ISP_CONTR =	ISP_CONTR | 0x80;       /* ISPEN=1		*/
}
/* =============== 关闭 ISP,IAP 功能 ================== */
void ISP_IAP_disable(void)
{
	ISP_CONTR	=	ISP_CONTR & 0x7f;	/* ISPEN = 0 */
	ISP_TRIG	=	0x00;
	EA			=   1;			/* 开中断 */
}
/* ================ 公用的触发代码 ==================== */
void ISPgoon(void)
{
	ISP_IAP_enable();			/* 打开 ISP,IAP 功能	*/
	ISP_TRIG	=	0x46;		/* 触发ISP_IAP命令字节1	*/
	ISP_TRIG	=	0xb9;		/* 触发ISP_IAP命令字节2	*/
	_nop_();
}
/* ==================== 字节读 ======================== */
unsigned char byte_read(unsigned int byte_addr)
{
	ISP_ADDRH = (unsigned char)(byte_addr >> 8);	/* 地址赋值	*/
	ISP_ADDRL = (unsigned char)(byte_addr & 0x00ff);

	ISP_CMD   = ISP_CMD	& 0xf8;			/* 清除低3位 	*/
	ISP_CMD   = ISP_CMD	| RdCommand;	/* 写入读命令	*/

	ISPgoon();							/* 触发执行		*/
	ISP_IAP_disable();				/* 关闭ISP,IAP功能	*/

	return (ISP_DATA);				/* 返回读到的数据	*/
}
/* ================== 扇区擦除 ======================== */
void sectorerase(unsigned int sector_addr)
{
	unsigned int iSectorAddr;
	iSectorAddr = (sector_addr & 0xfe00); /* 取扇区地址 */
	ISP_ADDRH = (unsigned char)(iSectorAddr >> 8);
	ISP_ADDRL = 0x00;

	ISP_CMD	= ISP_CMD & 0xf8;			/* 清空低3位 	*/
	ISP_CMD	= ISP_CMD | EraseCommand;	/* 擦除命令3 	*/

	ISPgoon();							/* 触发执行		*/
	ISP_IAP_disable();				/* 关闭ISP,IAP功能	*/

}
/* ==================== 字节写 ======================== */
void byte_write(unsigned int byte_addr, unsigned char original_data)
{
	ISP_ADDRH =	(unsigned char)(byte_addr >> 8); 	/* 取地址 	*/
	ISP_ADDRL =	(unsigned char)(byte_addr & 0x00ff);

	ISP_CMD	 = ISP_CMD & 0xf8;				/* 清低3位	*/
	ISP_CMD  = ISP_CMD | PrgCommand;		/* 写命令2	*/
	ISP_DATA = original_data;			/* 写入数据准备	*/

	ISPgoon();							/* 触发执行		*/
	ISP_IAP_disable();					/* 关闭IAP功能	*/
}
void write_eep(float eep_data,uint add)
{
	uchar fcdh,fcdl;
	fcdh=(uint)(eep_data*100)/256;
	fcdl=(uint)(eep_data*100)%256;
	byte_write(add,fcdh);//写入浮充电电压高8位
	byte_write(add+1,fcdl);//写入浮充电电压低8位
}
float read_eep(uint add)
{
	float date_re;
	uchar dateh,datel;
	dateh=byte_read(add);
	datel=byte_read(add+1);
	date_re=(dateh*256+datel)/100.0;
	return date_re;
}