先出手写的代码,代码分析还需要一段时间,不难,大家认真写。
#include <STC15F2K60S2.H>
#include "Seg.h"
#include "LED.h"
#include "Key.h"
#include "DS1302.h"
#include "DS18B20.h"
idata unsigned char DS18B20_Flag = 0; //DS18B20采集标志位,为1开始采集
idata unsigned char DS1302_Slow_Down; //DS1302实时时钟读取延时
idata unsigned char Seg_Slow_Down; //数码管延时变量
idata unsigned char Key_Slow_Down; //按键延时变量
idata unsigned char Seg_Buf[8]={10,10,10,10,10,10,10,10}; //数码管显示内容
idata unsigned char Seg_Scan; //数码管扫描
idata unsigned char LED_Buf[8]={0,0,0,0,0,0,0,0}; //LED亮灭数据
idata unsigned char Key_Val,Key_Down,Key_Up,Key_Old; //按键参数
unsigned char Time[3]={23,59,50}; //存储时间
idata unsigned char Temper; //温度
unsigned char Seg_Show_Mode; //数码管显示模式
idata unsigned char Gather_Time[4] = {1,5,30,60}; //设置采集时间数组
idata unsigned char Gather_Time_Index; //设置采集时间指针,用于变化采集时间
idata unsigned char Real_Gather_Time; //采集时间,将设置值传给Real_Gather_Time
idata unsigned int Time_1000ms; //计时1s,用于设计时钟界面1s闪烁
idata unsigned char Time_1000_Flag;
idata unsigned char Temper_Gather[10]; //采集温度数据
idata unsigned char Temper_Gather_Index; //温度数组指针
idata unsigned int Time_1000_Gather; //用于采集界面计时
idata unsigned char Count; //1s变化一次,相当与秒计时器
idata unsigned char LED_Disable_Flag; //按下按键6可以开始展示温度,同时熄灭LED,LED_Disable_Flag == 1时表示熄灭
idata unsigned int Time_1000_LED; //单独设计LED周期闪烁,防止4T判断时周期错误
idata unsigned char Time_1000_LED_Flag;
void System_Init() //系统初始化
{
unsigned char temp;
//关闭所有LED
P0 = 0xff;
temp = P2 & 0x1f;
temp = temp | 0x80;
P2 = temp;
temp = P2 & 0x1f;
P2 = temp;
//关闭外设
P0 = 0x00;
temp = P2 & 0x1f;
temp = temp | 0xa0;
P2 = temp;
temp = P2 & 0x1f;
P2 = temp;
}
//定时器一初始化,自己加上EA = 1;ET1 = 1;
void Timer1_Init(void) //1毫秒@12.000MHz
{
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x18; //设置定时初始值
TH1 = 0xFC; //设置定时初始值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
EA = 1; //打开总中断
ET1 = 1; //打开定时器一中断允许位
}
void Key_Proc() //按键处理函数
{
if(Key_Slow_Down <20) return; //按键减速
Key_Slow_Down = 0;
Key_Val = Key_Read(); //读取键码值
Key_Down = Key_Val & (Key_Old ^ Key_Val); //判断按下
Key_Up = ~Key_Val & (Key_Old ^ Key_Val); //判断松开
Key_Old = Key_Val; //判断长按
switch(Key_Down)
{
case 4: //切换采集间距按键
if(Seg_Show_Mode == 0)
{
LED_Disable_Flag = 0; //复位LED_Disable_Flag
if(++Gather_Time_Index == 4) //选择采集时间
Gather_Time_Index = 0;
}
break;
case 5: //确定采集时间,开始采集
if(Seg_Show_Mode == 0)
{
Real_Gather_Time = Gather_Time[Gather_Time_Index]; //确定采集时间
Gather_Time_Index = 0;
Seg_Show_Mode = 1; //开始采集
}
break;
case 6: //开始展示数据
if(Seg_Show_Mode == 2)
{
LED_Disable_Flag = 1;
if(++Temper_Gather_Index == 10)
Temper_Gather_Index = 0;
}
break;
case 7: //重新确认采集时间,重新开始采集
if(Seg_Show_Mode == 2)
{
Seg_Show_Mode = 0;
Temper_Gather_Index = 0;
Time_1000_Gather = 0;
Count = 0;
}
break;
}
}
void Seg_Proc() //数码管处理函数
{
if(Seg_Slow_Down <100) return; //减速
Seg_Slow_Down = 0;
switch(Seg_Show_Mode)
{
case 0: //采集时间界面
Seg_Buf[0] = Seg_Buf[1] = Seg_Buf[2] = Seg_Buf[3] = Seg_Buf[4] = 10; //熄灭
Seg_Buf[5] = 11; //-
Seg_Buf[6] = Gather_Time[Gather_Time_Index]/10%10;
Seg_Buf[7] = Gather_Time[Gather_Time_Index]%10;
break;
case 1: //时间显示界面(界面二)
Seg_Buf[0] = Time[0]/10%10;
Seg_Buf[1] = Time[0]%10;
Seg_Buf[2] = Time_1000_Flag ? 11:10; //闪烁
Seg_Buf[3] = Time[1]/10%10;
Seg_Buf[4] = Time[1]%10;
Seg_Buf[5] = Time_1000_Flag ? 11:10; //闪烁
Seg_Buf[6] = Time[2]/10%10;
Seg_Buf[7] = Time[2]%10;
break;
case 2: //数据显示界面(界面三)
Seg_Buf[0] = 11; //-
Seg_Buf[1] = Temper_Gather_Index/10%10; //索引值
Seg_Buf[2] = Temper_Gather_Index%10;
Seg_Buf[3] = Seg_Buf[4] = 10;
Seg_Buf[5] = 11; //-
Seg_Buf[6] = Temper_Gather[Temper_Gather_Index]/10%10; //采集数据
Seg_Buf[7] = Temper_Gather[Temper_Gather_Index]%10;
break;
}
}
void LED_Proc() //LED处理函数
{
LED_Buf[0] = (Seg_Show_Mode == 2) & (LED_Disable_Flag == 0) & (Time_1000_LED_Flag) ;
//当处于界面二时采集数据完成,自动跳转界面三(显示界面),此时按下S6(LED_Disable_Flag == 1直接熄灭)
//Time_1000_LED_Flag闪烁控制
//LED亮的条件,处于界面三,未按下S6,Time_1000_LED_Flag条件为真
}
void DS1302_Proc() // DS1302处理函数
{
if(DS1302_Slow_Down <160) return; //减速
DS1302_Slow_Down = 0;
DS1302_Read(); //获取时间
}
void DS18B20_Proc()
{
if(DS18B20_Flag == 0) return; //未到单次采集时间,不采集
DS18B20_Flag = 0; //DS18B20_Flag == 1开始采集一次,复位标志位
Temper_Gather[Temper_Gather_Index] = (unsigned char)Temperature_Read(); //开始采集
Temper_Gather_Index++;
if(Temper_Gather_Index == 10) //采集完成,自动跳转界面三显示
{
Seg_Show_Mode = 2;
Temper_Gather_Index = 0;
Time_1000_Gather = 0;
Count = 0;
}
}
void main()
{
System_Init();
Timer1_Init();
DS1302_Write();
while((unsigned char)Temperature_Read() == 85);
while(1)
{
Key_Proc();
Seg_Proc();
LED_Proc();
DS1302_Proc();
DS18B20_Proc();
}
}
//定时器一中断打开---中断标志位3
void Timer1_Routine() interrupt 3
{
Seg_Slow_Down++;
Key_Slow_Down++;
DS1302_Slow_Down++;
if(Seg_Show_Mode == 2 && (LED_Disable_Flag == 0)) //处于界面三且未按下S6,开始闪烁
{
if(++Time_1000_LED == 1000)
{
Time_1000_LED = 0;
Time_1000_LED_Flag ^=1;
}
}
else //不满足则清空计时
{
Time_1000_LED = 0;
}
if(++Time_1000ms == 1000) //设计时间显示界面闪烁
{
Time_1000ms = 0;
Time_1000_Flag ^=1;
}
if(Seg_Show_Mode == 1) //处于时间显示界面,开始采集数据
{
if(++Time_1000_Gather == 1000) //计时
{
Count++; //秒计时器
Time_1000_Gather = 0;
if(Count == Real_Gather_Time) //当秒计时器达到采集时间间隔
{
Count = 0;
DS18B20_Flag = 1; //开始温度采集
}
}
}
if(++Seg_Scan == 8) Seg_Scan = 0;
if(Seg_Buf[Seg_Scan] > 20) //判断带小数点的数据
Seg_Disp(Seg_Scan,Seg_Buf[Seg_Scan]-',',1);
else
Seg_Disp(Seg_Scan,Seg_Buf[Seg_Scan],0);
LED_Disp(LED_Buf); //LED扫描
}