目录
第五届-模拟智能灌溉
#include <STC15F2K60S2.H>
#include <Init.h>
#include <Led.h>
#include <Key.h>
#include <Seg.h>
#include "ds1302.h"
#include "iic.h"
unsigned char key_val,key_down,key_old,key_up;
unsigned char key_slow_down;
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 seg_pos;
unsigned int seg_slow_down;
unsigned char ucled[8] = {0,0,0,0,0,0,0,0};
unsigned char ucRtc[3] = {0x08,0x30,0x00};
bit seg_disp_mode; //数码管显示模式 0-显示 1-设置
unsigned char humidity; //读取到的湿度
bit work_mode; //工作模式 0-自动状态 1-手动状态
unsigned char humidity_disp=50,humidity_ctrl=50;
bit relay_flag; //继电器标志位
bit beep_flag; //蜂鸣器标志位
void key_proc()
{
if(key_slow_down) return;
key_slow_down = 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;
switch(key_down)
{
case 7: //按键7
work_mode ^= 1;
break;
case 6: // 按键6
if(work_mode == 1) //手动模式
{
beep_flag ^= 1;//切换蜂鸣器工作状态
}
else //自动模式
{
seg_disp_mode ^= 1;//切换数码管显示模式
if(seg_disp_mode == 0)//从阈值参数界面退出
{
humidity_ctrl = humidity_disp;//阈值参数生效
EEPROM_Write(&humidity_ctrl,0,1);//保存阈值参数
}
}
break;
case 5: //按键5
if(work_mode == 1) //手动模式
{
relay_flag = 1;//打开继电器
}
else //自动模式
{
if(seg_disp_mode == 1)//处于阈值参数界面
{
if(++humidity_disp == 100)//阈值+1
humidity_disp = 99;
}
}
break;
case 4: //按键4
if(work_mode == 1) //手动模式
{
relay_flag = 0;//关闭继电器
}
else //自动模式
{
if(seg_disp_mode == 1)
{
if(--humidity_disp == 255)//阈值-1
humidity_disp = 0;
}
}
break;
}
}
void seg_proc()
{
if(seg_slow_down) return;
seg_slow_down = 1;
Read_Rtc(ucRtc);
humidity = Ad_Read(0x03) / 2.56;
if(work_mode ==0) //自动
{
if(humidity < humidity_ctrl)
relay_flag = 1;
else
relay_flag = 0;
}
if(seg_disp_mode == 0)
{
seg_buf[0] = ucRtc[0] / 16;
seg_buf[1] = ucRtc[0] % 16;
seg_buf[2] = 11;
seg_buf[3] = ucRtc[1] / 16;
seg_buf[4] = ucRtc[1] % 16;
seg_buf[6] = humidity /10 % 10;
seg_buf[7] = humidity % 10;
}
else
{
seg_buf[0] = 11;
seg_buf[1] = 11;
seg_buf[2] = seg_buf[3] = seg_buf[4] = seg_buf[5] = 10;
seg_buf[6] = humidity_disp / 10 % 10;
seg_buf[7] = humidity_disp % 10;
}
}
void led_proc()
{
ucled[0] = !work_mode;
ucled[1] = work_mode;
}
void Timer0Init(void) //1毫秒@12.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1;
EA = 1;
}
void Timer0Sever() interrupt 1
{
if(++key_slow_down == 10) key_slow_down = 0;
if(++seg_slow_down == 500) seg_slow_down = 0;
if(++seg_pos == 8) seg_pos = 0;
led_disp(seg_pos,ucled[seg_pos]);
seg_disp(seg_pos,seg_buf[seg_pos],seg_point[seg_pos]);
relay(relay_flag);
beep(beep_flag && relay_flag);
}
void main()
{
Set_Rtc(ucRtc);
humidity = Ad_Read(0x03) / 2.56;
EEPROM_Read(&humidity_ctrl,0,1); //读取
humidity_disp = humidity_ctrl;
system_init();
Timer0Init();
while(1)
{
key_proc();
seg_proc();
led_proc();
}
}
1.继电器和蜂鸣器的底层temp变量为全局静态变量,可使继电器和蜂鸣器的使用互不影响。
//在定时器0中断服务函数增加如下语句,实现继电器和蜂鸣器的定时扫描
relay(relay_flag);
beep(beep_flag);
2.上电读取一次EEPROM的数据。退出参数界面进入显示界面(seg_disp_mode == 1)将显示参数传递给设置参数,同时向EEPROM写入一次数据。
3.自动模式蜂鸣器不参与,手动模式不考虑S6的开关作用外 其实蜂鸣器与继电器同步运行同状态。 即beep(relay_flag);。考虑到S6的开关作用的话 其实就是继电器打开的大前提下,蜂鸣器根据其他条件进行开和关,设定一个beep_flag变量,S6进行01切换, beep(beep_flag && relay_flag);。
第六届-温度记录器
#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_up,key_down,key_old,key_slow;
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 int seg_slow;
unsigned char ucled[8] = {0,0,0,0,0,0,0,0};
unsigned char seg_pos;
unsigned char seg_mode_disp; //数码管显示模式 0-参数设置界面,1-时钟显示/温度采集界面,2-温度采集显示界面
unsigned char a_time[4] = {1,5,30,60};//采集时间间隔存放数组
unsigned char a_time_index; //采集时间间隔存放数组指针
unsigned char a_time_disp = 1; //采集时间显示变量
unsigned char a_time_ctrl = 1; //采集时间控制变量
unsigned char ucRtc[3] = {0x23,0x59,0x50};
unsigned char temperature_index; //温度数组提示符
unsigned char temperature[10]; //温度数组提示符
unsigned int Timer_1000ms;
unsigned char sec_time;
unsigned int sec_tick;
bit seg_star_flag;
bit led_star_flag;
bit led_enable_flag;
void key_proc()
{
if(key_slow) return;
key_slow = 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;
switch(key_down)
{
case 4://参数切换按键
if(seg_mode_disp == 0)
{
if(++a_time_index == 4) a_time_index = 0;
a_time_disp = a_time[a_time_index];
}
break;
case 5://参数确认按键
if(seg_mode_disp == 0)
{
a_time_ctrl = a_time_disp;
seg_mode_disp = 1;
}
break;
case 6://数据切换按键
if(seg_mode_disp == 2)
{
led_enable_flag = 0;//关闭LED使能
if(++temperature_index == 10)
temperature_index = 0;
}
break;
case 7://进入参数设置界面
if(seg_mode_disp == 2)//当前处于温度显示界面
{
temperature_index = 0;//指针复位
seg_mode_disp = 0;
}
break;
}
}
void seg_proc()
{
unsigned char i;
if(seg_slow) return;
seg_slow = 1;
Read_Rtc(ucRtc);//RTC读出数据
if(sec_time == a_time_ctrl )//满足一次采集的时间
{
sec_time = 0;
temperature[temperature_index] = rd_temperature();//读取温度
if(++temperature_index == 10)//读够了
{
temperature_index = 0;//指针清零
led_enable_flag = 1;//使能LED
seg_mode_disp = 2;//温度采集显示
}
}
switch(seg_mode_disp)
{
case 0://参数设置界面
seg_buf[0] = seg_buf[1] = seg_buf[2] = 10;
// seg_buf[3] = a_time_index;
seg_buf[5] = 11;
seg_buf[6] = a_time_disp / 10 % 10;
seg_buf[7] = a_time_disp % 10;
break;
case 1://时钟显示界面
for(i=0;i<3;i++)
{
seg_buf[3*i] = ucRtc[i] / 16;
seg_buf[3*i+1] = ucRtc[i] % 16;
}
seg_buf[2] = seg_buf[5] = 10 + (unsigned char)seg_star_flag;
break;
case 2://温度采集显示界面
seg_buf[0] = seg_buf[5] = 11;
seg_buf[1] = 0;
seg_buf[2] = temperature_index;
seg_buf[3] = seg_buf[4] = 10;
seg_buf[6] = temperature[temperature_index] / 10 % 10;
seg_buf[7] = temperature[temperature_index] % 10;
break;
}
}
void led_proc()
{
ucled[0] = led_enable_flag & led_star_flag;//在使能状态下闪烁
}
void Timer0Init(void) //1毫秒@12.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1;
EA = 1;
}
void Timer0Server() interrupt 1
{
if(++key_slow == 10) key_slow = 0;
if(++seg_slow == 500) seg_slow = 0;
if(++seg_pos == 8) seg_pos = 0;
seg_disp(seg_pos,seg_buf[seg_pos],seg_point[seg_pos]);
led_disp(seg_pos,ucled[seg_pos]);
if(++Timer_1000ms == 1000)//时钟提示符、LED每1s取反一次
{
Timer_1000ms = 0;
seg_star_flag ^= 1;
led_star_flag ^= 1;
}
if(seg_mode_disp == 1)
{
if(++sec_tick == 1000)
{
sec_tick = 0;
sec_time++;
}
}
}
void Delay750ms() //@12.000MHz
{
unsigned char i, j, k;
i = 35;
j = 51;
k = 182;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void main()
{
Set_Rtc(ucRtc);
rd_temperature();
Delay750ms();
system_init();
Timer0Init();
while(1)
{
key_proc();
seg_proc();
led_proc();
}
}
1.采集间隔四个值可用一个数组存放起来,定义一个数组索引值,采集时间显示值与采集间隔设置值。参数切换界面,将数组值给到显示值;参数确认界面,将显示值给到设置值。
2.定时器0中断服务函数在采集模式下(seg_mode_disp == 1)每1ms sec_tick+1,加到1000(每1s)sec_time+1。在信息处理区域中,每当sec_time == 采集设置值,进行一次采集,sec_time清零。当采集到十次后,令seg_mode_disp==2.进入采集数据显示界面。之后数码管显示采集到的温度数值,每按下一次S6索引值加一,轮询显示。
第七届-模拟风扇系统
#include <STC15F2K60S2.H>
#include <Init.h>
#include <Led.h>
#include <Key.h>
#include <Seg.h>
#include "onewire.h"
unsigned char key_val,key_down,key_up,key_old,key_slow;
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 int seg_slow;
unsigned char ucled[8] = {0,0,0,0,0,0,0,0};
unsigned char seg_pos;
unsigned char seg_mode_disp;//数码管显示模式,0-倒计时,1-室温显示
unsigned char wind_mode; //风的模式, 0-睡眠风,1-自然风,2-常风
unsigned char wind_time[3] = {0,60,120}; //工作时间存放数组
unsigned char wind_time_index; //工作时间存放数组的指针
unsigned char work_time; //实际工作时间
unsigned int Timer_1000ms;
float temperature; //DS18B20
unsigned char pwm_count; //实现PWM定时器1计数值从0到9
unsigned char pwm_level; //
void key_proc()
{
if(key_slow) return;
key_slow = 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;
switch(key_down)
{
case 4://切换工作模式
if(seg_mode_disp == 0)
{
if(++wind_mode == 3)
wind_mode = 0;
}
break;
case 5://定时按键
if(seg_mode_disp == 0)
{
if(++wind_time_index == 3)
wind_time_index = 0;
work_time = wind_time[wind_time_index];//给剩余工作时间赋初值
}
break;
case 6://停止按键
if(seg_mode_disp == 0)
work_time = 0;
break;
case 7://室温按键
seg_mode_disp ^= 1;
break;
}
}
void seg_proc()
{
if(seg_slow) return;
seg_slow = 1;
// switch(wind_mode)
// {
// case 0:
// pwm_level = 2;
// break;
// case 1:
// pwm_level = 3;
// break;
// case 2:
// pwm_level = 7;
// break;
// }
temperature = rd_temperature();
if(seg_mode_disp == 0)//工作模式和剩余工作时间显示
{
seg_buf[0] = seg_buf[2] = 11;
seg_buf[1] = wind_mode+1;
seg_buf[3] = wind_time_index;
seg_buf[4] = 0;
seg_buf[5] = work_time / 100 %10;
seg_buf[6] = work_time / 10 %10;
seg_buf[7] = work_time % 10;
}
else //显示室温
{
seg_buf[0] = seg_buf[2] = 11;
seg_buf[1] = 4;
seg_buf[4] = 10;
seg_buf[5] = (unsigned char)temperature / 10 % 10;
seg_buf[6] = (unsigned char)temperature % 10;
seg_buf[7] = 12;
}
}
void led_proc()
{
unsigned char i;
for(i=0;i<3;i++) //互斥点亮
ucled[i] = (i == wind_mode) * work_time;
}
void Timer0Init(void) //1毫秒@12.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1;
EA = 1;
}
void Timer0Server() interrupt 1
{
if(++key_slow == 10) key_slow = 0;
if(++seg_slow == 500) seg_slow = 0;
if(++seg_pos == 8) seg_pos = 0;
seg_disp(seg_pos,seg_buf[seg_pos],seg_point[seg_pos]);
led_disp(seg_pos,ucled[seg_pos]);
if(work_time != 0)//实现工作时间的倒计时
{
if(++Timer_1000ms == 1000)
{
Timer_1000ms = 0;
work_time--;
}
}
}
void Timer1Init(void) //100微秒@12.000MHz
{
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x9C; //设置定时初值
TH1 = 0xFF; //设置定时初值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1 = 1;
}
void Timer1Server() interrupt 3
{
if(work_time != 0)
{
if(++pwm_count == 10) pwm_count = 0;
switch(wind_mode)
{
case 0:
pwm_level = 2;
break;
case 1:
pwm_level = 3;
break;
case 2:
pwm_level = 7;
break;
}
if(pwm_count >= pwm_level) P34 = 0;
else P34 = 1;
}
}
void Delay750ms() //@12.000MHz
{
unsigned char i, j, k;
i = 35;
j = 51;
k = 182;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void main()
{
system_init();
Timer0Init();
Timer1Init();
// Delay750ms();
// rd_temperature();
while(1)
{
key_proc();
seg_proc();
led_proc();
}
}
1.三种风对应三个模式对应三个不同的pwm_level
2.将三个不同的时间值放到一个数组中,给到工作时间变量,当工作时间变量不为零时,在定时器中断中进行倒计时。
第八届-电子钟
#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_up,key_down,key_slow;
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 int seg_slow;
unsigned char seg_pos;
unsigned char ucled[8] = {0,0,0,0,0,0,0,0};
unsigned char ucRtc[3] = {0x23,0x59,0x55};
unsigned char ucRtc_Set[3];
unsigned char ucRtc_Set_Index;
unsigned char Alarm[3] = {0x00,0x00,0x00};
unsigned char Alarm_Set[3] = {0x00,0x00,0x00};
bit seg_mode_disp; //0-时间显示,1-温度显示
unsigned char set_flag; //0-时钟显示,1-时钟设置,2-闹钟设置
unsigned char temperature;
unsigned int Timer_1000ms;
unsigned char Timer_200ms;
bit seg_star;
bit beep_flag;
bit led_star;
void key_proc()
{
unsigned char i;
if(key_slow) return;
key_slow = 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;
if(set_flag == 0) //处于时钟显示
{
if(key_old == 4) //长按S4
seg_mode_disp = 1; //进入温度显示
else
seg_mode_disp = 0; //进入时间显示
}
switch(key_down)
{
case 7: //时钟设置
if(seg_mode_disp == 0)
{
if(set_flag == 0)//处于时钟显示
{
for(i=0;i<3;i++)
ucRtc_Set[i] = ucRtc[i];
set_flag = 1;
}
else if(set_flag == 1)//处于时钟设置
{
if(++ucRtc_Set_Index == 3)//一轮切换完
{
ucRtc_Set_Index = 0;
Set_Rtc(ucRtc_Set);
set_flag = 0;
}
}
}
break;
case 6: //闹钟设置
if(seg_mode_disp == 0)
{
if(set_flag == 0) //时钟显示切换到闹钟设置
set_flag = 2;
else if(set_flag == 2)
{
if(++ucRtc_Set_Index == 3)
{
ucRtc_Set_Index = 0;
Alarm[i] = Alarm_Set[i];
set_flag = 0;
}
}
}
break;
case 5:
if(seg_mode_disp == 0)
{
if(set_flag == 1) //处于时钟设置
{
ucRtc_Set[ucRtc_Set_Index]++;
if(ucRtc_Set[ucRtc_Set_Index] % 16 == 0x0a)//按十六进制加,转BCD码
ucRtc_Set[ucRtc_Set_Index] += 6;
if(ucRtc_Set[ucRtc_Set_Index] == (ucRtc_Set_Index ? 0x60:0x24))//限幅
ucRtc_Set[ucRtc_Set_Index] = ucRtc_Set_Index ? 0x59:0x23;
}
if(set_flag == 2) //处于闹钟设置
{
Alarm[ucRtc_Set_Index]++;
if(Alarm[ucRtc_Set_Index] % 16 == 0x0a)//按十六进制加,转BCD码
Alarm[ucRtc_Set_Index] += 6;
if(Alarm[ucRtc_Set_Index] == (Alarm ? 0x60:0x24))//限幅
Alarm[ucRtc_Set_Index] = Alarm ? 0x59:0x23;
}
}
break;
case 4:
if(seg_mode_disp == 0)
{
if(set_flag == 1) //处于时钟设置
{
ucRtc_Set[ucRtc_Set_Index]--;
if(ucRtc_Set[ucRtc_Set_Index] % 16 == 0x0f)//按十六进制加,转BCD码
ucRtc_Set[ucRtc_Set_Index] -= 6;
if(ucRtc_Set[ucRtc_Set_Index] == 0xf9)//按十六进制加,转BCD码
ucRtc_Set[ucRtc_Set_Index] = 0;
if(ucRtc_Set[ucRtc_Set_Index] == (ucRtc_Set_Index ? 0x60:0x24))//限幅
ucRtc_Set[ucRtc_Set_Index] = ucRtc_Set_Index ? 0x59:0x23;
}
if(set_flag == 2) //处于闹钟设置
{
Alarm_Set[ucRtc_Set_Index]--;
if(Alarm_Set[ucRtc_Set_Index] % 16 == 0x0f)//按十六进制加,转BCD码
Alarm_Set[ucRtc_Set_Index] -= 6;
if(Alarm_Set[ucRtc_Set_Index] == 0xf9)//按十六进制加,转BCD码
Alarm_Set[ucRtc_Set_Index] = 0;
if(Alarm_Set[ucRtc_Set_Index] == (Alarm_Set ? 0x60:0x24))//限幅
Alarm_Set[ucRtc_Set_Index] = Alarm_Set ? 0x59:0x23;
}
}
break;
}
}
void seg_proc()
{
unsigned char i;
if(seg_slow) return;
seg_slow = 1;
Read_Rtc(ucRtc);
temperature = rd_temperature();
if(seg_mode_disp == 0) //时间显示界面
{
if(set_flag == 0) //时钟显示
{
seg_buf[2] = seg_buf[5] = 11;
for(i=0;i<3;i++)
{
seg_buf[3*i] = ucRtc[i]/16;
seg_buf[3*i+1] = ucRtc[i]%16;
}
}
else if(set_flag == 1) //时钟设置
{
for(i=0;i<3;i++)
{
seg_buf[3*i] = ucRtc_Set[i]/16;
seg_buf[3*i+1] = ucRtc_Set[i]%16;
}
seg_buf[3*ucRtc_Set_Index] = seg_star?10:ucRtc_Set[ucRtc_Set_Index] / 16;
seg_buf[3*ucRtc_Set_Index+1] = seg_star?10:ucRtc_Set[ucRtc_Set_Index] % 16;
}
else //闹钟设置
{
for(i=0;i<3;i++)
{
seg_buf[3*i] = Alarm[i]/16;
seg_buf[3*i+1] = Alarm[i]%16;
}
seg_buf[3*ucRtc_Set_Index] = seg_star?10:Alarm[ucRtc_Set_Index] / 16;
seg_buf[3*ucRtc_Set_Index+1] = seg_star?10:Alarm[ucRtc_Set_Index] % 16;
}
}
else //温度显示界面
{
for(i=0;i<5;i++)
seg_buf[i] = 10;
seg_buf[5] = temperature / 10;
seg_buf[6] = temperature % 10;
seg_buf[7] = 12;
}
}
void led_proc()
{
if((ucRtc[0]==Alarm[0])&&(ucRtc[1]==Alarm[1])&&(ucRtc[2]==Alarm[2]))//时钟等于闹钟
beep_flag = 1;
if((Alarm[2] % 16 + 5) == (ucRtc[2] % 16))//过了五秒
beep_flag = 0;
ucled[0] = led_star && beep_flag;//led闪烁
}
void Timer0Init(void) //1毫秒@12.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1;
EA = 1;
}
void Timer0Server() interrupt 1
{
if(++key_slow == 10) key_slow = 0;
if(++seg_slow == 500) seg_slow = 0;
if(++seg_pos == 8) seg_pos = 0;
seg_disp(seg_pos,seg_buf[seg_pos],seg_point[seg_pos]);
led_disp(seg_pos,ucled[seg_pos]);
if(++Timer_1000ms == 1000)
{
Timer_1000ms = 0;
seg_star ^= 1;
}
if(++Timer_200ms == 200)
{
Timer_200ms = 0;
led_star ^= 1;
}
}
void main()
{
system_init();
Timer0Init();
Set_Rtc(ucRtc);
while(1)
{
key_proc();
seg_proc();
led_proc();
}
}
1.定义时钟RTC数组,RTC设置数组及其索引,闹钟显示数组,闹钟设置数组;显示模式控制变量:seg_mode_disp的值对应“时间界面”和“温度界面”,set_flag的值对应“时钟显示”,“时钟设置”,“闹钟设置”。
2.处于“时钟显示”按下S7将RTC数组值给到RTC设置值后,使set_flag的值处于“时钟设置”,修改索引值自增到三(完成一轮切换)后令set_flag的值回到“时钟显示”,闹钟设置同理。
3.RTC的限幅
ucRtc_Set[ucRtc_Set_Index]++;
if(ucRtc_Set[ucRtc_Set_Index] % 16 == 0x0a)//按十六进制加,转BCD码
ucRtc_Set[ucRtc_Set_Index] += 6;
if(ucRtc_Set[ucRtc_Set_Index] == (ucRtc_Set_Index ? 0x60:0x24))//限幅
ucRtc_Set[ucRtc_Set_Index] = ucRtc_Set_Index ? 0x59:0x23;
ucRtc_Set[ucRtc_Set_Index]--;
if(ucRtc_Set[ucRtc_Set_Index] % 16 == 0x0f)//按十六进制加,转BCD码
ucRtc_Set[ucRtc_Set_Index] -= 6;
if(ucRtc_Set[ucRtc_Set_Index] == 0xf9)//按十六进制加,转BCD码
ucRtc_Set[ucRtc_Set_Index] = 0;
第九届-彩灯控制系统
#include <STC15F2K60S2.H>
#include <led.h>
#include <init.h>
#include <key.h>
#include <seg.h>
#include "iic.h"
unsigned char key_val,key_old,key_up,key_down,key_slow;
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[8] = {0,0,0,0,0,0,0,0};
unsigned char seg_pos;
unsigned int seg_slow;
unsigned char seg_mode_disp; //0-流转间隔设置界面 1-亮度等级显示界面
unsigned char seg_set_flag; //0-全部熄灭 1-运行模式 2-流转间隔
unsigned int led_time_disp[4] = {400,400,400,400};
unsigned int led_time_ctrl[4] = {400,400,400,400};
unsigned char led_time_index; //0-模式1,1-模式2,2-模式3,3-模式4
unsigned char seg_star; //每400ms闪烁一次
unsigned int Timer_400ms;
unsigned char EEPROM_Dat[4]; //EEPROM存放数据的数组
unsigned char led_level; //led亮度等级 0 1 2 3
bit system_flag; //开始停止标志位
unsigned int ms_tick; //计数值
unsigned char led_mode; //模式1 2 3 4
unsigned char led_pos;
unsigned char led_count;
void key_proc()
{
unsigned char i;
if(key_slow) return;
key_slow = 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;
if(seg_set_flag == 0) //处于非设置界面(熄灭)
{
if(key_old == 4) //长按S4
seg_mode_disp = 1; //亮度显示
else
seg_mode_disp = 0; //数据显示
}
switch(key_down)
{
case 4: //减
if(seg_set_flag == 1) //设置运行模式
{
if(--led_time_index == 255)
led_time_index = 0;
}
else if(seg_set_flag == 2) //设置流转间隔
{
led_time_disp[led_time_index] -= 100;
if(led_time_disp[led_time_index] < 400)
led_time_disp[led_time_index] = 400;
}
break;
case 5: //加按键
if(seg_set_flag == 1) //设置运行模式
{
if(++led_time_index == 4)
led_time_index = 3;
}
else if(seg_set_flag == 2) //设置流转间隔
{
led_time_disp[led_time_index] += 100;
if(led_time_disp[led_time_index] > 1200)
led_time_disp[led_time_index] = 1200;
}
break;
case 6: //设置按键
if(++seg_set_flag == 3)
seg_set_flag = 0;
if(seg_set_flag == 0)//退出设置界面
{
led_time_index = 0;
for(i=0;i<4;i++)
{
led_time_ctrl[i] = led_time_disp[i];
EEPROM_Dat[i] = led_time_ctrl[i]/100;
}
EEPROM_Write(EEPROM_Dat,0,4);
}
break;
case 7: //启动停止按键
system_flag ^= 1;
break;
}
}
void seg_proc()
{
unsigned char i;
if(seg_slow) return;
seg_slow = 1;
led_level = Ad_Read(0x03)/64;
if(seg_mode_disp == 0) //设置界面
{
seg_buf[0] = seg_buf[2] = 11;
seg_buf[1] = led_time_index + 1;
seg_buf[4] = led_time_disp[led_time_index] / 1000 % 10;
seg_buf[5] = led_time_disp[led_time_index] / 100 % 10;
seg_buf[6] = led_time_disp[led_time_index] / 10 % 10;
seg_buf[7] = led_time_disp[led_time_index] % 10;
if(seg_set_flag == 0 ) //全部熄灭
{
for(i=0;i<8;i++)
seg_buf[i] = 10;
}
else if(seg_set_flag == 1) //运行模式
{
seg_buf[0] = seg_buf[2] = seg_star?10:11;
seg_buf[1] = seg_star?10:(led_time_index+1);
}
else //流转间隔
{
seg_buf[4] = seg_star?10:led_time_disp[led_time_index] / 1000 % 10;
seg_buf[5] = seg_star?10:led_time_disp[led_time_index] / 100 % 10;
seg_buf[6] = seg_star?10:led_time_disp[led_time_index] / 10 % 10;
seg_buf[7] = seg_star?10:led_time_disp[led_time_index] % 10;
}
}
else //亮度等级界面
{
for(i=0;i<6;i++)
seg_buf[i] = 10;
seg_buf[6] = 11;
seg_buf[7] = led_level+1;
}
}
void led_proc()
{
unsigned char i;
if(system_flag == 1) //彩灯开始运行
{
if(ms_tick == led_time_ctrl[led_mode]) //
{
ms_tick = 0;
switch(led_mode)
{
case 0:
if(++led_pos == 8)
{
led_pos = 7;
led_mode = 1;
}
break;
case 1:
if(--led_pos == 255)
{
led_pos = 07;
led_mode = 2;
}
break;
case 2:
led_pos += 9;
if(led_pos > 34)
{
led_pos = 34;
led_mode = 3;
}
break;
case 3:
led_pos -= 9;
if(led_pos > 200)
{
led_pos = 0;
led_mode = 0;
}
break;
}
}
if(led_mode < 2) //前两种模式
{
for(i=0;i<8;i++)
ucled[i] = (i == led_pos);
}
else //后两种模式
{
for(i=0;i<8;i++)
ucled[i] = ((i == (led_pos / 10))|| (i == (led_pos % 10)));
}
}
// if(led_mode < 2) //前两种模式
// {
// for(i=0;i<8;i++)
// ucled[i] = (i == led_pos);
// }
// else //后两种模式
// {
// for(i=0;i<8;i++)
// ucled[i] = ((i == (led_pos / 10))|| (i == (led_pos % 10)));
// }
}
void Timer0Init(void) //1毫秒@12.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1;
EA = 1;
}
void Timer0Sever() interrupt 1
{
if(++key_slow == 10) key_slow = 0;
if(++seg_slow == 500) seg_slow = 0;
if(++seg_pos == 8) seg_pos = 0;
if(++led_count == 12) led_count = 0;
seg_disp(seg_pos,seg_buf[seg_pos],seg_point[seg_pos]);
if(led_count<(led_level+1)*3)
led_disp(seg_pos,ucled[seg_pos]);
else
led_disp(seg_pos,0);
if(++Timer_400ms == 400)
{
Timer_400ms = 0;
seg_star ^= 1;
}
if(system_flag == 1)
ms_tick++;
}
void main()
{
unsigned char i;
system_init();
Timer0Init();
EEPROM_Read(EEPROM_Dat,0,4);
for(i=0;i<4;i++)
led_time_disp[i] = led_time_ctrl[i] = EEPROM_Dat[i]*100;
while(1)
{
key_proc();
seg_proc();
led_proc();
}
}
1.定义seg_mode_disp变量分别对应“设置界面”和“亮度界面”,在非设置界面下通过检测key_old是否等于4来进行01切换,在“设置界面”下定义seg_set_flag表示“全部熄灭”“运行模式”“流转间隔”。由于LED有四个模式,四个不同的模式对应四个不同的间隔时间,故定义一对数组来存放四个时间值,相应的EEPROM存放值也定义一个数组。
2.同一按键4或5case下根据seg_set_flag值的不同执行不同的动作,S6进行seg_set_flag值的循环,当设置完成后,保存参数存放到EEPROM中写入一次。
3.将AD读取的电压值(0~255)除以64分成0,1,2,3.定义一个led_count每1ms从0加到11,当led_count<(led_level+1)*3时LED显示,否则LED熄灭,可实现滑动变阻器调节LED的亮度。
4.定义led_mode进行0123模式的指示,定义ms_tick在使能状态下每1ms进行自增,当满足ms_tick == led_time_ctrl[led_mode]时,ms_tick归零,进行一次led_pos的修改。
模式1中led_pos的值为,0、1、2、3、4、5、6、7(每次加一)
模式2中led_pos的值为,7、6、5、4、3、2、1、0(每次减一)
模式3中led_pos的值为,07、16、25、34(每次加九)
模式4中led_pos的值为,34、25、16、07(每次减九)
在驱动LED时,前两种模式进行“互斥点亮”,后两种模式i从0到8循环扫描只要led_pos的十位或者个位等于i,则ucled[i]置1.
第十届-频率电压测量
#include <STC15F2K60S2.H>//单片机寄存器专用头文件
#include <Init.h>//初始化底层驱动专用头文件
#include <Led.h>//Led底层驱动专用头文件
#include <Key.h>//按键底层驱动专用头文件
#include <Seg.h>//数码管底层驱动专用头文件
#include "iic.h"//数模转换底层驱动专用头文件
unsigned char key_val,key_down,key_up,key_old,key_slow;
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 seg_pos;
unsigned int seg_slow;
unsigned char ucled[8] = {0,0,0,0,0,0,0,0};
bit seg_mode_disp;//数码管显示界面模式 0-频率测量显示界面,1-电压测量显示界面
unsigned int Freq;
unsigned int Time_1000ms;
float voltage_ad,voltage_da;
bit led_flag,seg_flag;
bit out_mode;
void key_proc()
{
if(key_slow) return;
key_slow = 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;
switch(key_down)
{
case 4: //显示界面切换
seg_mode_disp ^= 1;
break;
case 5: //输出模式切换
out_mode ^= 1;
break;
case 6: //LED功能控制
led_flag ^= 1;
break;
case 7: //数码管控制
seg_flag ^= 1;
break;
}
}
void seg_proc()
{
unsigned char i;
if(seg_slow) return;
seg_slow = 1;
voltage_ad = Ad_Read(0x03)/51.0;
if(out_mode == 0)
voltage_da = 2;
else
voltage_da = voltage_ad;
if(seg_mode_disp == 0) //频率显示界面
{
seg_buf[0] = 11;//标识符F
seg_buf[3] = Freq / 10000 % 10;
seg_buf[4] = Freq / 1000 % 10;
seg_buf[5] = Freq / 100 % 10;
seg_buf[6] = Freq / 10 % 10;
seg_buf[7] = Freq % 10;
seg_point[5] = 0;
while(seg_buf[i] == 0)
{
seg_buf[i] = 10;
if(++i == 7) break;
}
}
else //电压显示界面
{
seg_buf[0] = 12;//标识符F
seg_buf[3] = seg_buf[4] = 10;
seg_buf[5] = (unsigned char)voltage_ad;
seg_buf[6] = (unsigned int)(voltage_ad * 100) / 10 % 10;
seg_buf[7] = (unsigned int)(voltage_ad * 100) % 10;
seg_point[5] = 1;
}
}
void led_proc()
{
unsigned char i;
Da_Write(voltage_da * 51);
for(i=0;i<2;i++)
ucled[i] = (i == seg_mode_disp);
ucled[2] = ((1.5<= voltage_ad)&(voltage_ad < 2.5)) | (voltage_ad >= 3.5);
ucled[3] = ((1000<=Freq) & (Freq < 5000)) | (Freq >= 10000);
ucled[4] = out_mode;
}
void Timer0Init(void) //0微秒@12.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x05; //设置定时器模式
TL0 = 0x00; //设置定时初值
TH0 = 0x00; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
}
void Timer1Init(void) //1毫秒@12.000MHz
{
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x18; //设置定时初值
TH1 = 0xFC; //设置定时初值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1 = 1;
EA = 1;
}
void Timer1Server() interrupt 3
{
if(++key_slow == 10) key_slow = 0;
if(++seg_slow == 500) seg_slow = 0;
if(++seg_pos == 8) seg_pos = 0;
if(seg_flag == 0)
Seg_Disp(seg_pos,seg_buf[seg_pos],seg_point[seg_pos]);
else
Seg_Disp(seg_pos,10,0);
if(led_flag == 0)
Led_Disp(seg_pos,ucled[seg_pos]);
else
Led_Disp(seg_pos,0);
if(++Time_1000ms == 1000)
{
Time_1000ms = 0;
Freq = TH0 <<8 | TL0;
TH0 = TL0 = 0;
}
}
void main()
{
System_Init();
Timer0Init();
Timer1Init();
while(1)
{
key_proc();
seg_proc();
led_proc();
}
}
1.定义seg_mode_disp控制频率显示与电压显示,按键S4进行01切换,out_mode控制DA输出模式按键S5进行01切换
2.NE555的频率采集,AD采集,DA输出的写法
第十一届第二场温度参数设置
#include <STC15F2K60S2.H>
#include <Led.h>
#include <Seg.h>
#include <Key.h>
#include <Init.h>
#include "onewire.h"
#include "iic.h"
unsigned char key_val,key_down,key_up,key_old,key_slow;
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 int seg_slow;
unsigned char seg_pos;
unsigned char ucled[8] = {0,0,0,0,0,0,0,0};
float temperature;
bit seg_mode_disp;
unsigned char voltage;
unsigned char temperature_disp[2] = {30,20};
unsigned char temperature_ctrl[2] = {30,20};
bit temperature_index = 1;
bit Error_flag;
void key_proc()
{
if(key_slow) return;
key_slow = 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;
switch(key_down)
{
case 4:
seg_mode_disp ^= 1;
if(seg_mode_disp == 1) //进入设置模式
{
temperature_disp[0] = temperature_ctrl[0];
temperature_disp[1] = temperature_ctrl[1];
temperature_index = 1;
}
else //退出设置模式
{
if(temperature_disp[0] > temperature_disp[1])//参数设置正确
{
temperature_ctrl[0] = temperature_disp[0];
temperature_ctrl[1] = temperature_disp[1];
Error_flag = 0;
}
else //参数设置失败
Error_flag = 1;
}
break;
case 5:
if(seg_mode_disp == 1)
temperature_index ^= 1;
break;
case 6:
if(seg_mode_disp == 1)
{
if(++temperature_disp[temperature_index] == 100)
temperature_disp[temperature_index] = 99;
}
break;
case 7:
if(seg_mode_disp == 1)
{
if(--temperature_disp[temperature_index] == 255)
temperature_disp[temperature_index] = 0;
}
break;
}
}
void seg_proc()
{
if(seg_slow) return;
seg_slow = 1;
temperature = rd_temperature();
if(seg_mode_disp == 0)
{
seg_buf[0] = 11;
seg_buf[3] = seg_buf[4] = 10;
seg_buf[6] = (unsigned char)temperature / 10 % 10;
seg_buf[7] = (unsigned char)temperature % 10;
}
else
{
seg_buf[0] = 12;
seg_buf[3] = temperature_disp[0] / 10 % 10;
seg_buf[4] = temperature_disp[0] % 10;
seg_buf[6] = temperature_disp[1] / 10 % 10;
seg_buf[7] = temperature_disp[1] % 10;
}
}
void led_proc()
{
if(temperature > temperature_ctrl[0]) voltage = 4;
else if(temperature < temperature_ctrl[1]) voltage = 2;
else voltage = 3;
DA_write(voltage * 51);
ucled[0] = (temperature > temperature_ctrl[0]);
ucled[1] = ((temperature <= temperature_ctrl[0]) & (temperature >= temperature_ctrl[1]));
ucled[2] = (temperature < temperature_ctrl[1]);
ucled[3] = Error_flag;
}
void Timer0Init(void) //1毫秒@12.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1;
EA = 1;
}
void Timer0server() interrupt 1
{
if(++key_slow == 10) key_slow = 0;
if(++seg_slow == 500) seg_slow = 0;
if(++seg_pos == 8) seg_pos = 0;
seg_disp(seg_pos,seg_buf[seg_pos],seg_point[seg_pos]);
led_disp(seg_pos,ucled[seg_pos]);
}
void Delay750ms() //@12.000MHz
{
unsigned char i, j, k;
i = 35;
j = 51;
k = 182;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void main()
{
rd_temperature();
Delay750ms();
system_init();
Timer0Init();
while(1)
{
key_proc();
seg_proc();
led_proc();
}
}
定义seg_mode_disp来进行“温度显示”“参数显示”界面的切换,定义一对温度最值参数数组来存放温度参数最大值与最小值。退出设置模式检验参数设置合理性返回一个标志位
目录
#include <STC15F2K60S2.H>//单片机寄存器专用头文件
#include <Init.h>//初始化底层驱动专用头文件
#include <Led.h>//Led底层驱动专用头文件
#include <Key.h>//按键底层驱动专用头文件
#include <Seg.h>//数码管底层驱动专用头文件
#include "onewire.h"//温度底层驱动专用头文件
#include "iic.h"//DAC底层驱动专用头文件
unsigned char key_val,key_down,key_up,key_old,key_slow;
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[8] = {0,0,0,0,0,0,0,0};
unsigned char seg_pos;
unsigned int seg_slow;
unsigned char seg_mode_disp=1;//数码管显示模式
float Temperature;//DS18B20读取到的温度
unsigned char temperature_params_disp = 25;//温度参数显示变量
unsigned char temperature_params_ctrol = 25;//温度参数实际控制变量
float Voltage_Output;//DA输出电压
bit Ouput_Mode;
void key_proc()
{
if(key_slow) return;
key_slow = 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;
switch(key_down)
{
case 4://界面切换按键
if(++seg_mode_disp == 3)
seg_mode_disp = 0;
if(seg_mode_disp == 1)
temperature_params_disp = temperature_params_ctrol;
if(seg_mode_disp == 2)
temperature_params_ctrol = temperature_params_disp;
break;
case 5://模式切换按键
Ouput_Mode ^= 1;
break;
case 8://减按键
if(seg_mode_disp == 1)
{
if(--temperature_params_disp == 255)
temperature_params_disp = 0;
}
break;
case 9://加按键
if(seg_mode_disp == 1)
{
if(++temperature_params_disp == 100)
temperature_params_disp = 99;
}
break;
}
}
void seg_proc()
{
if(seg_slow) return;
seg_slow = 1;
Temperature = rd_temperature();
switch(seg_mode_disp)
{
case 0:
seg_buf[0] = 11;//标识符C
seg_buf[4] = (unsigned char)Temperature / 10 % 10;
seg_buf[5] = (unsigned char)Temperature % 10;
seg_buf[6] = (unsigned int)(Temperature * 100) / 10 % 10;
seg_buf[7] = (unsigned int)(Temperature * 100) % 10;
seg_point[5] = 1;
break;
case 1:
seg_buf[0] = 12;//标识符P
seg_buf[4] = seg_buf[5] = 10;
seg_buf[6] = temperature_params_disp/ 10 % 10;
seg_buf[7] = temperature_params_disp % 10;
seg_point[5] = 0;
break;
case 2 :
seg_buf[0] = 13;//标识符R
seg_buf[5] = (unsigned char)Voltage_Output;
seg_buf[6] = (unsigned int)(Voltage_Output*100)/10%10;
seg_buf[7] = (unsigned int)(Voltage_Output*100)%10;
seg_point[5] = 1;
}
}
void led_proc()
{
unsigned char i;
for(i=0;i<3;i++)//模式指示灯
ucled[1+i] = (i == seg_mode_disp);
ucled[0] = !Ouput_Mode;
if(Ouput_Mode == 0)//模式1
{
if(Temperature < temperature_params_ctrol) Voltage_Output = 0;
else Voltage_Output = 5;
}
else//模式2
{
if(Temperature < 20) Voltage_Output = 1;
else if(Temperature > 40) Voltage_Output = 4;
else Voltage_Output = 3/20.0 * Temperature - 2;
}
}
void Timer0Init(void) //1毫秒@12.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //定时器中断0打开
EA = 1; //总中断打开
}
void Timer0Server() interrupt 1
{
if(++key_down == 10) key_slow = 0;//键盘减速专用
if(++seg_slow == 500) seg_slow = 0;//数码管减速专用
if(++seg_pos == 8) seg_pos = 0;//数码管显示专用
Seg_Disp(seg_pos,seg_buf[seg_pos],seg_point[seg_pos]);
Led_Disp(seg_pos,ucled[seg_pos]);
}
void Delay750ms() //@12.000MHz
{
unsigned char i, j, k;
i = 35;
j = 51;
k = 182;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void main()
{
rd_temperature();
Delay750ms();
System_Init();
Timer0Init();
while(1)
{
key_proc();
seg_proc();
led_proc();
}
}
第十三届第一场-温度时间控制继电器
#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_up,key_down,key_slow;
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 int seg_slow;
unsigned char seg_pos;
unsigned char ucled[8] = {0,0,0,0,0,0,0,0};
float temperature; //读取到的温度值
unsigned char temperature_disp = 23; //温度参数显示值
unsigned char temperature_ctrl = 23; //温度参数控制值
unsigned char ucRtc[3] = {0x07,0x58,0x20}; //Rtc数组
unsigned char seg_mode_disp; //0-温度显示,1-时间显示,2-参数设置
bit ucRtc_flag; //0-显示时分,1-显示分秒
bit mode; //0-温度控制,1-时间控制
bit relay_flag; //继电器控制变量 0-断开,1-吸合
unsigned char Timer_100ms;
bit led_star;
void key_proc()
{
// unsigned char i;
if(key_slow) return;
key_slow = 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;
if(seg_mode_disp == 1)//处于时间显示
{
if(key_old == 17) //长按S17
ucRtc_flag = 1; //显示分秒
else
ucRtc_flag = 0; //显示时分
}
switch(key_down)
{
case 12: //显示切换按键
if(++seg_mode_disp == 3)
seg_mode_disp = 0;
if(seg_mode_disp == 2) //进入参数设置界面
temperature_disp = temperature_ctrl;
if(seg_mode_disp == 0) //退出参数设置界面
temperature_ctrl = temperature_disp;
break;
case 13: //模式切换按键
mode ^= 1;
break;
case 16: //加
if(seg_mode_disp == 2)
{
if(++temperature_disp == 100)
temperature_disp = 99;
}
break;
case 17: //减
if(seg_mode_disp == 2)
{
if(--temperature_disp == 255)
temperature_disp = 0;
}
break;
break;
}
}
void seg_proc()
{
unsigned char i;
if(seg_slow) return;
seg_slow = 1;
Read_Rtc(ucRtc);
temperature = rd_temperature();
switch(seg_mode_disp)
{
case 0: //
seg_buf[0] = 12;
seg_buf[1] = 1;
seg_buf[2] = 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;
break;
case 1: //
seg_buf[0] = 12;
seg_buf[1] = 2;
seg_buf[2] = 10;
seg_buf[3] = ucRtc[0]/16;
seg_buf[4] = ucRtc[0]%16;
seg_buf[5] = 11;
seg_buf[6] = ucRtc[1]/16;
seg_buf[7] = ucRtc[1]%16;
seg_point[6] = 0;
break;
case 2:
seg_buf[0] = 12;
seg_buf[1] = 3;
seg_buf[2] = seg_buf[3] = seg_buf[4] =seg_buf[5] = 10;
seg_buf[6] = (unsigned char)temperature_disp/10%10;
seg_buf[7] = (unsigned char)temperature_disp%10;
seg_point[6] = 0;
break;
}
if(ucRtc_flag == 1) //长按S17显示分秒
{
seg_buf[0] = 12;
seg_buf[1] = 2;
seg_buf[2] = 10;
seg_buf[3] = ucRtc[1]/16;
seg_buf[4] = ucRtc[1]%16;
seg_buf[5] = 11;
seg_buf[6] = ucRtc[2]/16;
seg_buf[7] = ucRtc[2]%16;
}
}
void led_proc()
{
//继电器
if(mode == 0)
{
if(temperature > temperature_ctrl)
relay_flag = 1;
else
relay_flag = 0;
}
else
{
if((ucRtc[1]/16 == 0)&&(ucRtc[1]%16 == 0)&&(ucRtc[2]/16 == 0)&&(ucRtc[2]%16 == 0))
relay_flag = 1;
if(ucRtc[2]%16 == 5)
relay_flag = 0;
}
//LED1
if((ucRtc[1]/16 == 0)&&(ucRtc[1]%16 == 0)&&(ucRtc[2]/16 == 0)&&(ucRtc[2]%16 == 0))
ucled[0] = 1;
if(ucRtc[2]%16 == 5)
ucled[0] = 0;
//LED2
if(mode == 0)
ucled[1] = 1;
else
ucled[1] = 0;
//LED3
if(relay_flag == 1)
ucled[2] = led_star;
else
ucled[2] = 0;
}
void Timer0Init(void) //1毫秒@12.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1;
EA = 1;
}
void Timer0Server() interrupt 1
{
if(++key_slow == 10) key_slow = 0;
if(++seg_slow == 500) seg_slow = 0;
if(++seg_pos == 8) seg_pos = 0;
seg_disp(seg_pos,seg_buf[seg_pos],seg_point[seg_pos]);
led_disp(seg_pos,ucled[seg_pos]);
relay(relay_flag);
if(++Timer_100ms == 100)
{
Timer_100ms = 0;
led_star ^= 1;
}
}
void main()
{
system_init();
Timer0Init();
Set_Rtc(ucRtc);
while(1)
{
key_proc();
seg_proc();
led_proc();
}
}
1.定义seg_mode_disp进行“温度显示”“时间显示”“参数设置”界面的切换,定义ucRtc_flag显示“分秒”和“时分”,默认情况下ucRtc_flag = 0在switch(seg_mode_disp)case 2:下显示时分,当长按S17(key_old == 17)时,ucRtc_flag = 1,显示分秒。
2.判断整点可通过 if((ucRtc[1]/16 == 0)&&(ucRtc[1]%16 == 0)&&(ucRtc[2]/16 == 0)&&(ucRtc[2]%16 == 0))
第十四届-光敏电阻触发温度湿度时间采集
#include <STC15F2K60S2.H>
#include <init.h>
#include <led.h>
#include <key.h>
#include <seg.h>
#include "ds1302.h"
#include "onewire.h"
#include "iic.h"
unsigned char key_val,key_old,key_up,key_down,key_slow;
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 int seg_slow;
unsigned char seg_pos;
unsigned char ucled[8] = {0,0,0,0,0,0,0,0};
unsigned char seg_mode_disp; // 0-时间界面,1-回显界面,2-参数界面
unsigned char seg_huixian; //0-温度回显,1-湿度回显,2-时间回显
unsigned char ucRtc[3] = {0x13,0x03,0x05};
unsigned char temp_temperature,old_temperature,average_temperature,max_temperature;
unsigned char temperature_disp = 30; //温度参数显示值
unsigned char temperature_ctrl = 30; //温度参数控制值
unsigned int Timer_1000ms;
unsigned int Freq;
bit freq_flag; //0-有效 ,1-无效
unsigned char hum,temp_hum,old_hum,max_hum,average_hum,max_hum; //湿度
unsigned char trig_num ; //触发次数
unsigned char trig_time[2] = {0x00,0x00}; //触发时间
bit trig_flag ; //触发标志
unsigned char light,light_old; //接受亮度值
unsigned int key_time; //按键计数值
bit key_flag;
unsigned int Timer_3000ms;
bit Timer_3000ms_flag;
unsigned char Timer_100ms;
bit led_star;
void key_proc()
{
if(key_slow) return;
key_slow = 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;
if(key_down == 9)
key_flag = 1;
if(key_time < 2000) //短按S9
{
if(key_up == 9) //
{
}
}
else //长按S9
{
if(key_up == 9) //松开
{
key_flag = key_time = 0;
trig_num = 0;
max_temperature = 0;
max_hum = 0;
average_temperature = 0;
average_hum = 0;
}
}
switch(key_down)
{
case 4: //切换界面
if(++seg_mode_disp == 3)
seg_mode_disp = 0;
if(seg_mode_disp == 1)
temperature_ctrl = temperature_disp; //退出参数设置
if(seg_mode_disp == 3)
temperature_disp = temperature_ctrl; //进入参数设置
break;
case 5: //切换回显
if(seg_mode_disp == 1)
{
if(++seg_huixian == 3)
seg_huixian = 0;
}
break;
case 8: //温度参数加
if(seg_mode_disp == 2)
{
if(++temperature_disp == 100)
temperature_disp = 99;
}
break;
case 9: //温度参数减
if(seg_mode_disp == 2)
{
if(--temperature_disp == 255)
temperature_disp = 0;
}
break;
}
}
void seg_proc()
{
unsigned char i;
if(seg_slow) return;
seg_slow = 1;
//RTC,温度
Read_Rtc(ucRtc);
//湿度
if((Freq < 200) || (Freq > 2000)) //无效范围
freq_flag = 1;
else //有效范围
freq_flag = 0;
if(freq_flag == 0)
hum = 8/180.0 * Freq + 20/18.0;
//AD光敏电阻
light = Ad_Read(0x01);
//满足从亮到暗,满足触发条件。之前未触发。在三秒内
if((light_old > 70)&&(light < 70)&&(trig_flag == 0)&&(Timer_3000ms < 3000))
{
trig_flag = 1; //满足触发条件
temp_temperature = rd_temperature(); //采集温度
temp_hum = hum; //采集湿度
trig_num++;
if(freq_flag == 1)
trig_num--;
else
{
trig_time[0] = ucRtc[0];
trig_time[1] = ucRtc[1];
old_temperature = temp_temperature;
old_hum = temp_hum;
max_temperature = (max_temperature > temp_temperature)?max_temperature:temp_temperature;
max_hum = (max_hum > temp_hum)?max_hum:temp_hum;
if(trig_num == 1)
{
average_temperature = temp_temperature;
average_hum = temp_hum;
}
else
{
average_temperature = (average_temperature * (trig_num-1) + temp_temperature) / trig_num;
average_hum = (average_hum * (trig_num-1) + temp_hum) / trig_num;
}
}
}
if((trig_flag == 1)&&(Timer_3000ms_flag == 1)) //触发3秒后
trig_flag = 0;
light_old = light;
if(trig_flag == 1) //满足触发条件,显示温湿度
{
seg_buf[0] = 16;
seg_buf[1] = seg_buf[2] = 10;
seg_buf[5] = 11;
seg_buf[3] = (unsigned char)temp_temperature / 10 % 10;
seg_buf[4] = (unsigned char)temp_temperature % 10;
seg_point[6] = 0;
if(freq_flag == 0)
{
seg_buf[6] = (unsigned char)temp_hum/10%10;
seg_buf[7] = (unsigned char)temp_hum%10;
}
else
seg_buf[6] = seg_buf[7] = 17;
}
else
{
switch(seg_mode_disp)
{
case 0: //时间界面
seg_buf[2] = seg_buf[5] = 11;
for(i=0;i<3;i++)
{
seg_buf[3*i] = ucRtc[i]/16;
seg_buf[3*i+1] = ucRtc[i]%16;
}
seg_point[6] = 0;
break;
case 1:
switch(seg_huixian) //回显界面
{
case 0: //温度回显
seg_buf[0] = 12; //C
seg_buf[1] = 10;
seg_buf[2] = (unsigned char)max_temperature / 10 % 10;
seg_buf[3] = (unsigned char)max_temperature % 10;
seg_buf[4] = 11;
seg_buf[5] = (unsigned char)average_temperature / 10 % 10;
seg_buf[6] = (unsigned char)average_temperature % 10;
seg_buf[7] = 0;
// seg_buf[7] = (unsigned char)(average_temperature * 10) % 10;
seg_point[6] = 1;
break;
case 1: //湿度回显
seg_buf[0] = 13; //H
seg_buf[1] = 10;
seg_buf[2] = (unsigned char)max_hum / 10 % 10;
seg_buf[3] = (unsigned char)max_hum % 10;
seg_buf[4] = 11;
seg_buf[5] = (unsigned char)average_hum / 10 % 10;
seg_buf[6] = (unsigned char)average_hum % 10;
// seg_buf[7] = (unsigned char)(average_hum * 10) % 10;
break;
case 2: //时间回显
seg_buf[0] = 14; //F
seg_buf[1] = trig_num/10;
seg_buf[2] = trig_num%10;
seg_buf[3] = trig_time[0]/16;
seg_buf[4] = trig_time[0]%16;
seg_buf[5] = 11;
seg_buf[6] = trig_time[1]/16;
seg_buf[7] = trig_time[1]%16;
seg_point[6] = 0;
break;
}
break;
case 2: //参数界面
seg_buf[0] = 15; //P
for(i=0;i<5;i++)
seg_buf[i+1] = 10;
seg_buf[6] = temperature_disp/10;
seg_buf[7] = temperature_disp%10;
break;
}
}
}
void led_proc()
{
unsigned char i;
for(i=0;i<3;i++)//界面指示灯
ucled[i] = (i == seg_mode_disp);
if(temp_temperature > temperature_ctrl)
ucled[3] = led_star;
ucled[4] = freq_flag;
}
void Timer0Init(void) //0毫秒@12.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x05; //设置定时器模式
TL0 = 0x00; //设置定时初值
TH0 = 0x00; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
}
void Timer1Init(void) //1毫秒@12.000MHz
{
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x18; //设置定时初值
TH1 = 0xFC; //设置定时初值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1 = 1;
EA = 1;
}
void Timer1Server() interrupt 3
{
if(++key_slow == 10) key_slow = 0;
if(++seg_slow == 500) seg_slow = 0;
if(++seg_pos == 8) seg_pos = 0;
seg_disp(seg_pos,seg_buf[seg_pos],seg_point[seg_pos]);
led_disp(seg_pos,ucled[seg_pos]);
if(++Timer_1000ms == 1000)
{
Timer_1000ms = 0;
Freq = TH0 << 8 | TL0;
TH0 = TL0 = 0;
}
if(key_flag == 1)
{
if(++key_time == 2000)
key_time = 2000;
}
if(trig_flag == 1)
{
if(++Timer_3000ms == 3000)
{
Timer_3000ms = 0;
Timer_3000ms_flag = 1;
}
}
else
Timer_3000ms_flag = 0;
if(++Timer_100ms == 100)
{
Timer_100ms = 0;
led_star ^= 1;
}
}
void Delay750ms()
{
unsigned char i, j, k;
i = 35;
j = 51;
k = 182;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void main()
{
system_init();
Timer0Init();
Timer1Init();
Set_Rtc(ucRtc);
rd_temperature();
Delay750ms();
while(1)
{
key_proc();
seg_proc();
led_proc();
}
}
1.可定义seg_mode_disp进行“时间界面”“回显界面”“参数界面”的显示,seg_huixian进行“温度回显”“湿度回显”“时间回显”trig_flag进行“温湿度显示”“其他”
2.在seg_proc()中将信息处理部分与信息显示部分分开。
设定一个合理的照度阈值(0~100,这里用70),如果满足旧的照度值大于阈值同时当前照度值小于阈值同时触发标志位为0同时3000ms计数值小于3000,满足一次触发条件,trig_flag = 1; trig_num++;进行一次温湿度采集
3.如果湿度值有效,采集时间进行温湿度最大值和平均值的修改。