难点在于:
1.长按显示分秒,松开恢复时分
2.定义一个变量同步继电器状态
代码如下
unsigned char Time_Sub_Monde = 0; //0-显示时分,1-显示分秒
/* 在时间显示界面下,S17长按显示分、秒,短按显示时、分 */
if(Seg_Disp_Mode == 1) //在时间显示界面下有效
{
if(Key_Down == 17) //产生下降沿
Key_Flag = 1; //拉高标志位,系统开始计时
//在500毫秒以内,短按处理
if(Key_Time_600ms < 500 && Key_Up == 17)
{
Time_Sub_Monde = 0; //切换子状态
Key_Time_600ms = Key_Flag = 0; //复位
}
//在500毫秒以外,长按处理
else
{
if(Key_Old == 17) //仍按住
Time_Sub_Monde = 1; //显示分秒
if(Key_Up == 17) //识别到松开S17
Key_Time_600ms = Key_Flag = Time_Sub_Monde = 0; //复位
}
}
/* 时间显示界面 */
case 1:
if(Time_Sub_Monde == 0) //显示时分
{
Seg_Buf[0] = 11; //U
Seg_Buf[1] = Seg_Disp_Mode + 1; //界面编号1
Seg_Buf[3] = ucRtc[0] / 16 % 16; //时的十位
Seg_Buf[4] = ucRtc[0] % 16; //时的个位
Seg_Buf[5] = 12; //-
Seg_Buf[6] = ucRtc[1] / 16 % 16; //分的十位
Seg_Buf[7] = ucRtc[1] % 16; //分的个位
Seg_Point[6] = 0; //第7位小数点不使能
}
else //显示分秒
{
Seg_Buf[0] = 11; //U
Seg_Buf[1] = Seg_Disp_Mode + 1; //界面编号1
Seg_Buf[3] = ucRtc[1] / 16 % 16; //分的十位
Seg_Buf[4] = ucRtc[1] % 16; //分的个位
Seg_Buf[5] = 12; //-
Seg_Buf[6] = ucRtc[2] / 16 % 16; //秒的十位
Seg_Buf[7] = ucRtc[2] % 16; //秒的个位
Seg_Point[6] = 0; //第7位小数点不使能
}
break;
/* 继电器 */
void Beep_Disp(unsigned char enable)
{
static unsigned char temp = 0x00;
static unsigned char temp_Old = 0xff;
if(enable)
temp |= 0x40;
else
temp &= ~0x40;
g_beep_status = enable;
if(temp != temp_Old)
{
P0 = temp;
P2 = P2 & 0x1f | 0xa0; //打开锁存器
P2 = P2 & 0x1f; //关闭锁存器
temp_Old = temp;
}
}
/* L3 */
if(g_beep_status == 0)
ucLed_enable[2] = Star_Flag ? 0 : 1;
else if(g_beep_status == 1)
ucLed_enable[2] = 0;
本代码已通过4t测试,唯一bug在于继电器开启和关闭有一定问题,目前正在调试,其余部分无问题,可参考
main.c
/* 头文件声明区域 */
#include <STC15F2K60S2.H>
#include <Init.h>
#include <Led.h>
#include <Key.h>
#include <Seg.h>
#include "ds1302.h"
#include "onewire.h"
/* 变量声明区域 */
unsigned char Key_Val,Key_Old,Key_Down,Key_Up; //按键专用变量
unsigned char Key_Slow_Down_10ms; //按键减速专用变量
unsigned int Seg_Slow_Down_500ms; //数码管减速专用变量
unsigned char Seg_Pose = 0; //数码管扫描专用变量
unsigned char Seg_Buf[8] = {10,10,10,10,10,10,10,10}; //数码管显示数据专用存放数组
unsigned char Seg_Point[8] = {0,0,0,0,0,0,0,0}; //数码管小数点专用存放数组
unsigned char ucLed_enable[8] = {0,0,0,0,0,0,0,0}; //Led使能专用数组
unsigned char ucRtc[3] = {0x23,0x59,0x55}; //时钟数据存放数组
float Temperature; //实时温度专用变量
unsigned char Seg_Disp_Mode = 0; //数码管显示模式专用变量 0--温度显示界面 1--时间显示界面 2--参数设置界面
unsigned char Temperature_parameters = 23; //温度参数专用变量
bit Work_Mode = 0; //工作模式专用变量 0--温度控制 1--时间控制
bit Key_Flag = 0; //系统计时标志位
bit Star_Flag = 0; //闪烁标志位
unsigned char Timer_100ms = 0; //100毫秒
unsigned int Key_Time_600ms = 0; //系统计时变量
unsigned char Time_Sub_Monde = 0; //0-显示时分,1-显示分秒
unsigned char g_beep_status = 0;
/* 按键处理函数 */
void Key_Proc()
{
//按键减速专用程序
if(Key_Slow_Down_10ms) return;
Key_Slow_Down_10ms = 1;
//读取键码值
Key_Val = Key_Read();
Key_Down = Key_Val & (Key_Old ^ Key_Val);
Key_Up = ~Key_Val & (Key_Old ^ Key_Val);
Key_Old = Key_Val;
/* 在时间显示界面下,S17长按显示分、秒,短按显示时、分 */
if(Seg_Disp_Mode == 1) //在时间显示界面下有效
{
if(Key_Down == 17) //产生下降沿
Key_Flag = 1; //拉高标志位,系统开始计时
//在500毫秒以内,短按处理
if(Key_Time_600ms < 500 && Key_Up == 17)
{
Time_Sub_Monde = 0; //切换子状态
Key_Time_600ms = Key_Flag = 0; //复位
}
//在500毫秒以外,长按处理
else
{
if(Key_Old == 17) //仍按住
Time_Sub_Monde = 1; //显示分秒
if(Key_Up == 17) //识别到松开S17
Key_Time_600ms = Key_Flag = Time_Sub_Monde = 0; //复位
}
}
switch(Key_Down)
{
/* 切换按键 */
case 12:
if(++Seg_Disp_Mode == 3)
Seg_Disp_Mode = 0;
break;
/* 模式按键 */
case 13:
Work_Mode ^= 1;
break;
/* 加按键 */
case 16:
if(Seg_Disp_Mode == 2) //仅在参数设置界面下有效
{
if(++Temperature_parameters == 100) //上限值为99℃
Temperature_parameters = 99;
}
break;
/* 减按键 */
case 17:
if(Seg_Disp_Mode == 2) //在参数设置界面下有效
{
if(--Temperature_parameters == 9) //下限值为10℃
Temperature_parameters = 10;
}
break;
}
}
/* 数码管显示函数 */
void Seg_Proc()
{
unsigned char i = 3; //For循环专用变量
//数码管减速专用程序
if(Seg_Slow_Down_500ms) return;
Seg_Slow_Down_500ms = 1;
//实时读取数据
Temperature = rd_temperature(); //实时读取当前温度值
Read_Rtc(ucRtc); //实时读取当前时钟值
//数码管显示区域
switch(Seg_Disp_Mode)
{
/* 温度显示界面 */
case 0:
Seg_Buf[0] = 11; //U
Seg_Buf[1] = Seg_Disp_Mode + 1; //界面编号1
Seg_Buf[3] = Seg_Buf[4] = 10; //重置使熄灭
Seg_Buf[5] = (unsigned char)Temperature / 10 % 10; //温度十位
Seg_Buf[6] = (unsigned char)Temperature % 10; //温度个位
Seg_Buf[7] = (unsigned int)(Temperature * 10) % 10; //温度第一位小数
Seg_Point[6] = 1; //第7位小数点使能
break;
/* 时间显示界面 */
case 1:
if(Time_Sub_Monde == 0) //显示时分
{
Seg_Buf[0] = 11; //U
Seg_Buf[1] = Seg_Disp_Mode + 1; //界面编号1
Seg_Buf[3] = ucRtc[0] / 16 % 16; //时的十位
Seg_Buf[4] = ucRtc[0] % 16; //时的个位
Seg_Buf[5] = 12; //-
Seg_Buf[6] = ucRtc[1] / 16 % 16; //分的十位
Seg_Buf[7] = ucRtc[1] % 16; //分的个位
Seg_Point[6] = 0; //第7位小数点不使能
}
else //显示分秒
{
Seg_Buf[0] = 11; //U
Seg_Buf[1] = Seg_Disp_Mode + 1; //界面编号1
Seg_Buf[3] = ucRtc[1] / 16 % 16; //分的十位
Seg_Buf[4] = ucRtc[1] % 16; //分的个位
Seg_Buf[5] = 12; //-
Seg_Buf[6] = ucRtc[2] / 16 % 16; //秒的十位
Seg_Buf[7] = ucRtc[2] % 16; //秒的个位
Seg_Point[6] = 0; //第7位小数点不使能
}
break;
/* 参数设置界面 */
case 2:
Seg_Buf[0] = 11; //U
Seg_Buf[1] = Seg_Disp_Mode + 1; //界面编号1
for(i=3;i<6;i++)
Seg_Buf[i] = 10; //数码管4--6全部熄灭
Seg_Buf[6] = Temperature_parameters / 10 % 10; //温度参数的十位
Seg_Buf[7] = Temperature_parameters % 10; //温度参数的个位
break;
}
}
/* 其他显示函数 */
void Led_Proc()
{
/* 关闭蜂鸣器 */
Relay_Disp(1);
/* 继电器控制功能区域 */
if(Seg_Disp_Mode == 0)
{
if(Temperature > Temperature_parameters)
Beep_Disp(0); //打开继电器
else
Beep_Disp(1); //关闭继电器
}
else if(Seg_Disp_Mode == 1)
{
if(ucRtc[1] / 16 % 16 == 0 && ucRtc[1] % 16 == 0 && ucRtc[2] / 16 % 16 == 0 && ucRtc[2] % 16 == 0)
Beep_Disp(0); //打开继电器
if(ucRtc[2] % 16 == 5)
Beep_Disp(1); //关闭继电器
}
/* Led指示灯控制功能区域 */
/* L1 */
if(ucRtc[1] / 16 % 16 == 0 && ucRtc[1] % 16 == 0 && ucRtc[2] / 16 % 16 == 0 && ucRtc[2] % 16 == 0)
ucLed_enable[0] = 1; //整点时,L1点亮
if(ucRtc[2] % 16 == 5) //5秒后
ucLed_enable[0] = 0;
/* L2 */
ucLed_enable[1] = !Work_Mode;
/* L3 */
if(g_beep_status == 0)
ucLed_enable[2] = Star_Flag ? 0 : 1;
else if(g_beep_status == 1)
ucLed_enable[2] = 0;
}
/* 继电器 */
void Beep_Disp(unsigned char enable)
{
static unsigned char temp = 0x00;
static unsigned char temp_Old = 0xff;
if(enable)
temp |= 0x40;
else
temp &= ~0x40;
g_beep_status = enable;
if(temp != temp_Old)
{
P0 = temp;
P2 = P2 & 0x1f | 0xa0; //打开锁存器
P2 = P2 & 0x1f; //关闭锁存器
temp_Old = temp;
}
}
/* 定时器0初始化函数 */
void Timer0_Init(void) //1毫秒@12.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x18; //设置定时初始值
TH0 = 0xFC; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1;
EA = 1;
}
/* 定时器0中断服务函数 */
void Timer0_Server() interrupt 1
{
if(++Key_Slow_Down_10ms == 10) Key_Slow_Down_10ms = 0; //按键减速专用程序
if(++Seg_Slow_Down_500ms == 500) Seg_Slow_Down_500ms = 0; //数码管减速专用程序
if(++Seg_Pose == 8) Seg_Pose = 0;
Seg_Disp(Seg_Pose,Seg_Buf[Seg_Pose],Seg_Point[Seg_Pose]); //数码管显示程序
Led_Disp(Seg_Pose,ucLed_enable[Seg_Pose]); //Led显示程序
if(Key_Flag == 1)
{
if(++Key_Time_600ms == 600)
Key_Time_600ms = 600;
}
if(++Timer_100ms == 100)
{
Timer_100ms = 0;
Star_Flag ^= 1;
}
}
/* 750ms延时函数 */
void Delay750ms(void) //@12.000MHz
{
unsigned char data i, j, k;
i = 35;
j = 51;
k = 182;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
/* Main */
void main()
{
Set_Rtc(ucRtc);
rd_temperature();
Delay750ms();
System_Init();
Timer0_Init();
while(1)
{
Key_Proc();
Seg_Proc();
Led_Proc();
}
}