1. 主函数 main.c
c
#include "STC15F2K60S2.h"
#include "ds1302.h"
#include "iic.h"
#include "onewire.h"
#include "HC573.h"
#include "Nixie.h"
#include "keys.h"
#include "jdq.h"
#include "timer.h"
#include "LED.h"
#include "PCF8591.h"
unsigned char mode = 1;//1湿度 2设置 3定时
unsigned char smg_shidu = 0;
unsigned char stat_shidu = 50;//湿度阈值
unsigned char time_s = 3;//定时时间
unsigned char S5_t = 0 ;//按键5标志位 0停止 1运行
unsigned char stat_jdq =0x00;
unsigned char stat_led =0xff;
unsigned char jdq_s = 0;
unsigned int xms = 0;
unsigned int count = 0;
float ain3_value = 0.0;
float ain3_voit = 0;
unsigned char code SMG_Nodot[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
void Init_System()
{
Select_HC573(0,0x00);
Select_HC573(5,0x00);
Select_HC573(4,0xff);
DisplaySMG_ALL(0xff);
}
void main()
{
Init_System();
Init_timer0();
while(1)
{
DisplaySMG_Info();
Scan_Keys();
jdq_Running();
Running_LED();
Read_PCF8591();
}
}
- 变量定义:定义了系统所需的各种变量,如模式、湿度值、阈值、定时时间等。
Init_System
函数:初始化系统,关闭所有的 74HC573 锁存器输出,熄灭数码管。main
函数:首先调用Init_System
函数进行系统初始化,然后初始化定时器 0。在主循环中,不断调用数码管显示、按键扫描、继电器控制、LED 状态显示和湿度采集等函数。
2. 定时器模块 timer.c
c
#include <STC15F2K60S2.H>
#include "timer.h"
#include "HC573.h"
extern unsigned char smg_shidu;
extern unsigned char stat_shidu;//湿度阈值
extern unsigned char S5_t ;//按键5标志位 0停止 1运行
extern unsigned char time_s ;
extern unsigned char stat_jdq;
extern unsigned char jdq_s ;
extern unsigned int xms ;
extern unsigned int count ;
void Init_timer0()
{
TMOD = 0x01;
TH0=(65535-50000)/256;
TL0=(65535-50000)%256;
EA=1;
ET0=1;
TR0=1;
}
void ServiceTimer0()interrupt 1
{
TH0=(65535-50000)/256;
TL0=(65535-50000)%256;
if(S5_t ==1 )
{
count ++ ;
if(count == (time_s*20))
{
count =0;
jdq_s = 1;
}
}
}
Init_timer0
函数:初始化定时器 0,设置定时器工作模式为模式 1(16 位定时器),定时时间为 50ms,开启总中断和定时器 0 中断,并启动定时器 0。ServiceTimer0
函数:定时器 0 中断服务函数,当按键 5 标志位S5_t
为 1 时,计数器count
加 1。当count
达到time_s * 20
时(即定时时间到),将count
清零,jdq_s
置为 1。
3. 按键扫描模块 Keys.c
c
#include <STC15F2K60S2.H>
#include "keys.h"
#include "Nixie.h"
sbit R1=P3^3;
sbit R2=P3^2;
sbit C1=P4^4;
sbit C2=P4^2;
extern unsigned char mode ;//1湿度 2设置 3定时
extern unsigned char S5_t ;//按键5标志位 0停止 1运行
extern unsigned char stat_shidu;//湿度阈值
extern unsigned char time_s ;
void Scan_Keys()
{
R1 = 1; R2 = 1;
C1 = 0; C2 = 1;
if(R1==0)//S4
{
delay_ms(20);
if(R1==0)
{
while(R1==0)
{
DisplaySMG_Info();
}
if(mode==1)
{
mode=2;
}
else if(mode==2)
{
mode=3;
}
else if(mode==3)
{
mode=1;
}
}
}
if(R2==0)//S5
{
delay_ms(20);
if(R2==0)
{
while(R2==0)
{
DisplaySMG_Info();
}
if(S5_t==0)
{
S5_t=1;
}
else if(S5_t==1)
{
S5_t=0;
}
}
}
R1 = 1; R2 = 1;
C1 = 1; C2 = 0;
if(R1==0)//S8
{
delay_ms(20);
if(R1==0)
{
while(R1==0)
{
DisplaySMG_Info();
}
if(mode == 2)
{
if(stat_shidu>30)
{
stat_shidu = stat_shidu - 5;
}
else
{
stat_shidu = 90;
}
}
if(mode == 3)
{
if(time_s>1)
{
time_s = time_s - 1;
}
else
{
time_s = 10;
}
}
}
}
if(R2==0)//S9
{
delay_ms(20);
if(R2==0)
{
while(R2==0)
{
DisplaySMG_Info();
}
if(mode == 2)
{
if(stat_shidu<90)
{
stat_shidu = stat_shidu + 5;
}
else
{
stat_shidu = 30;
}
}
if(mode == 3)
{
if(time_s < 10)
{
time_s = time_s + 1;
}
else
{
time_s = 1;
}
}
}
}
}
- 按键定义:定义了四个按键
S4
、S5
、S8
和S9
,通过行列扫描的方式检测按键状态。 Scan_Keys
函数:实现了按键扫描功能,通过软件消抖处理,避免按键抖动引起的误触发。不同的按键有不同的功能:S4
:切换系统工作模式,依次为湿度显示、湿度阈值设置和定时时间设置。S5
:启动或停止系统运行。S8
:在湿度阈值设置模式下,减小湿度阈值;在定时时间设置模式下,减小定时时间。S9
:在湿度阈值设置模式下,增大湿度阈值;在定时时间设置模式下,增大定时时间。
4. 数码管显示模块 Nixie.c
c
#include "Nixie.h"
#include "STC15F2K60S2.h"
#include "HC573.h"
extern unsigned char mode ;//1湿度 2设置 3定时
extern unsigned char code SMG_Nodot[10];
extern unsigned char smg_shidu;
extern unsigned char stat_shidu;//湿度阈值
extern unsigned char time_s ;
void delay_ms(unsigned int xms)
{
unsigned int i,j;
for(i=xms;i>0;i--)
for(j=123;j>0;j--);
}
void delay_smg(unsigned int xms)
{
unsigned int i,j;
for(i=xms;i>0;i--)
for(j=123;j>0;j--)
DisplaySMG_Info();
}
void DisplaySMG_Bit(unsigned char pos,unsigned char value)
{
Select_HC573(6,0x01<<pos);
Select_HC573(7,value);
delay_ms(1);
Select_HC573(6,0x01<<pos);
Select_HC573(7,0xff);
}
void DisplaySMG_ALL(unsigned char value)
{
Select_HC573(6,0xff);
Select_HC573(7,value);
}
void DisplaySMG_Info()
{
switch(mode)
{
case 1:
if(smg_shidu > 9)
{
DisplaySMG_Bit(6,SMG_Nodot[smg_shidu / 10]);
}
DisplaySMG_Bit(7,SMG_Nodot[smg_shidu % 10]);
DisplaySMG_Bit(0,0xC6);
break;
case 2:
if(stat_shidu > 9)
{
DisplaySMG_Bit(6,SMG_Nodot[stat_shidu / 10]);
}
DisplaySMG_Bit(7,SMG_Nodot[stat_shidu % 10]);
DisplaySMG_Bit(0,0x86);
break;
case 3:
if(time_s > 9)
{
DisplaySMG_Bit(6,SMG_Nodot[time_s / 10]);
}
DisplaySMG_Bit(7,SMG_Nodot[time_s % 10]);
DisplaySMG_Bit(0,0x89);
break;
}
}
- 延时函数:
delay_ms
函数用于实现毫秒级延时,delay_smg
函数在延时的同时不断刷新数码管显示。 - 数码管显示函数:
DisplaySMG_Bit
函数:在指定位置显示指定字符。DisplaySMG_ALL
函数:在所有数码管上显示相同的字符。DisplaySMG_Info
函数:根据系统工作模式,显示当前湿度、湿度阈值或定时时间。
5. 继电器控制模块 jdq.c
c
#include <STC15F2K60S2.H>
#include "jdq.h"
#include "HC573.h"
#include "Nixie.h"
extern unsigned char smg_shidu;
extern unsigned char stat_shidu;//湿度阈值
extern unsigned char S5_t ;//按键5标志位 0停止 1运行
extern unsigned char time_s ;
extern unsigned int xms ;
extern unsigned char stat_jdq;
extern unsigned char jdq_s ;
extern unsigned int count ;
void jdq_Running()
{
if(S5_t == 0)
{
stat_jdq &= ~0x10;
Select_HC573(5,stat_jdq);
jdq_s = 0;
}
else if(S5_t == 1)
{
if(smg_shidu < stat_shidu)
{
stat_jdq |= 0x10;
Select_HC573(5,stat_jdq);
if(jdq_s==1)
{
stat_jdq &= ~0x10;
Select_HC573(5,stat_jdq);
count = 0; // 计数器清零
}
}
else
{
stat_jdq &= ~0x10;
Select_HC573(5,stat_jdq);
jdq_s = 0;
count = 0; // 计数器清零
}
}
}
jdq_Running
函数:根据按键 5 标志位S5_t
和当前湿度smg_shidu
与湿度阈值stat_shidu
的比较结果,控制继电器的开关。当S5_t
为 0 时,关闭继电器;当S5_t
为 1 且当前湿度小于阈值时,打开继电器;当jdq_s
为 1 时,关闭继电器并清零计数器。
6. 湿度采集模块 pcf8591.c
c
#include <STC15F2K60S2.H>
#include "iic.h"
#include "PCF8591.h"
extern unsigned char smg_shidu;
extern float ain3_value ;
extern float ain3_voit;
unsigned char PCF8591_ADC()
{
unsigned char tmp;
I2CStart();
I2CSendByte(0x90);
I2CWaitAck();
I2CSendByte(0x43);
I2CWaitAck();
I2CStop();
I2CStart();
I2CSendByte(0x91);
I2CWaitAck();
tmp = I2CReceiveByte();
I2CSendAck(1);
I2CWaitAck();
I2CStop();
return tmp;
}
void Read_PCF8591()
{
unsigned char i;
for(i=0;i<3;i++)
{
ain3_value+=PCF8591_ADC();
}
ain3_value = (ain3_value /3.0)/51.0;
ain3_voit = ain3_value *(80.0/3.0)+10-(80.0/3.0) ;
if(ain3_value <=1.0)
{
smg_shidu = 10;
}
else if(ain3_value >=4.0)
{
smg_shidu = 90;
}
else
{
smg_shidu = ain3_voit;
}
}
PCF8591_ADC
函数:通过 I2C 总线与 PCF8591 进行通信,读取指定通道的模拟量转换结果。Read_PCF8591
函数:连续读取三次数据并求平均值,然后将平均值转换为湿度值。根据转换后的湿度值范围,将其映射到 10 - 90 的湿度区间。
7. LED 状态指示模块 LED.c
#include "LED.h"
#include <STC15F2K60S2.H>
#include "HC573.h"
extern unsigned char mode ;//1湿度 2设置 3定时
extern unsigned char stat_led ;
extern unsigned char S5_t ;//按键5标志位 0停止 1运行
void Running_LED()
{
if(mode == 1)
{
stat_led &= ~0x01;
}
else
{
stat_led |= 0x01;
}