主要涉及温度传感器 DS18B20 实时时钟DS1302 官网驱动改写。需要注意时间越界问题,小时最多到23,分钟59,秒59,进行判断
#include
#include "ds1302.h"
#include "onewire.h"
#define uchar unsigned char
#define uint unsigned int
uchar code tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff,0xc6};
uchar yi,er,san,si,wu,liu,qi,ba;
uchar tem=0;//温度
uchar timeset=4;//时间设置
uchar clockset=0;//闹钟设置
uchar alarm[3]={0,0,0};//闹钟时间 秒 分 时
uchar show_tem=0;//温度显示
uchar s4=0;
uchar tt=0;
uint count=0;
uchar led=0;
uchar led_show=0;
void allinit();
void Delay1ms(uint ms);
void display1(uchar yi,uchar er);
void display2(uchar san,uchar si);
void display3(uchar wu,uchar liu);
void display4(uchar qi,uchar ba);
void keyscan();
void Timer0Init(void);
void main()
{
allinit();
Timer0Init();
Ds1302_Init();
// yi=1;er=2;san=3;si=4;wu=5;liu=1;qi=7;ba=8;
while(1)
{
Ds1302_TimeGet();
tem=temget();
if(show_tem==0)
{
if(timeset==4)//时钟显示
{
yi=time[2]/10;er=time[2]%10;san=10;
si=time[1]/10;wu=time[1]%10;liu=10;
qi=time[0]/10;ba=time[0]%10;
}
else if(timeset==1)//小时设置
{
if(time[0]%2==1)//通过判断秒进行数码管闪烁 奇数秒亮 偶数灭
{
yi=time[2]/10;er=time[2]%10;san=10;
si=time[1]/10;wu=time[1]%10;liu=10;
qi=time[0]/10;ba=time[0]%10;
}
else
{
yi=11;er=11;san=10;
si=time[1]/10;wu=time[1]%10;liu=10;
qi=time[0]/10;ba=time[0]%10;
}
}
else if(timeset==2)//分钟设置
{
if(time[0]%2==1)
{
yi=time[2]/10;er=time[2]%10;san=10;
si=time[1]/10;wu=time[1]%10;liu=10;
qi=time[0]/10;ba=time[0]%10;
}
else
{
yi=time[2]/10;er=time[2]%10;san=10;
si=11;wu=11;liu=10;
qi=time[0]/10;ba=time[0]%10;
}
}
else if(timeset==3)//秒设置
{
if(time[0]%2==1)
{
yi=time[2]/10;er=time[2]%10;san=10;
si=time[1]/10;wu=time[1]%10;liu=10;
qi=time[0]/10;ba=time[0]%10;
}
else
{
yi=time[2]/10;er=time[2]%10;san=10;
si=time[1]/10;wu=time[1]%10;liu=10;
qi=11;ba=11;
}
}
if(clockset==4)//闹钟显示
{
Ds1302_TimeGet();
yi=alarm[2]/10;er=alarm[2]%10;san=10;
si=alarm[1]/10;wu=alarm[1]%10;liu=10;
qi=alarm[0]/10;ba=alarm[0]%10;
}
else if(clockset==1)//小时设置
{
if(time[0]%2==1)
{
yi=alarm[2]/10;er=alarm[2]%10;san=10;
si=alarm[1]/10;wu=alarm[1]%10;liu=10;
qi=alarm[0]/10;ba=alarm[0]%10;
}
else
{
yi=11;er=11;san=10;
si=alarm[1]/10;wu=alarm[1]%10;liu=10;
qi=alarm[0]/10;ba=alarm[0]%10;
}
}
else if(clockset==2)//分钟设置
{
if(time[0]%2==1)
{
yi=alarm[2]/10;er=alarm[2]%10;san=10;
si=alarm[1]/10;wu=alarm[1]%10;liu=10;
qi=alarm[0]/10;ba=alarm[0]%10;
}
else
{
yi=alarm[2]/10;er=alarm[2]%10;san=10;
si=11;wu=11;liu=10;
qi=alarm[0]/10;ba=alarm[0]%10;
}
}
else if(clockset==3)//秒设置
{
if(time[0]%2==1)
{
yi=alarm[2]/10;er=alarm[2]%10;san=10;
si=alarm[1]/10;wu=alarm[1]%10;liu=10;
qi=alarm[0]/10;ba=alarm[0]%10;
}
else
{
yi=alarm[2]/10;er=alarm[2]%10;san=10;
si=alarm[1]/10;wu=alarm[1]%10;liu=10;
qi=11;ba=11;
}
}
}
else if(show_tem==1)
{
yi=11;er=11;san=11;si=11;wu=11;liu=tem/10;qi=tem%10;ba=12;//长按S4进行温度显示
}
if((time[2]==alarm[2])&&(time[1]==alarm[1])&&(time[0]==alarm[0]))//闹钟
{
EA=1;ET0=1;//打开中断控制led闪烁
led_show=1;
}
keyscan();
display1(yi,er);
display2(san,si);
display3(wu,liu);
display4(qi,ba);
}
}
void keyscan()
{
if(P30==0)//s7
{
Delay1ms(5);
if(P30==0)
{
if(led_show==0)
{
//时间显示和闹钟界面只能显示一个
if(timeset==0) {timeset=4;clockset=0;}//时间显示 闹钟不显示
else if(timeset==4) timeset=1;//时间显示 timeset初始化为4
else if(timeset==1) timeset=2;
else if(timeset==2) timeset=3;
else if(timeset==3) timeset=4;
}
else if(led_show==1)
{
led_show=0;
P2=0X80;
P0=0XFF;
}
}
while(!P30);
}
else if(P31==0)//s6
{
Delay1ms(5);
if(P31==0)
{
if(led_show==0)
{
if(clockset==0) {clockset=4;timeset=0;}// 闹钟显示 时间不显示
else if(clockset==4) clockset=1;//时间显示 timeset初始化为4
else if(clockset==1) clockset=2;
else if(clockset==2) clockset=3;
else if(clockset==3) clockset=4;
}
else if(led_show==1)
{
led_show=0;
P2=0X80;
P0=0XFF;
}
}
while(!P31);
}
else if(P32==0)//s5
{
Delay1ms(5);
if(P32==0)
{
if(led_show==0)
{
//时间调整 时 分 秒
if(timeset==1)
{
if(time[2]==23)
time[2]=0;
else time[2]++;Ds1302_Init();
}
else if(timeset==2)
{
if(time[1]==59)
time[1]=0;
else time[1]++;Ds1302_Init();
}
else if(timeset==3)
{
if(time[0]==59)
time[0]=0;
else time[0]++;Ds1302_Init();
}
//调整闹钟 时 分 秒
else if(clockset==1)
{
if(alarm[2]==23)
alarm[2]=0;
else{alarm[2]++;}
}
else if(clockset==2)
{
if(alarm[1]==59)
alarm[1]=0;
else{alarm[1]++;}
}
else if(clockset==3)
{
if(alarm[0]==59)
alarm[0]=0;
else{alarm[0]++;}
}
}
else if(led_show==1)
{
led_show=0;
P2=0X80;
P0=0XFF;
}
while(!P32);
}
}
else if(P33==0)//s4
{
Delay1ms(5);
if(P33==0)
{
s4=1;//判断按键是否按下的标志位
if(timeset==4) show_tem=1;
}
}
//====写在按键检测之后======//
if((s4==1)&&(P33==1))
{
s4=0;show_tem=0;
if(led_show==0)
{
//时间调整 时 分 秒
if(timeset==1)
{
if(time[2]==0)
time[2]=23;
else {time[2]--;}
Ds1302_Init();
}
else if(timeset==2)
{
if(time[1]==0)
time[1]=59;
else {time[1]--;}
Ds1302_Init();//if else 之后的语句都进行初始化
}
else if(timeset==3)
{
if(time[0]==0)
time[0]=59;
else {time[0]--;}
Ds1302_Init();
}
//调整闹钟 时 分 秒
else if(clockset==1)
{
if(alarm[2]==0)
alarm[2]=23;
else {alarm[2]--;}
}
else if(clockset==2)
{
if(alarm[1]==0)
alarm[1]=59;
else {alarm[1]--;}
}
else if(clockset==3)
{
if(alarm[0]==0)
alarm[0]=59;
else{alarm[0]--;}
}
}
else if(led_show==1)
{
led_show=0;
P2=0X80;
P0=0XFF;
}
}
}
void Timer0Init(void) //5毫秒@12.000MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0xA0; //设置定时初值
TH0 = 0x15; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
}
void Timer0(void) interrupt 1
{
tt++;
count++;
if(count==1000)
{
count=0;
EA=0;
ET0=0;//5s后关闭中断
led_show=0;//标志位置0
P2=0X80;
P0=0XFF;//关闭led 避免及时到最后是点亮的情况
}
if((tt==40)&&(led_show==1))//led闪烁
{
tt=0;
if(led==0)
{
P2=0X80;
P0=0XFF;
led=1;
}
else if(led==1)
{
P2=0X80;
P0=0XFE;
led=0;
}
}
}
void allinit()
{
P2=0X80;
P0=0XFF;
P2=0XC0;
P0=0XFF;
P2=0XE0;
P0=0XFF;
P2=0XA0;
P0=0X00;
}
void Delay1ms(uint ms) //@12.000MHz
{
uint k;
unsigned char i, j;
for(k=ms;k>0;k--)
{
i = 12;
j = 169;
do
{
while (--j);
} while (--i);
}
}
void display1(uchar yi,uchar er)
{
P2=0XC0;
P0=0X01;
P2=0XE0;
P0=tab[yi];
Delay1ms(1);
P2=0XC0;
P0=0X02;
P2=0XE0;
P0=tab[er];
Delay1ms(1);
}
void display2(uchar san,uchar si)
{
P2=0XC0;
P0=0X04;
P2=0XE0;
P0=tab[san];
Delay1ms(1);
P2=0XC0;
P0=0X08;
P2=0XE0;
P0=tab[si];
Delay1ms(1);
}
void display3(uchar wu,uchar liu)
{
P2=0XC0;
P0=0X10;
P2=0XE0;
P0=tab[wu];
Delay1ms(1);
P2=0XC0;
P0=0X20;
P2=0XE0;
P0=tab[liu];
Delay1ms(1);
}
void display4(uchar qi,uchar ba)
{
P2=0XC0;
P0=0X40;
P2=0XE0;
P0=tab[qi];
Delay1ms(1);
P2=0XC0;
P0=0X80;
P2=0XE0;
P0=tab[ba];
Delay1ms(1);
P2=0XC0;
P0=0XFF;
P2=0XE0;
P0=0XFF;//关闭所有数码管使其亮度一致
}
onewire
/*
程序说明: 单总线驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台
日 期: 2011-8-9
*/
#include "onewire.h"
//单总线延时函数
void Delay_OneWire(unsigned int t)
{
t=12*t;
while(t--);
}
//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;
}
//通过单总线向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;
}
//温度获取函数
unsigned char temget(void)
{
unsigned char low,high;
unsigned char temp;
Init_DS18B20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
Delay_OneWire(200);
Init_DS18B20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
low=Read_DS18B20();
high=Read_DS18B20();
temp=(low>>4)|(high<<4);
return temp;
}
#ifndef _ONEWIRE_H
#define _ONEWIRE_H
#include
#define OW_SKIP_ROM 0xcc
#define DS18B20_CONVERT 0x44
#define DS18B20_READ 0xbe
//IC引脚定义
sbit DQ = P1^4;
//函数声明
void Delay_OneWire(unsigned int t);
void Write_DS18B20(unsigned char dat);
bit Init_DS18B20(void);
unsigned char Read_DS18B20(void);
unsigned char temget(void);
#endif
ds1302
#include "ds1302.h"
unsigned char time[]={50,59,23,0,0,0,0};
/********************************************************************/
/*单字节写入一字节数据*/
void Write_Ds1302_Byte(unsigned char dat)
{
unsigned char i;
SCK = 0;
for (i=0;i<8;i++)
{
if (dat & 0x01) // 等价于if((addr & 0x01) ==1)
{
SDA_SET; //#define SDA_SET SDA=1 /*电平置高*/
}
else
{
SDA_CLR; //#define SDA_CLR SDA=0 /*电平置低*/
}
SCK_SET;
SCK_CLR;
dat = dat >> 1;
}
}
/********************************************************************/
/*单字节读出一字节数据*/
unsigned char Read_Ds1302_Byte(void)
{
unsigned char i, dat=0;
for (i=0;i<8;i++)
{
dat = dat >> 1;
if (SDA_R) //等价于if(SDA_R==1) #define SDA_R SDA /*电平读取*/
{
dat |= 0x80;
}
else
{
dat &= 0x7F;
}
SCK_SET;
SCK_CLR;
}
return dat;
}
/********************************************************************/
/*向DS1302 单字节写入一字节数据*/
void Ds1302_Single_Byte_Write(unsigned char addr, unsigned char dat)
{
RST_CLR; /*RST脚置低,实现DS1302的初始化*/
SCK_CLR; /*SCK脚置低,实现DS1302的初始化*/
RST_SET; /*启动DS1302总线,RST=1电平置高 */
addr = addr & 0xFE;
Write_Ds1302_Byte(addr); /*写入目标地址:addr,保证是写操作,写之前将最低位置零*/
Write_Ds1302_Byte((dat/10<<4)|(dat%10)); /*写入数据:dat*/
RST_CLR; /*停止DS1302总线*/
}
/********************************************************************/
/*从DS1302单字节读出一字节数据*/
unsigned char Ds1302_Single_Byte_Read(unsigned char addr)
{
unsigned char temp;
unsigned char dat1,dat2;
RST_CLR; /*RST脚置低,实现DS1302的初始化*/
SCK_CLR; /*SCK脚置低,实现DS1302的初始化*/
RST_SET; /*启动DS1302总线,RST=1电平置高 */
addr = addr | 0x01;
Write_Ds1302_Byte(addr); /*写入目标地址:addr,保证是读操作,写之前将最低位置高*/
temp=Read_Ds1302_Byte(); /*从DS1302中读出一个字节的数据*/
RST_CLR; /*停止DS1302总线*/
dat1=temp/16;
dat2=temp%16;
temp=temp=dat1*10+dat2;
// RST_CLR; /*读取完一个字节必须停止DS1302总线,否则出错*/
// SDA_CLR;
SD=0; //(即 使IO口P2^3=0)
return temp;
}
void Ds1302_Init(void)
{
unsigned char i,add;
add=0x80;
Ds1302_Single_Byte_Write(0x8e,0x00);
for(i=0;i<7;i++)
{
Ds1302_Single_Byte_Write(add,time[i]);
add+=2;
}
Ds1302_Single_Byte_Write(0x8e,0x80);
}
void Ds1302_TimeGet(void)
{
unsigned char i,add;
add=0x81;
Ds1302_Single_Byte_Write(0x8e,0x00);
for(i=0;i<7;i++)
{
time[i]=Ds1302_Single_Byte_Read(add);
add+=2;
}
Ds1302_Single_Byte_Write(0x8e,0x80);
}
#ifndef __DS1302_H__
#define __DS1302_H__
#include
#include
/********************************************************************/
sbit SCK=P1^7;
sbit SD=P2^3;
sbit RST=P1^3;
/********************************************************************/
/*复位脚*/
#define RST_CLR RST=0 /*电平置低*/
#define RST_SET RST=1 /*电平置高*/
/*双向数据*/
#define SDA_CLR SD=0 /*电平置低*/
#define SDA_SET SD=1 /*电平置高*/
#define SDA_R SD /*电平读取*/
/*时钟信号*/
#define SCK_CLR SCK=0 /*时钟信号*/
#define SCK_SET SCK=1 /*电平置高*/
/********************************************************************/
#define ds1302_sec_addr 0x80 //秒数据地址
#define ds1302_min_addr 0x82 //分数据地址
#define ds1302_hr_addr 0x84 //时数据地址
#define ds1302_date_addr 0x86 //日数据地址
#define ds1302_month_addr 0x88 //月数据地址
#define ds1302_day_addr 0x8A //星期数据地址
#define ds1302_year_addr 0x8C //年数据地址
#define ds1302_control_addr 0x8Ee //写保护命令字单元地址
#define ds1302_charger_addr 0x90 //涓电流充电命令字地址
#define ds1302_clkburst_addr 0xBE //日历、时钟突发模式命令字地址
/********************************************************************/
/********************************************************************/
/*单字节写入一字节数据*/
extern void Write_Ds1302_Byte(unsigned char dat);
/********************************************************************/
/*单字节读出一字节数据*/
extern unsigned char Read_Ds1302_Byte(void);
/********************************************************************/
/********************************************************************/
/*向DS1302单字节写入一字节数据*/
extern void Ds1302_Single_Byte_Write(unsigned char addr, unsigned char dat);
/********************************************************************/
/*从DS1302单字节读出一字节数据*/
extern unsigned char Ds1302_Single_Byte_Read(unsigned char addr);
extern unsigned char time[];
extern void Ds1302_Init(void);
extern void Ds1302_TimeGet(void);
#endif
/********************************************************************/
// END FILE
/********************************************************************/