注意:
数据处理方面
:由于ds1302芯片存储的数据是BCD码,所以我们要进行BCD码与十进制之间的转换,例如0x16 的BCD码为16,十进制为1 * 16 + 6 = 32。
源文件修改方面
:官方给onewire.h,ds1302.h中使用的时C51的头件"reg52.h",我们需修改为对应的15系列头文件"STC15F2K60S2.h",这样才可以使用一些特殊位寄存器。
底层代码
:需修改驱动代码onewire.c中单总线延时函数,官方给我们是STC89C52RC系列,15系列的单片机速度比51快8~12倍,需要修改对应的延时函数。修改如下
void Delay_OneWire(unsigned int t)
{
char i;
while(t–)
for (i = 0; i < 12; i++);
}
#include "STC15F2K60S2.h"
#include "onewire.h"
#include "ds1302.h"
#define uchar unsigned char
#define uint unsigned int
sbit L1 = P0^0;
sbit L2 = P0^1;
sbit L3 = P0^2;
uchar jm = 0;//界面初始化温度界面
code uchar tab[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff, 0xc1, 0xbf};
//U - 11 12
uchar init_time[3] = {0x40, 0x59, 0x23};//初始化时间秒 分 时
uchar time[3] = { 0 };//秒 分 时
bit mod_flag;//0为温度控制模式
bit rel_flag;//继电器是否闭合标志,为0未闭合
bit flag_5s;
bit led10_flag;//初始化0为led10熄灭
bit L1_flag;//初始化0为L1熄灭
bit L3_flag;//初始化0为L3熄灭
float curr_temp;
uchar para_temp = 23;
void sys_init();
void key_handle();
float rd_temperature();
void rd_time();
void rel_handle();
void led();
void dsp_smg_bit(uchar pos, val);
void display();//显示功能,分四个大块
void dsp_temp();
void dsp_time();
void dsp_para();
void dsp_min_sec();//长按S17显示分秒
void delay_k(uchar t);//延时t * 10us
void Delay1ms(); //[email protected],延时1ms用于给足数码管足够显示时间
void main()
{
sys_init();
while(1)
{
curr_temp = rd_temperature();
rd_time();//实时读取时间
key_handle();
display();
rel_handle();//继电器处理
led();
}
}
void led()
{
if (time[0] == 0x00 && time[1] == 0x00)
{
L1_flag = 1;
}
if (L1_flag)
{
P2 = (P2 & 0x1f) | 0x80;
L1 = 0;
}
else
{
P2 = (P2 & 0x1f) | 0x80;
L1 = 1;
}
if (!mod_flag)
{
P2 = (P2 & 0x1f) | 0x80;
L2 = 0;
}
else
{
P2 = (P2 & 0x1f) | 0x80;
L2 = 1;
}
if (led10_flag)
{
//继电器吸附,间隔0.1sL3闪烁
if (L3_flag)
{
P2 = (P2 & 0x1f) | 0x80;
L3 = 0;
}
else
L3 = 1;
}
P0 |= 0xf8;//将L4~L8熄灭
P2 &= 0x1f;
}
void rel_handle()
{
uint t = (uchar)(curr_temp * 10);
if (!mod_flag)
{
if (t > para_temp * 10)
{
led10_flag = 1;
P2 = (P2 & 0x1f) | 0xa0;
P0=0X10;
}
else
{
led10_flag = 0;
P2 = (P2 & 0x1f) | 0xa0;
P0 = 0xaf;
}
}
else if (mod_flag)
{
if (time[0] == 0x00 && time[1] == 0x00)
{
rel_flag = 1;//整点,继电器吸附标志
}
if (rel_flag)
{
P2 = (P2 & 0x1f) | 0xa0;
P0 = 0x10;
led10_flag = 1;
}
else
{
P2 = (P2 & 0x1f) | 0xa0;
P0 = 0xaf;
led10_flag = 0;
}
}
//P0 |= 0x00;
//P2 &= 0x1f;
}
void rd_time()
{
uchar t;
t = Read_Ds1302_Byte(0x81);//秒
time[0] = t / 16 * 10 + t % 16 ;
t = Read_Ds1302_Byte(0x83);//分
time[1] = t / 16 * 10 + t % 16 ;
t = Read_Ds1302_Byte(0x85);//时
time[2] = t / 16 * 10 + t % 16 ;
}
void display()
{
if (0 == jm)
dsp_temp();
else if (1 == jm)
dsp_time();
else if (2 == jm)
dsp_para();
}
void dsp_min_sec()
{
dsp_smg_bit(1, 11);//U
dsp_smg_bit(2, 2);//
dsp_smg_bit(4, time[1] / 10);
dsp_smg_bit(5, time[1] % 10);
dsp_smg_bit(6, 12);//-
dsp_smg_bit(7, time[0] / 10);
dsp_smg_bit(8, time[0] % 10);
}
void dsp_para()
{
dsp_smg_bit(1, 11);//U
dsp_smg_bit(2, 3);//
dsp_smg_bit(7, para_temp / 10 % 10);
dsp_smg_bit(8, para_temp % 10);
}
void dsp_time()
{
dsp_smg_bit(1, 11);//U
dsp_smg_bit(2, 2);//
dsp_smg_bit(4, time[2] / 10);
dsp_smg_bit(5, time[2] % 10);
dsp_smg_bit(6, 12);//-
dsp_smg_bit(7, time[1] / 10);
dsp_smg_bit(8, time[1] % 10);
}
void dsp_temp()
{
uint x = (uint)(curr_temp * 10);//当前温度扩大10倍
dsp_smg_bit(1, 11);//U
dsp_smg_bit(2, 1);//
dsp_smg_bit(6, x / 100 % 10);
//第7位数码管显示小数点
P2 = (P2 & 0x1f) | 0xc0;
P0 = 1 << (7 - 1);
P2 = (P2 & 0x1f) | 0xe0;
P0 = tab[x / 10 % 10] & 0x7f;
Delay1ms();
P0 = 0xff;
P2 &= 0x1f;
dsp_smg_bit(8, x % 10);
}
void dsp_smg_bit(uchar pos, val)
{
P2 = (P2 & 0x1f) | 0xc0;
P0 = 1 << (pos - 1);
P2 = (P2 & 0x1f) | 0xe0;
P0 = tab[val];
Delay1ms();
P0 = 0xff;
P2 &= 0x1f;
}
void Delay1ms() //@12.000MHz
{
unsigned char i, j;
i = 12;
j = 169;
do
{
while (--j);
} while (--i);
}
void delay_k(uchar t)
{
while(t--)
display();
}
void key_handle()
{
P35 = P34 = P32 = 1;
P33 = 0;//第四行拉低
if(!P35)//s12
{
delay_k(10);
if(!P35)
{
if (++jm >= 3)
jm = 0;
while(!P35)
{
display();
}
}
}
if(!P34)//s16
{
delay_k(10);
if(!P34)
{
if (2 == jm)
{
if (++para_temp > 99)
para_temp = 99;
}
while(!P34)
{
display();
}
}
}
P35 = P34 = P33 = 1;
P32 = 0;//第三行拉低
if(!P35)//s13
{
delay_k(10);
if(!P35)
{
mod_flag = !mod_flag;
while(!P35)
{
display();
}
}
}
if(!P34)//s17
{
delay_k(10);
if(!P34)
{
if (2 == jm)
{
if (--para_temp < 10)//参数操作 + 参数检查
para_temp = 10;
}
if (1 == jm)
{
while(!P34)//s17的长按键操作
{
rd_time();
dsp_min_sec();
}
}
while(!P34)
{
display();
}
}
}
}
float rd_temperature()
{
uchar l, h;
uint t;
float temp;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
l = Read_DS18B20();
h = Read_DS18B20();
t = (h & 0x0f);
t <<= 8;
t |= l;
temp = t * 0.0625;
return temp;
}
void timer0() interrupt 1
{
static uint i1, i2, i3;
if (rel_flag)//继电器闭合5秒断开标志
{
if (++i1 == 5000)
{
i1 = 0;
rel_flag = 0;
}
}
if (L1_flag)
{
if (++i2 == 5000)
{
i2 = 0;
L1_flag = 0;
}
}
if (++i3 == 100)//0.1s切换一次L3的状态,使其闪烁
{
L3_flag = !L3_flag;
i3 = 0;
}
}
void sys_init()
{
//关蜂鸣器,继电器
P2 = (P2 & 0x1f) | 0xa0;
P0 = 0xaf;
P2 = (P2 & 0x1f) | 0x80;
P0 = 0xff;
P2 &= 0x1f;
Write_Ds1302_Byte(0x8e,0x00);//关闭写保护
Write_Ds1302_Byte(0x80, init_time[0]);//秒
Write_Ds1302_Byte(0x82, init_time[1]);//分
Write_Ds1302_Byte(0x84, init_time[2]);//时
Write_Ds1302_Byte(0x8e,0x80);//开启写保护
//1ms
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1;
ET1 = 0;//禁止定时器中断1中断
EA = 1;
}
#ifndef __ONEWIRE_H
#define __ONEWIRE_H
#include
bit init_ds18b20(void);
unsigned char Read_DS18B20(void);
void Write_DS18B20(unsigned char dat);
void Delay_OneWire(unsigned int t);
#endif
/*
程序说明: 单总线驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台(外部晶振12MHz) STC89C52RC单片机
日 期: 2011-8-9
*/
#include "onewire.h"
sbit DQ = P1^4; //单总线接口
//单总线延时函数
void Delay_OneWire(unsigned int t) //STC89C52RC
{
char i;
while(t--)
for (i = 0; i < 12; i++);
}
//通过单总线向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;
}
#ifndef __DS1302_H
#define __DS1302_H
#include "STC15F2K60S2.h"
#include
sbit SCK = P1^7;
sbit SDA = P2^3;
sbit RST = P1^3;
void Write_Ds1302(unsigned char temp);
void Write_Ds1302_Byte( unsigned char address,unsigned char dat );
unsigned char Read_Ds1302_Byte( unsigned char address );
#endif
#include "ds1302.h"
//写字节
void Write_Ds1302(unsigned char temp)
{
unsigned char i;
for (i=0;i<8;i++)
{
SCK = 0;
SDA = temp&0x01;
temp>>=1;
SCK=1;
}
}
//向DS1302寄存器写入数据
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;
}
//从DS1302寄存器读出数据
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);
}