⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lcd1602电子钟源程序.c

📁 DS1302时间DS1302时间DS1302时间DS1302时间DS1302时间
💻 C
📖 第 1 页 / 共 3 页
字号:
/************************************************************
*程序名称 : LCD1602电子钟
*作    者 : jch
*日    期 : 08/09/19
*************************************************************/
#include"REGx52.h"
#include"JCHBASIC.H"
sbit a0 = ACC^0;
sbit a1 = ACC^1;
sbit a2 = ACC^2;
sbit a3 = ACC^3;
sbit a4 = ACC^4;
sbit a5 = ACC^5;
sbit a6 = ACC^6;
sbit a7 = ACC^7;
//sbit P1_0 = P1^0 ;
//sbit P1_1 = P1^1 ;
//sbit P1_2 = P1^2 ;
//sbit P3_7 = P3^7 ;
//sbit P3_6 = P3^6 ;
//sbit P3_5 = P3^5 ;
sbit DQ = P2^3 ; 		//18B20接口
sbit speaker = P3^7 ;	//蜂鸣器
sbit MODE = P2^7 ;	//模式键
sbit INC = P2^6 ;	//增加键
sbit DEC = P2^5 ;	//减少键
sbit OK = P2^4 ;	//OK键
#define LCD1602_DATA P0	//8位数据并行口
#define LCD1602_RS P1_0	//指令OR数据寄存器选择
#define LCD1602_RW P1_1	//读写控制
#define LCD1602_EN P1_2	//使能控制
#define LCD1602_CLR 0x01	//清屏
#define LCD1602_MODE 0x38	//8位数据,双列显示,5*7字形
#define LCD1602_ON 0x0c	//开显示,关光标,光标不闪烁
#define LCD1602_ADDR_MODE 0x06		//地址递增
#define DS1302_SCLK P2_2	//1302时钟线	
#define DS1302_IO P2_1		//1302数据线
#define DS1302_RST P2_0		//1302复位线

volatile uint8 data timedata[7] ;	//时间值
volatile uint8 data display_buffer1[16];	//显示缓冲区1 
volatile uint8 data display_buffer2[16];	//显示缓冲区2
volatile uint8 data temdata[5] ;	//存放温度值
volatile uint16 data tdat ;	//温度值变量
volatile uint8 data tflag ;	//温度正负值标志
volatile int8 self_pos = 0 ;//自定义三角形标志显示位置变量
volatile uint8 OK_VALUE = 0 ; //OK键键值变量 
volatile bit bdata DIS_ON = 1 ; //显示开关位 1 == on 0 == off
volatile bit bdata SCAN_ON = 0 ; //按键扫描开关位,由定时器每20MS刷新
volatile data MODE_ON = 0 ; //模式键按下后显示菜单的开关位
volatile data INC_VALUE = 0 ;
volatile data DEC_VALUE = 0 ;
volatile bit bdata ALARM_VALUE = 0 ;//闹钟标志位 
volatile bit bdata ALARM_ON = 1 ; //闹钟响时关闭标志位
volatile uint8 data read_1 = 1,read_2 = 1,read_3 = 1,read_4 = 1;
volatile uint8 data stopwatch_count = 0;
volatile uint8 data stopwatch_second = 0;
volatile uint8 data stopwatch_minute  = 0;
volatile bit bdata STOPWATCH_START = 0;
uint8 code self_table1[]={
						0x08,0x0f,0x12,0x0f,0x0a,0x1f,0x02,0x02,//	年
						0x1f,0x11,0x1f,0x11,0x1f,0x11,0x15,0x17,//月
						0x00,0x1f,0x11,0x1f,0x11,0x11,0x1f,0x00,//	日
						0x01,0x0c,0x17,0x14,0x17,0x0c,0x01,0x00,//闹钟标志
						0x10,0x18,0x1c,0x1e,0x1f,0x1c,0x18,0x10	};//三角形符号								


/**********************************************************
蜂鸣器
************************************************************/
void delay_ms(uint16 count)        // 延时时间count*1ms
{	uint16 i;
	for(;count>0;count--)
	{
		for(i=0;i<110;i++)
		{
			nop;
		}
	}
}
void speakers(uint8 speak_count)
{
	for(;speak_count>0;speak_count--)
		{
			speaker = 0 ;
			delay_ms(1) ;
			speaker = 1 ;
			delay_ms(3) ;
		}
}
/***********************************************************
忙检测
************************************************************/
 void LCD1602_check_busy(void)
{
	LCD1602_DATA = 0xff;
	LCD1602_RS = 0 ;	
	LCD1602_RW = 1 ;	
	LCD1602_EN = 1 ;	
	while(LCD1602_DATA & 0x80) ;	
	LCD1602_EN = 0 ;			
}

/**********************************************************
写指令
************************************************************/

 void LCD1602_write_cmd(uint8 cmd)
{
	LCD1602_check_busy();	
	LCD1602_RS = 0 ;	
	LCD1602_RW = 0 ;	
	LCD1602_DATA = cmd ;	
	LCD1602_EN = 1 ;	
	LCD1602_EN = 0 ;
}

/***********************************************************
写数据
*************************************************************/
 void LCD1602_write_data(uint8 dat)
{
	LCD1602_check_busy();	
	LCD1602_RS = 1 ;	
	LCD1602_RW = 0 ;	
	LCD1602_DATA = dat ;	
	LCD1602_EN = 1 ;	
	LCD1602_EN = 0 ;
}


/***********************************************************
1602初始化
************************************************************/
 void LCD1602_init(void)
{
	uint8 i  ;
	LCD1602_write_cmd(0x40);//CGRAM起始地址
	for(i=0;i<40;i++)
		LCD1602_write_data(self_table1[i]);//写入自定义字符
	LCD1602_write_cmd(LCD1602_MODE) ;
	LCD1602_write_cmd(LCD1602_ON) ;
	LCD1602_write_cmd(LCD1602_ADDR_MODE) ;
	LCD1602_write_cmd(LCD1602_CLR) ;
}

/************************************************************
设置显示坐标
************************************************************/
 void LCD1602_set_postion(uint8 x , uint8 y)
{
	if(y<2)
		{
			y &= 0x01 ;	//y值限定在0~1之间
			x &= 0x0f ;	//x值限定在0~15之间
			if(y == 0)
				x |= 0x40 ;	//如果显示是在第二行,则x的值加0x40
			x |= 0x80 ;		//获得x的值
			LCD1602_write_cmd(x) ;//写入坐标值到LCD
		}
}

/************************************************************
指定位置写字符
*************************************************************/
 void LCD1602_write_char(uint8 x , uint8 y , uint8 chardata)
{
	LCD1602_set_postion(x,y) ;
	LCD1602_write_data(chardata) ;
}

/************************************************************
指定位置写字符串
*************************************************************/
 void LCD1602_write_string(uint8 x , uint8 y , uint8 *string)
{
	LCD1602_set_postion(x,y) ;
	while((*string) != '\0')
	{	
		LCD1602_write_data(*string) ;
		string++ ;
	}
}
/***************************************************************
指定位置显示自定义字符
**************************************************************
uint8 LCD1602_display_self(uint8 count)
{
	switch(count)
		{
			case 0 : sele_count = 0 ; break ;
			case 1 : sele_count = 1 ; break ;
			case 2 : sele_count = 2 ; break ;
			case 3 : sele_count = 3 ; break ;
			default : break ;
		}
	return(self_count) ;
}*/


/****************************************************************
底层驱动函数(输入)
*****************************************************************/
 void DS1302_input(uint8 inputdata)
{
	ACC = inputdata ;
	DS1302_IO = a0 ; DS1302_SCLK = 1 ; DS1302_SCLK = 0 ;
	DS1302_IO = a1 ; DS1302_SCLK = 1 ; DS1302_SCLK = 0 ;
	DS1302_IO = a2 ; DS1302_SCLK = 1 ; DS1302_SCLK = 0 ;
	DS1302_IO = a3 ; DS1302_SCLK = 1 ; DS1302_SCLK = 0 ;
	DS1302_IO = a4 ; DS1302_SCLK = 1 ; DS1302_SCLK = 0 ;
	DS1302_IO = a5 ; DS1302_SCLK = 1 ; DS1302_SCLK = 0 ;
	DS1302_IO = a6 ; DS1302_SCLK = 1 ; DS1302_SCLK = 0 ;
	DS1302_IO = a7 ; DS1302_SCLK = 1 ; DS1302_SCLK = 0 ;
}

/****************************************************************
底层驱动函数(输出)控制位的第七位必须为1
*****************************************************************/
 uint8 DS1302_output(void)
{
	DS1302_IO = 1 ;
	a0 = DS1302_IO ;
	DS1302_SCLK = 1 ; DS1302_SCLK =0 ; a1 = DS1302_IO ;
	DS1302_SCLK = 1 ; DS1302_SCLK =0 ; a2 = DS1302_IO ;
	DS1302_SCLK = 1 ; DS1302_SCLK =0 ; a3 = DS1302_IO ;
	DS1302_SCLK = 1 ; DS1302_SCLK =0 ; a4 = DS1302_IO ;
	DS1302_SCLK = 1 ; DS1302_SCLK =0 ; a5 = DS1302_IO ;
	DS1302_SCLK = 1 ; DS1302_SCLK =0 ; a6 = DS1302_IO ;
	DS1302_SCLK = 1 ; DS1302_SCLK =0 ; a7 = DS1302_IO ;
	return(ACC);
}

/****************************************************************
底层驱动函数(指定地址写一个字节的数据)
*****************************************************************/
 void DS1302_write_byte(uint8 cmd , uint8 dat)
{
	DS1302_SCLK = 0 ;
	DS1302_RST = 0 ;
	DS1302_RST = 1 ;
	DS1302_input(cmd) ;
	DS1302_input(dat) ;
	DS1302_RST = 0 ;
	DS1302_SCLK = 1 ;
}

/****************************************************************
底层驱动函数(指定地址读取一字节的数据)
*****************************************************************/
 uint8 DS1302_read_byte(uint8 cmd)
{
	uint8 receivedata = 0 ;
	DS1302_SCLK = 0 ;
	DS1302_RST = 0 ;
	DS1302_RST = 1 ;
	DS1302_input(cmd) ;
	receivedata = DS1302_output() ;
	DS1302_RST = 0 ;
	DS1302_SCLK = 1 ;
	return(receivedata) ;
}

/********************************************************
设置1302的初始时间
*********************************************************/
 void DS1302_init()
{	
		if(DS1302_read_byte(0xc9) != 0xf0) 
		{
			DS1302_write_byte(0x8e,0x00) ;//允许写操作
			DS1302_write_byte(0xc8,0xf0) ; //写入初始化标志	,系统上电后检测此标志,即此子函数只会在第一次初始化一次。
			DS1302_write_byte(0x8c,0x08) ;//年
			DS1302_write_byte(0x8a,0x05) ;//星期
			DS1302_write_byte(0x88,0x09) ;//月
			DS1302_write_byte(0x86,0x19) ;//日
			DS1302_write_byte(0x84,0x12) ;//时
			DS1302_write_byte(0x82,0x00) ;//分
			DS1302_write_byte(0x80,0x00) ;//秒
			DS1302_write_byte(0x90,0xa5) ;//充电
			
			
	
			DS1302_write_byte(0x8e,0x80) ;//禁止写操作	 
		}
}

/********************************************************
读取时间数据并放在timedata[]中
*********************************************************/
 void DS1302_read_time()
{
	timedata[0] = DS1302_read_byte(0x8d) ;	//年
	timedata[1] = DS1302_read_byte(0x89) ;	//月
	timedata[2] = DS1302_read_byte(0x87) ;	//日
	timedata[3] = DS1302_read_byte(0x85) ;	//时
	timedata[4] = DS1302_read_byte(0x83) ;	//分
	timedata[5] = DS1302_read_byte(0x81) ;	//秒
	timedata[6] = DS1302_read_byte(0x8b) ;	//星期
}


/***********************************************************
DS18B20相关函数
*************************************************************/
void delay_18b20(uint16 sum) //短暂延时
{
	while(sum--);
}

void rst_18b20()                 //18B20复位
{	//uchar flag;
	DQ=1;
	delay_18b20(8);
	DQ=0;
	delay_18b20(80);
	DQ=1;
	delay_18b20(13);
	//flag=DQ;
	//return(flag);
//	delay_18b20(20);
}	


void wr_18b20(uint8 dat)	//写一个字节的数据
{
	uint8 i=8;
	for(;i>0;i--)
	{
		DQ=0;
		DQ=dat&0x01;
		delay_18b20(5);
		DQ=1;
		dat>>=1;
	}	
}

uint8 rd_18b20()		//读一个字节的内容
{
	uint8 dat=0,i=8;
	for(;i>0;i--)
	{
		DQ=0;
		dat>>=1;
		DQ=1;
		if(DQ)
		dat|=0x80;
		delay_18b20(4);
	}
	return(dat);
}
uint16 rd_temperature()		//读取温度值
{	
	uint8 a=0,b=0;
	uint16 t=0;
	float tt=0;
	rst_18b20();		//复位
	wr_18b20(0xcc);		//跳过ROM
	wr_18b20(0x44);		//启动温度转换
	rst_18b20();		//再次对18B20操作时,需要重新复位一次
	wr_18b20(0xcc);		//跳过ROM
	wr_18b20(0xbe);		//读取内部RAM的内容
	a=rd_18b20();		//读温度值低位(内部RAM的第0个字节)
	b=rd_18b20();		//读温度值高位(内部RAM的第1个字节)
	t=b;
	t<<=8;				//温度值的高8位放在t的高8位
	t=t|a;				//温度值的低8位放在t的低8位
	if(t<0x0fff)		//判断温度值得正负值
   		tflag=0;		//tflag=0温度值为正
    else
   {
		t=~t+1;			//温度值为负,负值以补码形式存放,这里要将其还原成原码
		tflag=1;		//tflag=1温度值为负
   }
	tt=t*0.0625;
	t = tt*100 ;			

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -