#include <REG52.H>
#include <intrins.H>
#include <math.h>
/* 液晶引脚定义 */ //1602
#define LCD_DB P0 //P0.0-P0.7 DB0-DB7
sbit LCD_RS=P2^0; //data/command (HL)
sbit LCD_RW=P2^1; //read/write(HL)
sbit LCD_E=P2^2; //disenable/enable
/* 温度传感器引脚定义 */ //DS18B20
sbit B20_IO=P1^3;
/* 时钟芯片引脚定义 */ //DS1302
sbit DS1302_IO=P1^0;
sbit DS1302_SCLK=P1^1;
sbit DS1302_RST_CE=P1^2; //CE
/* 独立按键引脚定义 */
sbit KeyOne = P3^2; //功能键
sbit KeyThree = P3^3; //+
sbit KeyTwo = P3^4; //-
sbit KeyFour = P3^5;
/* 第0位 第八位 位操作 */
sbit ACC0=ACC^0;
sbit ACC7=ACC^7;
/* 报警指示引脚定义 */
sbit Red = P3^6;
sbit Green = P3^7;
sbit Beep = P1^4;
#if 0
/* 时钟芯片寄存器定义 */
#define write_second 0x80
#define write_minute 0x82
#define write_hour 0x84
#define write_day 0x86
#define write_month 0x88
#define write_week 0x8a
#define write_year 0x8c
#else
/* 时钟芯片寄存器定义 */
#define write_second 0x80
#define read_second 0x81
#define write_minute 0x82
#define read_minute 0x83
#define write_hour 0x84
#define read_hour 0x85
#define write_day 0x86
#define read_day 0x87
#define write_month 0x88
#define read_month 0x89
#define write_year 0x8c
#define read_year 0x8d
#define write_week 0x8a
#define read_week 0x8b
#endif
/* 按键状态 */
enum KEYSTART
{
KEYDOWN, //0 按下
KEYUP
};
/* 按键键值 */
enum KEYCONFIG
{
KEYINIT,
KEYYEAR,
KEYMONTH,
KEYDAY,
KEYWEEK,
KEYHOUR,
KEYMINTH,
KEYALARH,
KEYALARM
};
/* 逻辑变量定义 */
unsigned char miao=0,shi=0,fen=0,ri=0,yue=0,nian=0,week=0;
extern unsigned char miao,shi,fen,ri,yue,nian,week;
unsigned int TempVal=0,AlarmFlag=0;
unsigned char YearData=0,MonthData=0,DayData=0,WeekData=0,HourData=0,
MinuteData=0,AlarmH=0,AlarmM=0;
/* n*10微妙延时 */
void delay_n10us(unsigned int n)
{
unsigned int i=0;
for(i=n;i>0;i--)
{
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}
}
/* 写命令函数 */
void LCD_write_command(unsigned char dat)
{
delay_n10us(10);
LCD_RS=0;
LCD_RW=0;
LCD_E=1;
LCD_DB=dat;
delay_n10us(10);
LCD_E=0;
delay_n10us(10);
}
/* 写数据函数 */
void LCD_write_data(unsigned char dat)
{
delay_n10us(10);
LCD_RS=1;
LCD_RW=0;
LCD_E=1;
LCD_DB=dat;
delay_n10us(10);
LCD_E=0;
delay_n10us(10);
}
/* 写字符函数 X:0~15 Y:1,2 */
void LCD_disp_char(const unsigned char x,const unsigned char y,unsigned char dat)
{
unsigned char address=0;
if(y==1)
address=0x80+x;
else
address=0xc0+x;
//address = 0x80 + 0x40 + x;
LCD_write_command(address);
LCD_write_data(dat);
}
/* 写一串字符 X:0~15 Y:1,2 */
void LCD_disp_str(const unsigned char x,const unsigned char y,const unsigned char *str)
{
unsigned char address=0;
if(y==1)
address=0x80+x;
else
address=0xc0+x;
LCD_write_command(address);
while(*str!='\0')
{
LCD_write_data(*str);
str++;
}
}
/* 液晶初始化 */
void LCD_init(void)
{
delay_n10us(10);
LCD_write_command(0x38);//16x2显示 5X7点阵 8bit数据接口
delay_n10us(10);
LCD_write_command(0x0c);//开显示,不显示光标 00001100
delay_n10us(10);
LCD_write_command(0x06);//写最后一个字符后,地址指针自动加1
delay_n10us(10);
LCD_write_command(0x01);//显示清0,数据指针清0
delay_n10us(100);
}
/* 温度传感器最小单位延时 */
/* 延时n x ms */ //1000(1s)
void delay_n_ms(unsigned int ms)
{
unsigned int i=0,j=0;
for(i=ms;i>0;i--)
for(j=110;j>0;j--);
}
/*
温度传感器复位操作
DS18B20 复位, INIT
初始化DS18B20
让DS18B20一段相对长时间低电平, 然后一段相对非常短时间高电平, 即可启动
一定要使用unsigned int型, 一个i++指令的时间, 作为与DS18B20通信的小时间间隔
*/
void dsB20_reset(void)
{
unsigned int i=0;
B20_IO=0;
i=105;
while(i>0)
i--;
B20_IO=1;
i=5;
while(i>0)
i--;
}
/* 读温度传感器一位数据信息 */
/*
读DS18B20 1bit
向DS18B20读取一位数据
读一位, 让DS18B20一小周期低电平, 然后两小周期高电平,
之后DS18B20则会输出持续一段时间的一位数据
*/
bit temp_read_bit(void) //temperature
{
unsigned int i=0;
bit dat=0;
B20_IO=0;
i++;
B20_IO=1;
i++;
i++;
dat=B20_IO;
i=8;
while(i>0)
i--;
return (dat);
}
/* 读温度传感器八位数据信息 */
unsigned char temp_read_byte(void)
{
unsigned char i=0,j=0,dat=0;
for(i=1;i<=8;i++)
{
j=temp_read_bit(); //最先读出的是最低位数据
dat=(j<<7)|(dat>>1);
}
return(dat);
}
/* 写DS18B20 八位数据 */
void temp_write_byte(unsigned char dat)
{
unsigned int i=0;
unsigned char j=0;
bit testb=0;
for(j=1;j<=8;j++)
{
testb=dat&0x01;
dat=dat>>1;
if(testb) //write 1 让低电平持续2个小延时, 高电平持续8个小延时
{
B20_IO=0;
i++;
i++;
B20_IO=1;
i=8;
while(i>0)
i--;
}
else
{
B20_IO=0; //write 0 让低电平持续8个小延时, 高电平持续2个小延时
i=8;
while(i>0)
i--;
B20_IO=1;
i++;
i++;
}
}
}
/* DS18B20开始获取温度并转换 */
void temp_change(void)
{
dsB20_reset();
delay_n_ms(1);
temp_write_byte(0xcc); //cc 跳过rom
temp_write_byte(0x44); //44 转换
}
/* 读取温度寄存器转换数据 */
unsigned int get_temp_value(void)
{
float tt=0;
unsigned char a=0,b=0;
unsigned int tempA=0;
dsB20_reset();
delay_n_ms(1);
temp_write_byte(0xcc);
temp_write_byte(0xbe);//读取数据命令
a=temp_read_byte();//读低8位
b=temp_read_byte();//读高8位
//高低两字节合并为一个整形变量
tempA=b;
tempA<<=8;
tempA=tempA|a;
tt=tempA*0.0625;//精确度为0.0625度
tempA=tt*10+0.5;//乘以10,表示小数点后只取一位, 0.5是进行4舍5入
return tempA;
}
/*
控制字总是从最低位开始输出。在控制字指令输入
后的下一个SCLK时钟的上升沿时,数据被写入DS1302
数据输入从最低位(0位)开始。
同样,在紧跟8位的控制字指令后的下一个SCLK脉
冲的下降沿,读出DS1302的数据,读出的数据也是
从最低位到最高位。
*/
/* 写时钟芯片八位数据信息 */
void write_1302_byte(unsigned char dat)
{
unsigned char a=0;
ACC=dat;
DS1302_RST_CE=1; // CE:输入信号,在读、写数据期间,必须为高。
for(a=8;a>0;a--)
{
DS1302_IO=ACC0;
DS1302_SCLK=0;
//delay_n_ms(1);
DS1302_SCLK=1;//上升沿写入,下降沿读出
//delay_n_ms(1);
ACC=ACC>>1;
}
}
/* 读时钟芯片八位数据信息 */
unsigned char read_1302_byte()
{
unsigned char a=0;
DS1302_RST_CE=1;
for(a=8;a>0;a--)
{
ACC7=DS1302_IO;
DS1302_SCLK=1;
//delay_n_ms(1);
DS1302_SCLK=0;
//delay_n_ms(1);
ACC=ACC>>1;
}
return (ACC);
}
/* 在时钟芯片指定位置写指定数据 */
void write_1302_addr_data(unsigned char add,unsigned char dat)
{
DS1302_RST_CE=0;//初始CE线置为0
DS1302_SCLK=0; //初始时钟线置为0
DS1302_RST_CE=1;//初始CE置为1,传输开始
write_1302_byte(add);
write_1302_byte(dat);
DS1302_SCLK=1; //时钟线拉高
DS1302_RST_CE=0;//读取结束,CE置为0,结束数据的传输
}
/* 读取时钟芯片指定地址的数据信息 */
unsigned char read_1302_addr_data(unsigned char add)
{
unsigned char temp;
DS1302_RST_CE=0;
DS1302_SCLK=0;
DS1302_RST_CE=1;
write_1302_byte(add);
temp=read_1302_byte();
DS1302_SCLK=1;
DS1302_RST_CE=0;
return(temp);
}
/* 时钟芯片数据转换 */
unsigned char BCD_Decimal(unsigned char bcd)
{
unsigned char Decimal;
Decimal=bcd>>4;
return(Decimal=Decimal*10+(bcd&=0x0F));
}
/* 时钟芯片初始化操作 */
/*
控制寄存器(8Fh、8Eh)的位7是写保护位(WP)
其它7位均置为0。在任何的对时钟和RAM的写操作之前
WP位必须为0。当WP位为1时,写保护位
防止对任一寄存器的写操作.
*/
void ds1302_init()
{
DS1302_RST_CE=0;
DS1302_SCLK=0;
write_1302_addr_data(0x8e,0x00); //写保护关 将控制寄存器值设为0,wp=0允许写
write_1302_addr_data(0x8e,0x80); //写保护开,防止影响时间值
}
/* 设置时钟芯片参数信息 */
void Set_RTC(unsigned char address,unsigned char temp)
{
unsigned char tmp=0;
tmp=temp/10;
temp=temp%10;
temp=temp+tmp*16;
write_1302_addr_data(0x8E,0X00);
write_1302_addr_data(address,temp&0x7f);
write_1302_addr_data(0x8E,0x80);
}
/* 提取时钟芯片时间信息 */
void GetTime(void)
{
#if 0
miao = BCD_Decimal(read_1302_addr_data(0x81));
fen = BCD_Decimal(read_1302_addr_data(0x83));
shi = BCD_Decimal(read_1302_addr_data(0x85));
ri = BCD_Decimal(read_1302_addr_data(0x87));
yue = BCD_Decimal(read_1302_addr_data(0x89));
nian=BCD_Decimal(read_1302_addr_data(0x8d));
week=BCD_Decimal(read_1302_addr_data(0x8b));
#else
nian = BCD_Decimal(read_1302_addr_data(read_year));
yue = BCD_Decimal(read_1302_addr_data(read_month));
ri = BCD_Decimal(read_1302_addr_data(read_day));
shi = BCD_Decimal(read_1302_addr_data(read_hour));
fen = BCD_Decimal(read_1302_addr_data(read_minute));
miao = BCD_Decimal(read_1302_addr_data(read_second));
week = BCD_Decimal(read_1302_addr_data(read_week))-1;
#endif
}
/* 按键消抖动 */
void KeyDelay(void)
{
unsigned char i=0,j=0;
for(i=15;i>0;i--)
for(j=80;j>0;j--);
}
/* 读取按键键值 */
unsigned char KeyProcess(void)
{
static unsigned char KeyVal=KEYINIT;
if(KeyOne==KEYDOWN)
{
KeyDelay();
if(KeyOne==KEYDOWN)
{
while(KeyOne==KEYDOWN);
LCD_disp_str(0,1," ");
LCD_disp_str(0,2," ");
KeyVal++;
if(KeyVal>KEYALARM)
KeyVal=KEYINIT;
}
}
return KeyVal;
}
/* 定时器配置 */
void Time_init() //定时器、计数器设置函数
//void init() //定时器、计数器设置函数
{
TMOD=0x01; //指定定时/计数器的工作方式为3
// TMOD=0x01; 定时器0 中断号1 方式1 16位定时器
TH0=0x3c; //定时器T0的高四位=0
TL0=0xb0; //定时器T0的低四位=0
EA=1; //系统允许有开放的中断
ET0=1; //允许T0中断
TR0=1; //开启中断,启动定时器T0
}
/* 外围硬件初始化 */
void HandInit(void)
{
LCD_init();
ds1302_init();
Time_init();
Red = 1;
Green = 0;
}
/* 年月日信息显示 */
void show_Data(void)
{
unsigned char dis_Data[16]={0};
dis_Data[0]='2';
dis_Data[1]='0';
dis_Data[2]=(nian/10)+'0'; //ascii0(48) 0x30(48)
//dis_Data[2]=(nian/10)+'0';
dis_Data[3]=(nian%10)+'0';
dis_Data[4]='-';
dis_Data[5]=(yue/10)+'0';
dis_Data[6]=(yue%10)+'0';
dis_Data[7]='-';
dis_Data[8]=(ri/10)+'0';
dis_Data[9]=(ri%10)+'0';
dis_Data[10]=' ';
dis_Data[11]='W';
dis_Data[12]=126;//~
dis_Data[13]='<';
dis_Data[14]=(week%10)+'0';
dis_Data[15]='>';
LCD_disp_str(0,1,dis_Data);
}
/* 时分秒温度信息显示 */
void Show_Time_Temperature(void)
{
unsigned char dis_Time[16]={0};
dis_Time[0]=' ';
dis_Time[1]=(shi/10)+'0';
dis_Time[2]=(shi%10)+'0';
dis_Time[3]=':';
dis_Time[4]=(fen/10)+'0';
dis_Time[5]=(fen%10)+'0';
dis_Time[6]=':';
dis_Time[7]=(miao/10)+'0';
dis_Time[8]=(miao%10)+'0';
dis_Time[9]=' ';
dis_Time[10]=TempVal/100+'0';
dis_Time[11]=TempVal%100/10+'0';
dis_Time[12]='.';
dis_Time[13]=TempVal%10+'0';
dis_Time[14]=223;
dis_Time[15]='C';
LCD_disp_str(0,2,dis_Time);
}
/* 设置年参数 */
void Set_Year(void)
{
YearData=read_1302_addr_data(0x8D);
YearData=(YearData>>4)*10+(YearData&0x0f);
if(KeyTwo==KEYDOWN)
{
KeyDelay();
if(KeyTwo==KEYDOWN)
{
while(KeyTwo==KEYDOWN);
if(YearData<=0)
YearData=1;
YearData-=1;
Set_RTC(write_year,YearData);
}
}
if(KeyThree==KEYDOWN)
{
KeyDelay();
if(KeyThree==KEYDOWN)
{
while(KeyThree==KEYDOWN);
if(YearData>=99)
YearData=98;
YearData+=1;
Set_RTC(write_year,YearData);
}
}
LCD_disp_str(0,1," SET YEAR ");
LCD_disp_char(4,2,'2');
LCD_disp_char(5,2,'0');
LCD_disp_char(6,2,YearData/10+'0');
LCD_disp_char(7,2,YearData%10+'0');
}
/* 设置月参数 */
void SetMonth(void)
{
MonthData=read_1302_addr_data(0x89);
MonthData=(MonthData>>4)*10+(MonthData&0x0f);
if(KeyTwo==KEYDOWN)
{
KeyDelay();
if(KeyTwo==KEYDOWN)
{
while(KeyTwo==KEYDOWN);
if(MonthData<=1)
MonthData=2;
MonthData-=1;
Set_RTC(write_month,MonthData);
}
}
if(KeyThree==KEYDOWN)
{
KeyDelay();
if(KeyThree==KEYDOWN)
{
while(KeyThree==KEYDOWN);
if(MonthData>=12)
MonthData=11;
MonthData+=1;
Set_RTC(write_month,MonthData);
}
}
LCD_disp_str(0,1," SET MONTH ");
LCD_disp_char(6,2,MonthData/10+'0');
LCD_disp_char(7,2,MonthData%10+'0');
}
/* 设置日参数 */
void SetDay(void)
{
DayData=read_1302_addr_data(0x87);
DayData=(DayData>>4)*10+(DayData&0x0f);
if(KeyTwo==KEYDOWN)
{
KeyDelay();
if(KeyTwo==KEYDOWN)
{
while(KeyTwo==KEYDOWN);
if(DayData<=1)
DayData=2;
DayData-=1;
Set_RTC(write_day,DayData);
}
}
if(KeyThree==KEYDOWN)
{
KeyDelay();
if(KeyThree==KEYDOWN)
{
while(KeyThree==KEYDOWN);
if(DayData>=30)
DayData=29;
DayData+=1;
Set_RTC(write_day,DayData);
}
}
LCD_disp_str(0,1," SET DAY ");
LCD_disp_char(6,2,DayData/10+'0');
LCD_disp_char(7,2,DayData%10+'0');
}
/* 设置周期参数 */
void SetWeek(void)
{
WeekData=read_1302_addr_data(0x8b);
WeekData=(WeekData>>4)*10+(WeekData&0x0f);
if(KeyTwo==KEYDOWN)
{
KeyDelay();
if(KeyTwo==KEYDOWN)
{
while(KeyTwo==KEYDOWN);
if(WeekData<=1)
WeekData=2;
WeekData-=1;
Set_RTC(write_week,WeekData);
}
}
if(KeyThree==KEYDOWN)
{
KeyDelay();
if(KeyThree==KEYDOWN)
{
while(KeyThree==KEYDOWN);
if(WeekData>=7)
WeekData=6;
WeekData+=1;
Set_RTC(write_week,WeekData);
}
}
LCD_disp_str(0,1," SET WEEK ");
LCD_disp_char(6,2,WeekData/10+'0');
LCD_disp_char(7,2,WeekData%10+'0');
}
/* 设置小时参数 */
void SetHour(void)
{
HourData=read_1302_addr_data(0x85);
HourData=(HourData>>4)*10+(HourData&0x0f);
if(KeyTwo==KEYDOWN)
{
KeyDelay();
if(KeyTwo==KEYDOWN)
{
while(KeyTwo==KEYDOWN);
if(HourData<=0)
HourData=1;
HourData-=1;
Set_RTC(write_hour,HourData);
}
}
if(KeyThree==KEYDOWN)
{
KeyDelay();
if(KeyThree==KEYDOWN)
{
while(KeyThree==KEYDOWN);
if(HourData>=23)
HourData=22;
HourData+=1;
Set_RTC(write_hour,HourData);
}
}
LCD_disp_str(0,1," SET HOUR ");
LCD_disp_char(6,2,HourData/10+'0');
LCD_disp_char(7,2,HourData%10+'0');
}
/* 设置分钟参数 */
void SetMinute(void)
{
MinuteData=read_1302_addr_data(0x83);
MinuteData=(MinuteData>>4)*10+(MinuteData&0x0f);
if(KeyTwo==KEYDOWN)
{
KeyDelay();
if(KeyTwo==KEYDOWN)
{
while(KeyTwo==KEYDOWN);
if(MinuteData<=0)
MinuteData=1;
MinuteData-=1;
Set_RTC(write_minute,MinuteData);
}
}
if(KeyThree==KEYDOWN)
{
KeyDelay();
if(KeyThree==KEYDOWN)
{
while(KeyThree==KEYDOWN);
if(MinuteData>=59)
MinuteData=58;
MinuteData+=1;
Set_RTC(write_minute,MinuteData);
}
}
LCD_disp_str(0,1," SET MINUTE ");
LCD_disp_char(6,2,MinuteData/10+'0');
LCD_disp_char(7,2,MinuteData%10+'0');
}
/* 设置闹钟小时参数 */
void SetAlarH(void)
{
if(KeyTwo==KEYDOWN)
{
KeyDelay();
if(KeyTwo==KEYDOWN)
{
while(KeyTwo==KEYDOWN);
if(AlarmH<=0)
AlarmH=1;
AlarmH-=1;
}
}
if(KeyThree==KEYDOWN)
{
KeyDelay();
if(KeyThree==KEYDOWN)
{
while(KeyThree==KEYDOWN);
if(AlarmH>=23)
AlarmH=22;
AlarmH+=1;
}
}
LCD_disp_str(0,1," SET ALARMH ");
LCD_disp_char(6,2,AlarmH/10+'0');
LCD_disp_char(7,2,AlarmH%10+'0');
}
/* 设置闹钟分钟参数 */
void SetAlarM(void)
{
if(KeyTwo==KEYDOWN)
{
KeyDelay();
if(KeyTwo==KEYDOWN)
{
while(KeyTwo==KEYDOWN);
if(AlarmM<=0)
AlarmM=1;
AlarmM-=1;
}
}
if(KeyThree==KEYDOWN)
{
KeyDelay();
if(KeyThree==KEYDOWN)
{
while(KeyThree==KEYDOWN);
if(AlarmM>=59)
AlarmM=58;
AlarmM+=1;
}
}
LCD_disp_str(0,1," SET ALARMM ");
LCD_disp_char(6,2,AlarmM/10+'0');
LCD_disp_char(7,2,AlarmM%10+'0');
}
/* 逻辑信息处理 */
void Process(void)
{
unsigned char StartChange=KEYINIT;
StartChange=KeyProcess();
if(KeyFour==KEYDOWN)
{
KeyDelay();
if(KeyFour==KEYDOWN)
{
while(KeyFour==KEYDOWN);
AlarmFlag=!AlarmFlag;
if(AlarmFlag)
{
Red = 0;
Green = 1;
}
else
{
Red = 1;
Green = 0;
}
}
}
switch(StartChange)
{
case KEYINIT:
show_Data();
Show_Time_Temperature();
break;
case KEYYEAR:
Set_Year();
break;
case KEYMONTH:
SetMonth();
break;
case KEYDAY:
SetDay();
break;
case KEYWEEK:
SetWeek();
break;
case KEYHOUR:
SetHour();
break;
case KEYMINTH:
SetMinute();
break;
case KEYALARH:
SetAlarH();
break;
case KEYALARM:
SetAlarM();
break;
default:break;
}
}
/* 取得并显示日历和时间 */
void timer0() interrupt 1
{
TH0=0x3c; //定时器T0的高四位=0
TL0=0xb0; //定时器T0的低四位=0
temp_change();
TempVal=get_temp_value();
GetTime();
if(AlarmFlag)
{
HourData=read_1302_addr_data(0x85);
HourData=(HourData>>4)*10+(HourData&0x0f);
MinuteData=read_1302_addr_data(0x83);
MinuteData=(MinuteData>>4)*10+(MinuteData&0x0f);
if((HourData==AlarmH)&&(MinuteData==AlarmM))
{
Beep=!Beep;
}
}
else
{
Beep=0;
}
}
/* 主函数 */
void main(void)
{
HandInit();
while(1)
{
Process();
}
}
万年历
最新推荐文章于 2022-08-25 11:07:18 发布