一.碎碎念
在整点操作的时候,我是采用时分都是0的条件判断,但这种操作会在一秒内重复触发,为解决这种情况,可以多添加一种标志位,在时分非0情况下置零,如果时分为0且标志位为0,说明之前没有触发过。
void LED_Control()
{
if(sec==0&&min==0&&LED_Flag==0)
{
LED_Flag=1;
count_times=0;
LED_Select&=0xfe;
SelectHC573(4,LED_Select);
}
if(jdq_Mode==1)
{
LED_Select&=0xfd;
SelectHC573(4,LED_Select);
}
if(jdq_Mode!=1)
{
LED_Select|=0x02;
SelectHC573(4,LED_Select);
}
}
二.题目要求
三.代码实现
main.c
#include <STC15F2K60S2.H>
#include "onewire.h"
#include "ds1302.h"
sbit C1=P3^5; //矩阵按键
sbit C2=P3^4;
sbit R1=P3^2;
sbit R2=P3^3;
code unsigned char SMG_Nodot[] =
{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
code unsigned char SMG_Dot[] =
{0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
unsigned int SMG_Mode=1; //数码管模式选择
unsigned int t_smg; //数码管显示用的温度数据
float t; //实际温度数据
unsigned char t_param=23; //温度参数
unsigned char hour,min,sec; //时间
unsigned char jdq_Mode=1; //继电器触发模式
unsigned char jdq_Select=0x00; //继电器选择(可以直接位操作,但我还是习惯这样)
unsigned char LED_Select=0xff; //LED选择
unsigned char count_times=0; //LED亮时间
bit LED_Flag=0; //整点触发
bit Flash_Flag=0; //闪烁标志位
unsigned char Flash_times; //闪烁时间记录
bit jdq_Flag=0;
void jdq_control();
void LED_Control();
void Delay_SMG(unsigned int t)
{
while(t--);
}
void SelectHC573(unsigned char channel,unsigned char dat)
{
P0=dat;
switch(channel)
{
case 4:
P2=(P2&0x1f)|0x80;
break;
case 5:
P2=(P2&0x1f)|0xa0;
break;
case 6:
P2=(P2&0x1f)|0xc0;
break;
case 7:
P2=(P2&0x1f)|0xe0;
break;
case 0:
P2=(P2&0x1f)|0x00;
break;
}
P2=(P2&0x1f)|0x00;
}
void Display_SMG(unsigned char pos,unsigned char dat)
{
SelectHC573(6,0x01<<(pos-1));
SelectHC573(7,dat);
Delay_SMG(500);
SelectHC573(6,0x01<<(pos-1));
SelectHC573(7,0xff);
}
void Display_Dynamic()
{
Display_SMG(1,0xc1);
Display_SMG(2,SMG_Nodot[SMG_Mode]);
if(SMG_Mode==1)
{
Display_SMG(6,SMG_Nodot[t_smg/100]);
Display_SMG(7,SMG_Dot[t_smg%100/10]);
Display_SMG(8,SMG_Nodot[t_smg%10]);
}
if(SMG_Mode==2)
{
Display_SMG(4,SMG_Nodot[hour/16]);
Display_SMG(5,SMG_Nodot[hour%16]);
Display_SMG(6,0xbf);
Display_SMG(7,SMG_Nodot[min/16]);
Display_SMG(8,SMG_Nodot[min%16]);
}
if(SMG_Mode==3)
{
Display_SMG(7,SMG_Nodot[t_param/10]);
Display_SMG(8,SMG_Nodot[t_param%10]);
}
}
void Timer0Init(void) //定时器0初始化.12T,50ms
{
AUXR &= 0x7F;
TMOD &= 0xF0;
TL0 = 0xB0;
TH0 = 0x3C;
TF0 = 0;
TR0 = 1;
ET0=1;
EA=1;
}
void Timer0_Service() interrupt 1
{
if(LED_Flag==1) //LED亮5s后关闭
{
count_times++;
if(count_times==100)
{
LED_Flag=0;
LED_Select|=0x01;
SelectHC573(4,LED_Select);
count_times=0;
}
}
if(jdq_Flag==1) //LED闪烁
{
Flash_times++;
if(Flash_times==2)
{
Flash_Flag=~Flash_Flag;
if(Flash_Flag==1)
{
LED_Select&=0xfb;
SelectHC573(4,LED_Select);
}
if(Flash_Flag==0)
{
LED_Select|=0x04;
SelectHC573(4,LED_Select);
}
Flash_times=0;
}
}
}
void DS18B20_Read_temp() //读取温度
{
unsigned char MSB,LSB;
unsigned int t_temp;
init_ds18b20();
Display_Dynamic();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
Display_Dynamic();
init_ds18b20();
Display_Dynamic();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
LSB=Read_DS18B20();
MSB=Read_DS18B20();
Display_Dynamic();
t_temp=MSB<<8|LSB;
t=t_temp*0.0625;
t_smg=t*10;
}
void DS1302_Config() //DS1302时钟初始化
{
Write_Ds1302_Byte(0x8e,0x00);
Write_Ds1302_Byte(0x80,0x50);
Write_Ds1302_Byte(0x82,0x59);
Write_Ds1302_Byte(0x84,0x23);
Write_Ds1302_Byte(0x8e,0x80);
}
void DS1302_Read() //DS1302时间读取
{
sec=Read_Ds1302_Byte(0x81);
min=Read_Ds1302_Byte(0x83);
hour=Read_Ds1302_Byte(0x85);
}
void Scan_Key()
{
C1=0;C2=1;
R1=R2=1;
if(R1==0)
{
Delay_SMG(500);
if(R1==0)
{
switch(jdq_Mode)
{
case 1:
jdq_Mode=2;
break;
case 2:
jdq_Mode=1;
break;
}
}
while(R1==0)
{
Display_Dynamic();
DS18B20_Read_temp();
DS1302_Read();
}
}
if(R2==0)
{
Delay_SMG(500);
if(R2==0)
{
switch(SMG_Mode)
{
case 1:
SMG_Mode=2;
break;
case 2:
SMG_Mode=3;
break;
case 3:
SMG_Mode=1;
break;
}
}
while(R2==0)
{
Display_Dynamic();
DS18B20_Read_temp();
DS1302_Read();
}
}
C1=1;C2=0;
R1=R2=1;
if(R1==0)
{
Delay_SMG(500);
if(R1==0)
{
if(SMG_Mode==3)
{
if(t_param>0)
{
t_param--;
}
}
if(SMG_Mode==2)
{
while(R1==0)
{
DS1302_Read();
Display_SMG(1,0xc1);
Display_SMG(2,SMG_Nodot[SMG_Mode]);
Display_SMG(4,SMG_Nodot[min/16]);
Display_SMG(5,SMG_Nodot[min%16]);
Display_SMG(6,0xbf);
Display_SMG(7,SMG_Nodot[sec/16]);
Display_SMG(8,SMG_Nodot[sec%16]);
jdq_control();
LED_Control();
}
}
}
while(R1==0)
{
Display_Dynamic();
DS18B20_Read_temp();
DS1302_Read();
}
}
if(R2==0)
{
Delay_SMG(500);
if(R2==0)
{
if(SMG_Mode==3)
{
if(t_param<99)
{
t_param++;
}
}
}
while(R2==0)
{
Display_Dynamic();
DS18B20_Read_temp();
DS1302_Read();
}
}
}
void jdq_control()
{
if(jdq_Mode==1)
{
if(t>t_param)
{
jdq_Select|=0x10;
SelectHC573(5,jdq_Select);
jdq_Flag=1;
}
if(t<t_param)
{
jdq_Select=0x00;
SelectHC573(5,jdq_Select);
jdq_Flag=0;
LED_Select|=0x04;
SelectHC573(4,LED_Select);
}
}
if(jdq_Mode==2)
{
if(sec==0&&min==0)
{
jdq_Select|=0x10;
SelectHC573(5,jdq_Select);
jdq_Flag=1;
}
if(sec!=0||min!=0)
{
jdq_Select=0x00;
SelectHC573(5,jdq_Select);
jdq_Flag=0;
LED_Select|=0x04;
SelectHC573(4,LED_Select);
}
}
}
void LED_Control()
{
if(sec==0&&min==0&&LED_Flag==0)
{
LED_Flag=1;
count_times=0;
LED_Select&=0xfe;
SelectHC573(4,LED_Select);
}
if(jdq_Mode==1)
{
LED_Select&=0xfd;
SelectHC573(4,LED_Select);
}
if(jdq_Mode!=1)
{
LED_Select|=0x02;
SelectHC573(4,LED_Select);
}
}
void Sys_init()
{
SelectHC573(4,0xff);
SelectHC573(5,0x00);
DS1302_Config();
Timer0Init();
}
void main()
{
Sys_init();
while(1)
{
Display_Dynamic();
DS18B20_Read_temp();
DS1302_Read();
jdq_control();
LED_Control();
Scan_Key();
}
}
onewire.c
/* # 单总线代码片段说明
1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include <STC15F2K60S2.H>
sbit DQ=P1^4;
//
void Delay_OneWire(unsigned int t)
{
unsigned char i;
while(t--){
for(i=0;i<12;i++);
}
}
//
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);
}
//
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;
}
//
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;
}
onewire.h
#ifndef __ONEWIRE_H__
#define __ONEWIRE_H__
void Write_DS18B20(unsigned char dat);
unsigned char Read_DS18B20(void);
bit init_ds18b20(void);
#endif
ds1302.c
/* # DS1302代码片段说明
1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include <STC15F2K60S2.H>
#include "intrins.h"
sbit SCK=P1^7;
sbit SDA=P2^3;
sbit RST=P1^3;
//
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);
}
ds1302.h
#ifndef __DS1302_H__
#define __DS1302_H__
void Write_Ds1302_Byte( unsigned char address,unsigned char dat );
unsigned char Read_Ds1302_Byte ( unsigned char address );
#endif