LQB,手打,第十三届简化

#include  "stc15.h"
#include <intrins.h> //添加nop函数的头文件
#include <stdio.h> //sprintf函数
#include <ds1302.h> //sprintf函数
#include <onewire.h> //sprintf函数

//定时器1定时1ms      测试DS 1302,测试温度模块读取是不是正常

#define FOSC 11059200L

#define T1MS (65536-FOSC/1000)      //1T模式
//#define T1MS (65536-FOSC/12/1000) //12T模式
#define     LED       4 
#define     ULN       5   
#define     COM       6   
#define     ABC       7   
typedef     unsigned char   u8;
typedef     unsigned int    u16;
typedef     unsigned long   u32;

u8 LEDbuf=0xFF; //LED缓冲
u8 ULNbuf=0x00;  //ULN2003缓冲
u8 SMGbuf[8];   //数码管8位,缓冲
u8 SMGtemp[20]; //数码管暂时变量,20个字节最多

u32 t1mscnt=0;
u16 LEDdly=0;
u16 ULNdly=0;
u16 SMGABCdly=0;    //数码管刷新数据
u16 SMGdly=0;//数码管显示延时
u16 KEYdly=0;
u16 ReadDly =0;
float wendu=0;     //温度
float wenduset=23;
char page=0;     //页面
char pagexx=0;
char ctrlmode=0;//控制模式,=0温度控制,=1,时间控制
u8 zhengdianflag=0;
u16 zhengdiantime=0;
/*************  本地常量声明    **************/
u8 code t_display[]={   //标准字库
//   0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
    0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
//black  -     H    J    K    L    N    o   P    U     t    G    Q    r   M    y
    0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e,
    0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46};    //0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1

u8 code T_COM[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};      //位码

//函数声明
void Delay1ms();		//@11.0592MHz
void delayms(u16 xms);
void sel573(u8 x);//选择哪个一个通道
void closeall();
void LEDctrl();
void ULNctrl();
void LEDout();
void ULNout();
//字库是共阴数码管字库,在stcISP中复制过来。
void SMGconv();//将字符串和字库对比,转换到打印区
void SMGdisp();
void KeyRead();
void ReadData();
void SMGnow();


//测试DS1302程序,测试温度程序
void main()
{
	u8 i=0;
	//关闭所有的外设
	closeall();
	//读取一次温度,跳过85度的数据
  wendu = read18b20();
  delayms(800);//跳过85度的显示数据

  AUXR |= 0x40;                   //定时器1为1T模式
  TMOD = 0x00;                    //设置定时器为模式0(16位自动重装载)
  TL1 = T1MS;                     //初始化计时值
  TH1 = T1MS >> 8;
  TR1 = 1;                        //定时器1开始计时
  ET1 = 1;                        //使能定时器0中断
  EA = 1;
	
  second = 50;
	minute = 59;
	hour   =5;
	set1302(); //设置时间
	
	 wendu = read18b20();   //这里读取一次,覆盖之前的85度
	while(1)
	{
		 if(LEDdly>100)
		 {
			LEDdly=0;
			LEDctrl();
		 }
    
		 if(ULNdly>100)
		 {
			ULNdly=0;
			ULNctrl(); 
		 } 
		 if(ReadDly>500)
		 {
		     ReadDly=0;
			   ReadData();

		 }
		 
		 if(SMGABCdly>300)
		 {
		    SMGABCdly =0;
			  SMGnow();

		 }
		
		 KeyRead();
	}
}

/* Timer1 interrupt routine */
void tm1_isr() interrupt 3 using 1
{
  t1mscnt++;
	LEDdly++;
	ULNdly++;
  ReadDly++;
  SMGABCdly++;
	SMGdly++;
  SMGdisp();//1ms刷新一次
	
	if(zhengdianflag==1)
	{
		zhengdiantime++;
		if(zhengdiantime>=5000)
		{
		   zhengdiantime=0; //时间清0
       zhengdianflag=0; //标记等于0
		}
	}
//	

}

void Delay1ms()		//@11.0592MHz
{
	unsigned char i, j;

	_nop_();
	_nop_();
	_nop_();
	i = 11;
	j = 190;
	do
	{
		while (--j);
	} while (--i);
}
void delayms(u16 xms)
{
	u16 i;
	for(i=0;i<xms;i++)
	{
	  Delay1ms();	
	}
}
void sel573(u8 x)//选择哪个一个通道
{
	switch(x)
	{
		case 0: P2=P2&0x1F;break;
		case LED: P2=P2&0x1F|0x80;break;//0x80--a0--c0--e0
		case ULN: P2=P2&0x1F|0xA0;break;
		case COM: P2=P2&0x1F|0xC0;break;
		case ABC: P2=P2&0x1F|0xE0;break;
	}
}
void closeall()
{
	//关闭LED,蜂鸣器,数码管等;
	sel573(LED);LEDbuf=0x00;P0=~LEDbuf;sel573(0); 
	//注意,这里取反了LEDbuf,再输出,
	//因为原理图是低电平点亮,和我们1点亮的常识不太符合
	sel573(ULN);ULNbuf=0x00;P0=ULNbuf;sel573(0);
	//注意ULN2003是反相芯片,0---1,关闭继电器和蜂鸣器
	sel573(COM);P0=0x00;sel573(0); //共阳数码管,我们让等于0,不亮
	sel573(ABC);P0=0xFF;sel573(0);
}

void LEDout()
{
  sel573(LED);P0=~LEDbuf;sel573(0); 
}
void LEDctrl()
{
	if(zhengdianflag==1)
	{
	   LEDbuf = LEDbuf | 0x01 ;//L1点亮,P00=0; 00000001
	}
	else  if(zhengdianflag==0)
	{
	   LEDbuf = LEDbuf& (~0x01) ;//L1ximie,P00=0; 0000 0001
	}
	//控制模式
	if(ctrlmode==0)  //温度控制模式,L2点亮
	{
		  LEDbuf = LEDbuf | 0x02 ;//L2点亮,P00=0; 1111 1101
	}
	else if(ctrlmode==1)
	{
		  LEDbuf = LEDbuf & (~0x02) ;//L2熄灭,P00=0; 0000 0010
	}
	//判断P04是不是等于1,L10点亮
	//ULNbuf>>4     0001 0000
	if((ULNbuf>>4)&0x01 ==1)  //吸合状态
	{
		//L3间隔100ms闪烁 将0000 0100,P03异或1,其他异或0
	  LEDbuf = LEDbuf ^ 0x04 ;//L3点亮,P00=0; 0000 0100
	}
	else 	 //放开状态     if((ULNbuf>>4)&0x01 ==0) 
	{
	   	LEDbuf = LEDbuf &(~0x04) ;//L3熄灭,P00=0;0000 0100
	}
	//输出数据
   LEDout();
}
void ULNout()
{
	sel573(ULN);P0=ULNbuf;sel573(0);
}
void ULNctrl()
{
	  
	 if(ctrlmode==0) //温度控制模式
	 {
	    if(wendu>=wenduset)   //继电器P04,让P04=1,闭合
			{
				ULNbuf = ULNbuf |0x10;    //0001 0000
			}
			else  if(wendu<wenduset)   //继电器P04,让P04=0,  松开
			{
				ULNbuf = ULNbuf & (~0x10);    //1110 1111
			} 
	 }
	 else if(ctrlmode==1)  //时间控制模式
	 {
	   
			//如果是整点的话
			if(zhengdianflag==1)
			{
			  	ULNbuf = ULNbuf |0x10;    //0001 0000
			}
			else  if(zhengdianflag==0)
			{
			  	ULNbuf = ULNbuf & (~0x10);    //1110 1111
			}
	 }
	//输出数据 
	 ULNout();
}
//字库是共阴数码管字库,在stcISP中复制过来。
void SMGconv()//将字符串和字库对比,转换到打印区
{
	//对比一下,放到字库中,注意有个小数点
	u8 i,j,temp;
	while(SMGtemp[i]!=0x00)
	{
	  switch(SMGtemp[i])
		{
			case '0':temp =0x3F;break;
			case '1':temp =0x06;break;
			case '2':temp =0x5B;break;
			case '3':temp =0x4F;break;
			case '4':temp =0x66;break;
			case '5':temp =0x6D;break;
			case '6':temp =0x7D;break;
			case '7':temp =0x07;break;
			case '8':temp =0x7F;break;
			case '9':temp =0x6F;break;
			//剩下的字符,看实际需要
		  case '-':temp =0x40;break;
		  case 'U':temp =0x3E;break;
         //**********		其他,熄灭	
			default  :  temp =0x00;break;
		}
		//判断下一个是不是小数点,是的话
		//把最高位点亮,i=i+2,跳过小数点
		if(SMGtemp[i+1]=='.')
		{
		   temp =temp |0x80;
			 i=i+2;
		}
		else
			i=i+1;
		
		SMGbuf[j]= temp;
		j=j+1;
		
	}
}
void SMGdisp()
{
	static u8 i=0;
	//消隐鬼影
	sel573(COM);P0=0x00;sel573(0); //共阳数码管,我们让等于0,不亮
	sel573(ABC);P0=0xFF;sel573(0);
	//显示数据
	sel573(COM);P0=T_COM[i];sel573(0); //共阳数码管,我们让等于0,不亮
	sel573(ABC);P0=~SMGbuf[i];sel573(0);//注意取反,注意这里是SMGbuf
	
	i=i+1;
	if(i>=8)i=0;
}

void KeyRead()
{
//******************************  S17 S13  S9 S5 
	//******************************
	P30=1;P31=1;P32=0;P33=1;
	P34=1;P35=1;P42=1;P44=1;
	if(P34==0)      //*******************************S17
	{
		delayms(10);
		if(P34==0)
		{
			    if(page==2)         //参数设置界面
				{
					wenduset=wenduset-1;  //每次减1度,最小是10度
					if(wenduset<10)wenduset=99;
				}
		}
		while(P34==0)//等待松开  
		{
			if(page==1)
			{ 	
				pagexx=1; //按下的话,就是显示分秒
				read1302();//500ms读取一次时间
				SMGnow();
				delayms(1);
			}
		}
		pagexx=0;//关闭回到,时,分
	}
	else if(P35==0)        //*******************************S13
	{
		delayms(10);    //切换工作控制模式
		if(P35==0)
		{
			 if(ctrlmode==0)ctrlmode=1;
			else if(ctrlmode==1)ctrlmode=0;
		}
		while(P35==0);//等待松开
	}

//******************************  S16   S12  S8   S4 
	//******************************
	P30=1;P31=1;P32=1;P33=0;
	P34=1;P35=1;P42=1;P44=1;
	if(P34==0)
	{
		delayms(10);
		if(P34==0)  // &*********************************S16
		{
			  if(page==2)         //参数设置界面
				{
					wenduset=wenduset+1;  //每次加一读,最大是99度
					if(wenduset>100)wenduset=10;
				}
		}
		while(P34==0);//等待松开
	}
	else if(P35==0)    //************************S12  //**********切换页面
	{
		delayms(10);
		if(P35==0)
			
		{
			 if(page==0)page=1;
			else if(page==1)page=2;
			else if(page==2)page=0;
		}
		while(P35==0);//等待松开
	}
	//******************************
}
void ReadData()
{	
	read1302();//500ms读取一次时间
	if(minute==0 && second ==0 )
	{
		//整点
		zhengdianflag=1;
	}
	wendu = read18b20();//500ms读取一次	
}
void SMGnow()
{
	if(page==0)   //温度显示界面
	{
	//U1xxx23.5
	  sprintf(SMGtemp,"U1   %4.1f",wendu);  //测试时间显示	
	}
	else if(page==1)
	{
		//U2x23-25
		if(pagexx==0)
		{
		 	 sprintf(SMGtemp,"U2 %02d-%02d",(int)hour,(int)minute);  //测试时间显示
		}
		else if(pagexx==1)
		{
		 sprintf(SMGtemp,"U2 %02d-%02d",(int)minute,(int)second);  //测试时间显示
		}
	}
	else if(page==2)
	{
		//U3xxxx23  	 
		sprintf(SMGtemp,"U3xxxx%2d",(int)wenduset);  //测试时间显示
	}
	 SMGconv();	
		
}



DS1302.h

#ifndef __DS1302_H
#define __DS1302_H

extern unsigned char  second;
extern unsigned char  minute;
extern unsigned char  hour;



void Write_Ds1302(unsigned char temp);
void Write_Ds1302_Byte( unsigned char address,unsigned char dat );
unsigned char Read_Ds1302_Byte( unsigned char address );

void init1302();//初始化1302的时间,注意BCD码
//设置时间和读取时间
void set1302();
void read1302();
#endif

DS1302.c

/*
  程序说明: DS1302驱动程序
  软件环境: Keil uVision 4.10 
  硬件环境: CT107单片机综合实训平台 8051,12MHz
  日    期: 2011-8-9
*/

#include <stc15.h>
#include <intrins.h>
 #include <ds1302.h>

unsigned char  second;
unsigned char  minute;
unsigned char  hour;


sbit SCK=P1^7;		
sbit SDA=P2^3;		
sbit RST = P1^3;   // DS1302复位												

void Write_Ds1302(unsigned  char temp) 
{
	unsigned char i;
	for (i=0;i<8;i++)     	
	{ 
		SCK=0;
		SDA=temp&0x01;
		temp>>=1; 
		SCK=1;
	}
}   

void Write_Ds1302_Byte( unsigned char address,unsigned char dat )     
{
 	RST=0;	_nop_();
 	SCK=0;	_nop_();
 	RST=1; 	_nop_();  
 	Write_Ds1302(address);	
 	Write_Ds1302(dat);		
 	RST=0; 
}

unsigned char Read_Ds1302_Byte ( unsigned char address )
{
 	unsigned char i,temp=0x00;
 	RST=0;	_nop_();
 	SCK=0;	_nop_();
 	RST=1;	_nop_();
 	Write_Ds1302(address);
 	for (i=0;i<8;i++) 	
 	{		
		SCK=0;
		temp>>=1;	
 		if(SDA)
 		temp|=0x80;	
 		SCK=1;
	} 
 	RST=0;	_nop_();
 	SCK=0;	_nop_();
	SCK=1;	_nop_();
	SDA=0;	_nop_();
	SDA=1;	_nop_();
	return (temp);			
}

void init1302()//初始化1302的时间,注意BCD码
{
	//关闭写保护
  Write_Ds1302_Byte(0x8E,0x00);	
	//写数据
	Write_Ds1302_Byte(0x80,0x50);	// 秒   50秒
  Write_Ds1302_Byte(0x82,0x20);	//分 20分
  Write_Ds1302_Byte(0x84,0x10);	//时  10点
	//打开写保护
	 Write_Ds1302_Byte(0x8E,0x80);	

}
//设置时间和读取时间
void set1302()
{
	unsigned char miaotemp;
	unsigned char fentemp;
	unsigned char shitemp;
	//将十进制数据,改造成BCD码。参照STCISP软件
	miaotemp= ((second / 10) << 4) + (second % 10);
  fentemp = ((minute / 10) << 4) + (minute % 10);
  shitemp= ((hour / 10) << 4) + (hour % 10);
	//关闭写保护
  Write_Ds1302_Byte(0x8E,0x00);	
	//写数据
	Write_Ds1302_Byte(0x80,miaotemp);	// 秒   50秒
  Write_Ds1302_Byte(0x82,fentemp);	//分 20分
  Write_Ds1302_Byte(0x84,shitemp);	//时  10点
	//打开写保护
	Write_Ds1302_Byte(0x8E,0x80);	

}
void read1302()
{
		unsigned char miaotemp;
	unsigned char fentemp;
	unsigned char shitemp;
	 	//关闭写保护
  Write_Ds1302_Byte(0x8E,0x00);	
	//数据
	miaotemp=Read_Ds1302_Byte(0x81);	// 秒   50秒
  fentemp=Read_Ds1302_Byte(0x83);	//分 20分
  shitemp= Read_Ds1302_Byte(0x85);	//时  10点
	//打开写保护
	 Write_Ds1302_Byte(0x8E,0x80);	
	
	 second = ((miaotemp >> 4) & 0x07) * 10 + (miaotemp& 0x0f);
    minute = ((fentemp >> 4) & 0x07) * 10 + (fentemp & 0x0f);
    hour   = ((shitemp >> 4) & 0x03) * 10 + (shitemp& 0x0f);
}

onewire.h

#ifndef __ONEWIRE_H
#define __ONEWIRE_H

unsigned char rd_temperature(void);  //; ;
float read18b20();
#endif

onewire.c

/*
  程序说明: 单总线驱动程序
  软件环境: Keil uVision 4.10 
  硬件环境: CT107单片机综合实训平台(外部晶振12MHz) STC89C52RC单片机
  日    期: 2011-8-9
*/
#include "stc15.h"
#include "onewire.h"

sbit DQ = P1^4;  //单总线接口

//单总线延时函数
void Delay_OneWire(unsigned int t)  //STC89C52RC
{
	t=t*10;
	while(t--);
}

//通过单总线向DS18B20写一个字节
void Write_DS18B20(unsigned char dat)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		DQ = 0;
		DQ = dat&0x01;
		Delay_OneWire(5);
		DQ = 1;
		dat >>= 1;
	}
	Delay_OneWire(5);
}

//从DS18B20读取一个字节
unsigned char Read_DS18B20(void)
{
	unsigned char i;
	unsigned char dat;
  
	for(i=0;i<8;i++)
	{
		DQ = 0;
		dat >>= 1;
		DQ = 1;
		if(DQ)
		{
			dat |= 0x80;
		}	    
		Delay_OneWire(5);
	}
	return dat;
}

//DS18B20设备初始化
bit init_ds18b20(void)
{
  	bit initflag = 0;
  	
  	DQ = 1;
  	Delay_OneWire(12);
  	DQ = 0;
  	Delay_OneWire(80);
  	DQ = 1;
  	Delay_OneWire(10); 
    initflag = DQ;     
  	Delay_OneWire(5);
  
  	return initflag;
}
//背下来 ,忘记了顺序的话,

float read18b20()
{
	unsigned char high,low;
	unsigned int temp;
	float xx;
	 init_ds18b20();
	 Write_DS18B20(0xCC); //跳过ROM
	 Write_DS18B20(0x44);  //开始转换
	 Delay_OneWire(100);
	
	 init_ds18b20();
	 Write_DS18B20(0xCC); //跳过ROM
	 Write_DS18B20(0xBE);  //读取数据
	 Delay_OneWire(100);
	low= Read_DS18B20();   //先低
	high= Read_DS18B20();   //后高
	//与0x0F,是将高四位清0,因为只有12位精度
	//左移八位,然后或,合并
	temp = ((high &0x0F)<<8)  | low ;
	xx=temp*0.0625;//转换得到实际的温度
	
	return xx;
}






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值