这个题目还是很简单的,一般在DS1302和DS18B20的驱动写好情况下,两个小时就可以写好。
就用到了DS1302显示实时时间,四个独立按键功能很简单,注意模式切换就可以了,数码管显示也是模式切换就行了。
下载链接:https://download.csdn.net/download/xiaomo_haa/11004437
main.c
#include
#include "sys.h"
bit flag_start = 0;
bit flag_50ms = 0;
bit flag_temper = 0;
bit flag_led = 0;
u8 mode = 1, Temper_time = 1;
u8 temperno = 0;
int Realtemper[11];
u8 Realtime[] = {0x19, 0x03, 0x07, 0x23, 0x59, 0x50, 0x04};
void main(void)
{
u8 index = 0, t = 1, leddat = 0xff;
int temp = 0;
AllInit();
Start18B20();
EA = 0;
Timer0Init();
InitDS1302(&Realtime);
EA = 1;
while(1)
{
KeyPress();
if(flag_50ms)
{
flag_50ms = 0;
GetRealTime(&Realtime); //读取1302时间
if(flag_led)
{
leddat = 0xfe | t;
t = ~t;
}
else
leddat = 0xff;
}
if(flag_temper == 1)
{
flag_temper = 0;
Get18B20Temp(&temp);
temp >>= 4;
Realtemper[index] = temp;
index ++;
Start18B20();
if(index >= 10)
{
mode = 3; //自动切换到温度显示界面
flag_start = 0; //停止采集温度
flag_led = 1; //显示温度
}
}
if(flag_start == 0)
index = 0;
LEDLight(leddat);
}
}
sys.c
#include "sys.h"
void AllInit(void)
{
P2 = (P2 & 0x1f) | 0x80;
P0 = 0xff;
P2 = (P2 & 0x1f) | 0xc0;
P0 = 0x00;
P2 = (P2 & 0x1f) | 0xa0;
P0 = 0x00;
P2 = P2 & 0x1f;
}
void Timer0Init(void) //2毫秒@11.0592MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x9A; //设置定时初值
TH0 = 0xA9; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1;
}
void Timer0(void) interrupt 1
{
static u8 T0count1 = 0;
static u16 T0count2 = 0;
u16 time_temp = 0;
T0count1 ++;
T0count2 ++;
time_temp = Temper_time * 500;
if(T0count1 >= 25)
{
T0count1 = 0;
flag_50ms = 1;
}
if(flag_start)
{
if(T0count2 >= time_temp)
{
T0count2 = 0;
flag_temper = 1;
}
}
else
{
T0count2 = 0;
flag_temper = 0;
}
KeyScan();
TubeShow();
TubeScan();
}
sys.h
#ifndef _SYS_H_
#define _SYS_H_
typedef unsigned char u8;
typedef unsigned int u16;
typedef unsigned long u32;
#include
#include
#include "ds18b20.h"
#include "ds1302.h"
extern bit flag_start;
extern bit flag_50ms;
extern bit flag_temper;
extern bit flag_led;
extern u8 mode, Temper_time;
extern u8 temperno;
extern int Realtemper[11];
extern u8 Realtime[];
//function
void AllInit(void);
void Timer0Init(void);
void TubeScan(void);
void TubeShow(void);
void LEDLight(unsigned char dat);
unsigned char BCDToNum(unsigned char bcd);
void KeyScan(void);
void KeyAction(unsigned char key);
void KeyPress(void);
//pin
sbit S7 = P3^0;
sbit S6 = P3^1;
sbit S5 = P3^2;
sbit S4 = P3^3;
#endif
display.c
#include "sys.h"
unsigned char code table[]={0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8,
0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e,
0xff, 0xbf};
u8 TubeBuff[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
u8 smg1, smg2, smg3, smg4, smg5, smg6, smg7, smg8;
void TubeScan(void)
{
static u8 index = 0;
P2 = (P2 & 0x1f) | 0xe0;
P0 = 0xff;
P2 = (P2 & 0x1f) | 0xc0;
P0 = (0x01 << index);
P2 = (P2 & 0x1f) | 0xe0;
P0 = TubeBuff[index];
P2 = P2 & 0x1f;
index ++;
index &= 0x07;
}
void TubeShow(void)
{
if(mode == 1) //设置时间间隔界面
{
smg1 = smg2 = smg3 = smg4 = smg5 = 16;
smg6 = 17;
smg7 = Temper_time / 10;
smg8 = Temper_time % 10;
}
else if(mode == 2) //采集温度时显示温度
{
smg1 = BCDToNum(Realtime[3]) / 10;
smg2 = BCDToNum(Realtime[3]) % 10;
smg4 = BCDToNum(Realtime[4]) / 10;
smg5 = BCDToNum(Realtime[4]) % 10;
smg7 = BCDToNum(Realtime[5]) / 10;
smg8 = BCDToNum(Realtime[5]) % 10;
if(smg8 % 2 == 0)
smg3 = smg6 = 16;
else
smg3 = smg6 = 17;
}
else if(mode == 3)
{
smg1 = smg6 = 17;
smg4 = smg5 = 16;
smg2 = temperno / 10;
smg3 = temperno % 10;
smg7 = Realtemper[temperno] / 10;
smg8 = Realtemper[temperno] % 10;
}
TubeBuff[0] = table[smg1];
TubeBuff[1] = table[smg2];
TubeBuff[2] = table[smg3];
TubeBuff[3] = table[smg4];
TubeBuff[4] = table[smg5];
TubeBuff[5] = table[smg6];
TubeBuff[6] = table[smg7];
TubeBuff[7] = table[smg8];
}
void LEDLight(unsigned char dat)
{
P0 = 0xff;
P2 = (P2 & 0x1f) | 0x80;
P0 = dat;
P2 = P2 & 0x1f;
}
unsigned char BCDToNum(unsigned char bcd)
{
unsigned char a, b;
a = (bcd >> 4);
b = bcd & 0x0f;
return (a * 10 + b);
}
key.c
#include "sys.h"
u8 KeySta[] = {1, 1, 1, 1};
u8 KeyBackup[] = {1, 1, 1, 1};
u8 KeyBuff[] = {0xff, 0xff, 0xff, 0xff};
void KeyScan(void)
{
u8 i;
KeyBuff[0] = (KeyBuff[0] << 1) | S7;
KeyBuff[1] = (KeyBuff[1] << 1) | S6;
KeyBuff[2] = (KeyBuff[2] << 1) | S5;
KeyBuff[3] = (KeyBuff[3] << 1) | S4;
for(i = 0; i < 4; i ++)
{
if(KeyBuff[i] == 0xff) //Key release
KeySta[i] = 1;
else if(KeyBuff[i] == 0x00) //Key press
KeySta[i] = 0;
else
{}
}
}
void KeyAction(unsigned char key)
{
static u8 index = 1;
if((key == 3) && (mode == 1)) //S4
{
index ++;
switch(index)
{
case 1: Temper_time = 1; break;
case 2: Temper_time = 5; break;
case 3: Temper_time = 30; break;
case 4: Temper_time = 60; break;
default: index = 1; Temper_time = 1; break;
}
}
else if((key == 2) && (mode == 1)) //S5
{
flag_start = 1;
mode = 2;
}
else if((key == 1) && (mode == 3)) //S6
{
if(flag_led)
flag_led = 0;
temperno ++;
if(temperno >= 10)
temperno = 0;
}
else if((key == 0) && (mode == 3)) //S7
{
mode = 1;
temperno = 0;
}
}
void KeyPress(void)
{
u8 i;
for(i = 0; i < 4; i ++)
{
if(KeySta[i] != KeyBackup[i])
{
if(KeySta[i] == 0) //action when key press
KeyAction(i);
KeyBackup[i] = KeySta[i];
}
}
}
ds18b20.c
#include "sys.h"
sbit DS18B20_IO = P1^4;
void Delayus(unsigned int us)
{
do{
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}while(--us);
}
bit Get18B20Ack(void)
{
bit ack;
DS18B20_IO = 0; //产生500us的复位脉冲
Delayus(500);
EA = 0; //禁止总中断
DS18B20_IO = 1; //延时60us
Delayus(60);
EA = 1; //重新使能总中断
ack = DS18B20_IO; //读取存在脉冲
while(!DS18B20_IO); //等待存在脉冲结束
return ack;
}
void DS18B20Write(unsigned char dat)
{
unsigned char mask;
for(mask = 0x01; mask != 0; mask <<= 1) //低位在先,依次移出8个bit
{
EA = 0;
DS18B20_IO = 0; //产生2us低电平脉冲
Delayus(2);
if(dat & mask) //输出该bit值
DS18B20_IO = 1;
else
DS18B20_IO = 0;
EA = 1;
Delayus(60); //延时60us
DS18B20_IO = 1; //拉高通信引脚
}
}
unsigned char DS18B20Read(void)
{
unsigned char mask, dat = 0;
for(mask = 0x01; mask != 0; mask <<= 1) //低位在先,依次采集8个bit
{
EA = 0;
DS18B20_IO = 0; //产生2us低电平脉冲
Delayus(2);
DS18B20_IO = 1; //结束低电平脉冲,等待18B20输出数据
Delayus(2); //延时2us
EA = 1;
if(DS18B20_IO) //读取通信引脚上的值
dat |= mask;
Delayus(60); //再延时60us
}
return dat;
}
bit Start18B20()
{
bit ack;
static bit flag = 1;
ack = Get18B20Ack(); //执行总线复位,并获取18B20应答
if(ack == 0) //如18B20正确应答,则启动一次转换
{
DS18B20Write(0xCC); //跳过ROM操作
if(flag)
{
flag = 0;
DS18B20Write(0x4e); //写暂存器指令4E
DS18B20Write(0x4b); //写高速缓存器TH高温限值75度
DS18B20Write(0x00); //写高速缓存器TL低温限值0度
DS18B20Write(0x1f); //写配置寄存器4
//0x1f : 0.5000°C 转换时间93.75ms
//0x3f : 0.2000°C 转换时间187.5ms
//0x5f : 0.1250°C 转换时间375ms
//0x7f : 0.0625°C 转换时间750ms
}
ack = Get18B20Ack(); //执行总线复位,并获取18B20应答
if(ack == 0) //如18B20正确应答,则启动一次转换
{
DS18B20Write(0xCC); //跳过ROM操作
DS18B20Write(0x44); //启动一次温度转换
}
}
return ~ack; //ack == 0 表示操作成功,所以返回值对其取反
}
bit Get18B20Temp(int *temp)
{
bit ack;
unsigned char LSB, MSB; //16bit温度值的低字节和高字节
ack = Get18B20Ack(); //执行总线复位,并获取18B20应答
if(ack == 0) //如18B20正确应答,则读取温度值
{
DS18B20Write(0xCC); //跳过ROM操作
DS18B20Write(0xBE); //发送读命令
LSB = DS18B20Read(); //读温度值的低字节
MSB = DS18B20Read(); //读温度值的高字节
*temp = ( MSB << 8) + LSB; //合成16bit的整数
}
return ~ack; //ack == 0 表示操作应答,所以返回值为1其取反值
}
ds18b20.h
#ifndef __DS18B20_H
#define __DS18B20_H
//单总线延时函数
void Delayus(unsigned int us);
bit Get18B20Ack(void);
void DS18B20Write(unsigned char dat);
unsigned char DS18B20Read(void);
bit Start18B20();
bit Get18B20Temp(int *temp);
#endif
ds1302.c
#include "sys.h"
sbit DS1302_IO = P2^3;
sbit DS1302_CK = P1^7;
sbit DS1302_CE = P1^3;
void DS1302ByteWrite(unsigned char dat)
{
unsigned char mask;
DS1302_IO = 1; //拉低IO总线
for(mask = 0x01; mask != 0; mask <<= 1) //低位在前,逐位移出
{
if((dat&mask) != 0) //首先输出该位数据
DS1302_IO = 1;
else
DS1302_IO = 0;
DS1302_CK = 1; //拉高时钟线
DS1302_CK = 0; //拉低时钟线,完成一个位的操作
}
DS1302_IO = 1; //写完之后确保释放IO总线
}
unsigned char DS1302ByteRead(void)
{
unsigned char mask, dat = 0;
for(mask = 0x01; mask != 0; mask <<= 1) //低位在前,逐位读取
{
if(DS1302_IO) //首先读取此时的IO引脚,并设置dat中的对应位
dat |= mask;
DS1302_CK = 1; //拉高时钟
DS1302_CK = 0; //再拉低时钟,完成一个位的操作
}
return dat; //返回读到的字节数据
}
void DS1302SingleWrite(unsigned char reg, unsigned char dat)
{
DS1302_CE = 1; //使能片选信号
DS1302ByteWrite((reg << 1) | 0x80); //发送写寄存器指令
DS1302ByteWrite(dat); //写入字节数据
DS1302_CE = 0; //除能片选信号
}
unsigned char DS1302SingleRead(unsigned char reg)
{
unsigned char dat;
DS1302_CE = 1; //使能片选信号
DS1302ByteWrite((reg << 1) | 0x81); //发送读寄存器指令
dat = DS1302ByteRead(); //读取字节数据
DS1302_CE = 0; //除能片选信号
DS1302_IO = 0; //单字节读必须加的!
return dat;
}
void DS1302BurstWrite(unsigned char *dat)
{
unsigned char i;
DS1302_CE = 1;
DS1302ByteWrite(0xBE); //发送突发写寄存器指令
for(i = 0; i < 7; i ++) //连续写入8字节数据
DS1302ByteWrite(*dat++);
DS1302_CE = 0;
}
void DS1302BurstRead (unsigned char *dat)
{
unsigned char i;
DS1302_CE = 1;
DS1302ByteWrite(0xBF); //发送突发读寄存器指令
for(i = 0; i < 7; i++) //连续读取8个字节
dat[i] = DS1302ByteRead();
DS1302_CE = 0;
DS1302_IO = 0; //突发读必须加
}
void GetRealTime(unsigned char *time)
{
unsigned char buf[8];
DS1302BurstRead(buf);
time[0] = buf[6];
time[1] = buf[4];
time[2] = buf[3];
time[3] = buf[2];
time[4] = buf[1];
time[5] = buf[0];
time[6] = buf[5];
}
void SetRealTime(unsigned char *time)
{
unsigned char buf[8];
buf[7] = 0;
buf[6] = time[0];
buf[4] = time[1];
buf[3] = time[2];
buf[2] = time[3];
buf[1] = time[4];
buf[0] = time[5];
buf[5] = time[6];
DS1302BurstWrite(buf);
}
void InitDS1302(unsigned char *time)
{
unsigned char dat;
signed char i = 7;
unsigned char timeinit[8];
while(i >= 0)
{
timeinit[i] = time[i];
i --;
}
DS1302_CE = 0; //初始化DS1302通信引脚
DS1302_CK = 0;
dat = DS1302SingleRead(0); //读取秒寄存器
DS1302SingleWrite(7, 0x00); //撤销写保护以允许写入数据
SetRealTime(&timeinit); //设置DS1302时间
// DS1302SingleWrite(7, 0x80); //写保护以禁止写入数据
}
ds1302.h
#ifndef __DS1302_H
#define __DS1302_H
void DS1302ByteWrite(unsigned char dat);
unsigned char DS1302ByteRead(void);
void DS1302SingleWrite(unsigned char reg, unsigned char dat);
unsigned char DS1302SingleRead(unsigned char reg);
void DS1302BurstWrite(unsigned char *dat);
void DS1302BurstRead (unsigned char *dat);
void GetRealTime(unsigned char *time);
void SetRealTime(unsigned char *time);
void InitDS1302(unsigned char *time);
#endif