一、题目及要求:
二、代码实现
主函数main.c文件:
/*
作者:废物小陈
时间:2021-1-26
功能:温度记录器。
*/
//----------------------头文件------------------------//
#include <STC15F2K60S2.H>
#include "port.h"
#include "ds1302.h"
#include "key.h"
#include "onewire.h"
//----------------------全局变量------------------------//
unsigned char code smg_duan[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,
0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x00,0x40,0x76};
unsigned char code smg_wei[] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
unsigned char menu[][8] = {{20, 20, 20, 20, 20, 21, 0, 1}, {2, 3, 21, 5, 9, 21, 5, 0},{21, 0, 0, 20, 20, 21, 0, 0}};//不同的模式对应不同的菜单
unsigned char oper_mode, disp_index;//不同的模式oper_mode对应不同的检索下标disp_index
unsigned int timer2_cnt;//定时器2计数值
unsigned char Trg, Com;//按键检测键值,Trg只有20ms的存在时间,适合于按键短按,Com适合于按键长按
bit keyFlag, tick_200ms, tick_1s, led_state;//keyFlag按键按下标志位,tick_200ms计时20ms标志位,tick_1s计时1s标志位
unsigned char collect_tmp_mode, tmp_mode[4] = {1, 5, 30, 60};//收集温度的时长模式的确定
unsigned char hour, min, sec;//当前时间显示
unsigned char collect_tmp[10] = {0}, collect_cnt;//用于保存当前测量的温度值及测量次数
//----------------------定时器2初始化------------------------//
void Timer2Init(void) //1000微秒@11.0592MHz
{
AUXR |= 0x04; //定时器时钟1T模式
T2L = 0xCD; //设置定时初值
T2H = 0xD4; //设置定时初值
AUXR |= 0x10; //定时器2开始计时
IE2 |= 0x04;
}
//----------------------定时器2中断服务函数------------------------//
void t2int() interrupt 12 //中断入口
{
static unsigned char i;
unsigned char key_val;
//数码管1ms刷新一次
LED_Com(0x00);
LED_Bit(smg_wei[i]);
LED_Com(smg_duan[menu[disp_index][i]]);
if(++i == 8)
i = 0;
//按键20ms检测一次
if(timer2_cnt % 20 == 0)
{
keyFlag = 1;
key_val = KeyScan();
Trg = key_val & (key_val ^ Com);
Com = key_val;
}
if(timer2_cnt % 200 == 0)
tick_200ms = 1;
if(++timer2_cnt % 1000 == 0)
{
tick_1s = 1;
timer2_cnt = 0;
}
}
void main(void)
{
unsigned char time_1s;
unsigned char tmp[2] = {20, 21};
bit tmp_cnt;
//各设备上电初始化
Relay(0);
Buzzer(0);
LED(0x00);
Ds1302_SetTime(23, 59, 50);//设置初始时间
Ds18b20_Gettemperature();//先初始化温度,防止一开始的温度跳变
Timer2Init();
EA = 1;
while(1)
{
if(keyFlag)//检测按键按下
{
keyFlag = 0;
switch(Trg)
{
case 4://S4按下
{
if(oper_mode == 0)
if(++collect_tmp_mode == 4)
collect_tmp_mode = 0;
break;
}
case 5:
{
if(oper_mode == 0)//从设置温度采集模式转换成时间显示模式
{
oper_mode = 1;
disp_index = 1;
}
break;
}
case 6:
{
if(oper_mode == 2)//更换显示采集温度值
{
LED(0);
if(++collect_cnt == 10)
collect_cnt = 0;
}
break;
}
case 7://清空标志位,准备进行下一步采集
{
if(oper_mode == 2)
{
oper_mode = 0;
disp_index = 0;
collect_tmp_mode = 0;
collect_cnt = 0;
}
break;
}
}
}
if(tick_200ms)//不同模式对应显示不同
{
tick_200ms = 0;
if(oper_mode == 0)//temperature
{
menu[0][6] = tmp_mode[collect_tmp_mode] / 10;
menu[0][7] = tmp_mode[collect_tmp_mode] % 10;
}
else if(oper_mode == 1)//clock
{
hour = Read_Ds1302_Byte(0x85);
min = Read_Ds1302_Byte(0x83);
sec = Read_Ds1302_Byte(0x81);
menu[1][0] = hour >> 4;
menu[1][1] = hour & 0x0f;
menu[1][3] = min >> 4;
menu[1][4] = min & 0x0f;
menu[1][6] = sec >> 4;
menu[1][7] = sec & 0x0f;
}
else if(oper_mode == 2)
{
menu[2][1] = collect_cnt / 10;
menu[2][2] = collect_cnt % 10;
menu[2][6] = collect_tmp[collect_cnt] / 10;
menu[2][7] = collect_tmp[collect_cnt] % 10;
}
}
if(tick_1s)//1s任务
{
tick_1s = 0;
if(oper_mode == 1 && collect_cnt < 10)//处于显示时间界面下进行温度采集
{
menu[1][2] = tmp[tmp_cnt];//实现间隔1s闪烁
tmp_cnt = ~tmp_cnt;
menu[1][5] = menu[1][2];
if(++time_1s == tmp_mode[collect_tmp_mode])
{
time_1s = 0;
collect_tmp[collect_cnt++] = Ds18b20_Gettemperature();//温度采集模式下1s实现采集一次温度
}
}
else if(collect_cnt >= 10 && oper_mode == 1)
{
tmp_cnt = 1;
collect_cnt = 0;
oper_mode = 2;
disp_index = 2;
}
else if(oper_mode == 2 && collect_cnt == 0)//当前S6没按下,L1灯闪烁
{
LED(tmp_cnt);
tmp_cnt = ~tmp_cnt;
}
}
}
}
端口程序文件port.c
#include "port.h"
#include <STC15F2K60S2.H>
#include <intrins.h>
unsigned char bdata control;
sbit relay = control^4;
sbit buzzer = control^6;
void Relay(unsigned char ch)
{
relay = ch;
P0 = control;
P2 = 0xa0;
_nop_();
P2 = 0x00;
}
void Buzzer(unsigned char ch)
{
buzzer = ch;
P0 = control;
P2 = 0xa0;
_nop_();
P2 = 0x00;
}
void LED(unsigned char ch)
{
P0 = ~ch;
P2 = 0x80;
_nop_();
P2 = 0x00;
}
void LED_Bit(unsigned char ch)
{
P0 = ch;
P2 = 0xc0;
_nop_();
P2 = 0x00;
}
void LED_Com(unsigned char ch)
{
P0 = ~ch;
P2 = 0xe0;
_nop_();
P2 = 0x00;
}
独立按键扫描程序key.c文件:
#include <STC15F2K60S2.H>
#include "key.h"
#include "intrins.h"
void Delay100us() //@11.0592MHz
{
unsigned char i, j;
_nop_();
_nop_();
i = 2;
j = 15;
do
{
while (--j);
} while (--i);
}
unsigned char KeyScan(void)
{
if(P30 == 0)
{
Delay100us();
if(P30 == 0)
return 7;
}
if(P31 == 0)
{
Delay100us();
if(P31 == 0)
return 6;
}
if(P32 == 0)
{
Delay100us();
if(P32 == 0)
return 5;
}
if(P33 == 0)
{
Delay100us();
if(P33 == 0)
return 4;
}
return 0;
}
时钟ds1302.c文件:
/*
³ÌÐò˵Ã÷: DS1302Çý¶¯³ÌÐò
Èí¼þ»·¾³: Keil uVision 4.10
Ó²¼þ»·¾³: CT107µ¥Æ¬»ú×ÛºÏʵѵƽ̨ 8051£¬12MHz
ÈÕ ÆÚ: 2011-8-9
*/
#include <reg52.h>
#include <intrins.h>
#include "ds1302.h"
sbit SCK=P1^7;
sbit SDA=P2^3;
sbit RST = P1^3; // DS1302¸´Î»
void Write_Ds1302(unsigned char temp)
{
unsigned char i;
for (i=0;i<8;i++)
{
SCK=0;
SDA=temp&0x01;
temp>>=1;
SCK=1;
}
}
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;
}
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);
}
void Ds1302_SetTime(unsigned char hour, unsigned char min, unsigned char sec)
{
unsigned char hh, hl, mh, ml, sh, sl;
hh = (hour / 10) << 4;
hl = hour % 10;
mh = (min / 10) << 4;
ml = min % 10;
sh = (sec / 10) << 4;
sl = sec % 10;
Write_Ds1302_Byte(0x8e, 0x00);
Write_Ds1302_Byte(0x80, sh | sl);
Write_Ds1302_Byte(0x82, mh | ml);
Write_Ds1302_Byte(0x84, hh | hl);
Write_Ds1302_Byte(0x8e, 0x80);
}
温度检测onewire.c文件:
/*
ԌѲ˵ķ: եПȽ֯ԌѲ
ɭݾ۷: Keil uVision 4.10
Ӳݾ۷: CT107եƬܺ؛ۏʵѵƽ̨(ҿާֱ12MHz) STC89C52RCեƬܺ
ɕ ǚ: 2011-8-9
*/
#include "reg52.h"
#include "onewire.h"
sbit DQ = P1^4; //եПޓࠚ
//եПғʱگ˽
void Delay_OneWire(unsigned int t) //STC89C52RC
{
t *= 7;
while(t--);
}
//ͨڽեПв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;
}
float Ds18b20_Gettemperature(void)
{
unsigned char th, tl;
unsigned int tmp;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
Delay_OneWire(400);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
tl = Read_DS18B20();
th = Read_DS18B20();
tmp = (th << 8) | tl;
return tmp * 0.0625f;
}
以上代码个人亲测有效,有问题欢迎大家提出一起讨论呀!