前言
目前花了一个月时间自学,编写了开水机整套程序,以及仿真,初步完成。
功能:
检测温度,上传到数码管显示
检测水位,上传到数码管显示
温度上限下限显示和设置
水位上限下限显示和设置
抽水电机自动识别水位高低,并且启动,且进水指示灯亮
出水电机受按键控制,出水和停水按键,且出水指示灯亮
温度过低,接通加热管加热,加热指示灯亮,保温灯灭;过高,关闭继电器,停止加热,加热指示灯灭,保温灯亮;
后期思路:
出水电机转速控制——控制出水量,出水量显示在数码管,并且能够按键调控
串口通讯,为位上位机和下位机;(实物板子操作)
警示灯
主函数
数码管显示
数码管驱动:MAX7221
延迟函数
温度检测:DHT11和DS18B20,我用的是DS18B20
水位检测:ADC0808
仿真软件:protues7.8
下面放下功能代码
main.h头文件
#ifndef __MAIN_H__
#define __MAIN_H__
#include <reg51.h>
#include <intrins.h>
sbit LED_hot = P0^0; //加热LED指示灯
sbit out_water_led = P0^1; //出水指示灯
sbit LED_stop_hot = P0^2; //保温指示灯
sbit KEY_WATER = P0^3; //控制出水按键
sbit KEY_STOP_WATER = P0^4; //控制停水按键
sbit in_water_led = P0^5; //进水指示灯
sbit OUT_WATER_ENT_MOTOR= P3^1; //出水电机控制
sbit OUT_IN_WATER= P3^2; //出水电机正转
sbit IN_WATER_ENT_MOTOR= P3^3; //进水电机控制
sbit hot = P3^4; //加热控制
sbit KEY_HOT = P3^5; //按键加热开关
sbit KEY_STOP_HOT = P3^6; //按键停止加热开关
sbit KEY_MODEL = P3^7; //模式切换开关
//sbit ADD_A = P3^5;
//sbit ADD_B = P3^6;
//sbit ADD_C = P3^7;
extern void Init_Timer0();
extern unsigned char Count;
extern unsigned int Sec;
#endif
main.c主函数
//E:表示水位值,P表示温度值
#include <reg51.h>
#include "main.h"
#include "digital.h"
#include "MAX7221.h"
#include "delay.h"
#include "DS18B20.h"
#include "ADC0808.h"
//#include "uart.h"
unsigned int Count; //温度转换
unsigned int Sec=0; //
unsigned long int c=0;
unsigned char model=0; //模式
unsigned int HOT_L=30; //温度下限
unsigned int HOT_H=90; //温度上限
unsigned char WATER_L=50; //水位上限
unsigned char WATER_H=150; //水位下限
unsigned char Val; //模数转换出的电压值,也就是水位值
void send_byte(unsigned char dat)
{
SBUF = dat; // 将数据送到发送缓冲寄存器SBUF,一位一位的发送
while(!TI); // 等待发送完毕 (发送完毕TI硬件置1)
TI = 0; // 将TI清零,表示可以发送下一字节数据。
}
void send_str(unsigned char *s)
{
while(*s != '\0') // '\0':字符串结束标志
{
send_byte(*s); // 发送1个字节数据,1个字符占8位,1字节
s++; // 指向下一个字符
}
}
void main(void)
{
//------------------------------------参数初始化-------------------------------------------//
WATER=0; //控制进水电机(正转)p3.0
hot=1; //加热管
LED_hot=1; //加热灯
LED_stop_hot=0; //保温灯
IN_WATER_ENT_MOTOR=0; //进水电机使能 p3.3
OUT_IN_WATER=0; //控制出水电机(正转)
OUT_WATER_ENT_MOTOR=0; //出水电机(出水电机使能)
out_water_led=0; //出水灯
in_water_led=0;
KEY_HOT=1; //加热按键/加键
KEY_STOP_HOT=1; //停止加热按键/减键
KEY_MODEL=1; //模式切换1234种模式
//------------------------------------函数初始化-------------------------------------------//
Get_temp(); //温度值获取
Init_Timer0(); //定时器初始化
init_max7221(); //max7221驱动初始化
DS18B20_Init(); //温度初始化
//--------------------------------误差清除------------------------------------------// 如果 出现问题则启动 程序运行过程中,仿真提示RAM COMMAND UNSUPPORTED,这是由于读数据太快,以至于DS18B20还没准备好。会有出现0的问题
while(!Val) //刚启动时电压会输出0,导致电机启动,目的清零
{
ST = 0;
ST = 1; //复位
delay_ms(5);
ST = 0; //开始转换
while(EOC == 0); //等待EOC变1,等待AD转换信号结束
OE = 1; //数据输出开启
Val=P1;
OE = 0; //数据输出关闭
}
while(temp==850)Get_temp(); //清除第一次输出的850,取真实值显示
//------------------------------------循环---------------------------------------------//
while(1)
{
Get_temp(); //获取温度值,传出一个参数temp
Count=temp/10; //温度值换算
if(Count>99) //最大值99°
{
Count=99;
}
//--------------------------出水电机按键控制--------------------------------//
if(KEY_WATER==0||OUT_WATER_ENT_MOTOR==1)
{
OUT_WATER_ENT_MOTOR=1; //出水
out_water_led=1; //LED出水灯亮
}
if(KEY_STOP_WATER==0||OUT_WATER_ENT_MOTOR==0)
{
OUT_WATER_ENT_MOTOR=0; //停止出水
out_water_led=0; //LED出水灯灭
}
//--------------------------------温度值显示----------------------------------//
if(model==0)
{
digital_show(Count); //数字显示
write_data(6,disp_buff_2[14]); //显示“P.”代表温度
write_data(5,disp_buff_1[10]); //显示“-”
if(Count<=HOT_L||KEY_HOT==0||hot==0) //当小于最小温度下限值,则自动加热,或者当加热键按下时,加热。
{
hot=0; //加热
LED_hot=0; //加热灯亮
LED_stop_hot=1; //保温灯灭
}
else if(Count>=HOT_H||KEY_STOP_HOT==0||hot==1) //当大于最大温度上限值,则自动停止加热,或者当停止键按下时,停止加热。
{
hot=1; //停止加热
LED_hot=1; //加热灯灭
LED_stop_hot=0; //保温灯亮
}
//-------------------------------水位初始化------------------------------------//
//-------------------------------ADC0808初始化--------------------------------- //
ST = 0;
ST = 1; //复位
delay_ms(5);
ST = 0; //开始转换
while(EOC == 0); //等待EOC变1,等待AD转换信号结束
OE = 1; //数据输出开启
Val=P1;
OE = 0; //数据输出关闭
DIGITAL_WATER_SHOW(Val); //水位显示
write_data(1,disp_buff_2[11]); //显示“E.”代表水位
//------------------------------进水电机转速控制------------------------------------- //
if(Val == 0) //当电压等于0的时候
{
WATER = 0;
DelayMS(0xff); //延迟255
}
if(Val == 0xff) //当电压等于最大值的时候
{
WATER = 1;
DelayMS(0xff); //延迟255
}
WATER = 1;
DelayMS(Val); //高电平占空比
WATER = 0;
DelayMS(0xff - Val); //低电平占空比
//-----------------------高低水位控制进水电机转速条件----------------------------------- //
if(Val>WATER_H)
{
IN_WATER_ENT_MOTOR=0; //电机停止
in_water_led=0;
}
if(Val<WATER_L)
{
IN_WATER_ENT_MOTOR=1; //电机转动
in_water_led=1;
}
}
//-------------------------温度上限调节----------------------------------//
if(model==1) //上限值设置
{
digital_show(HOT_H); //数字显示
write_data(6,disp_buff_2[12]); //显示“H ”
delay_10um(680);
write_data(6,disp_buff_2[15]); //闪烁
write_data(5,disp_buff_1[10]); //显示“-”
if(KEY_HOT==0) //上限值加
{
HOT_H++;
}
if(HOT_H<=HOT_L) //上限值不能小于下下限值
{
HOT_H=HOT_L+1;
}
if(KEY_STOP_HOT==0) //上限值减
{
HOT_H--;
}
if(HOT_H==99) //上限值不能超过98°
{
HOT_H=98;
}
}
//-------------------------温度下限调节----------------------------------//
if(model==2) //下限值设置
{
digital_show(HOT_L); //数字显示
write_data(6,disp_buff_2[13]); //显示“L” ,代表下限
delay_10um(680);
write_data(6,disp_buff_2[15]); //闪烁
write_data(5,disp_buff_1[10]); //显示“-”
if(KEY_HOT==0) //按键加
{
HOT_L++;
}
if(HOT_L>=HOT_H) //下限值不能高于上限值
{
HOT_L=HOT_H-1;
}
if(KEY_STOP_HOT==0) //按键减
{
HOT_L--;
}
if(HOT_L<1) //下限值最小不小于1
{
HOT_L=1;
}
}
//-----------------------水位上限调节----------------------------------// //水位值Val,范围0——255//
if(model==3)
{
DIGITAL_WATER_SHOW(WATER_H);
write_data(1,disp_buff_2[12]); //显示“H.”代表上限值
write_data(6,disp_buff_2[14]); //显示“P.”代表温度
delay_10um(770);
write_data(1,disp_buff_2[15]); //闪烁
if(KEY_HOT==0)
{
WATER_H++;
}
if(KEY_STOP_HOT==0)
{
WATER_H--;
}
if(WATER_H<=WATER_L)WATER_H=WATER_L+1;//上限必定大于下限
}
//-----------------------水位下限调节----------------------------------//
if(model==4)
{
DIGITAL_WATER_SHOW(WATER_L);
write_data(1,disp_buff_2[13]); //显示“L.”代表温度
delay_10um(820);
write_data(1,disp_buff_2[15]); //闪烁
if(KEY_HOT==0)
{
WATER_L++;
}
if(KEY_STOP_HOT==0)
{
WATER_L--;
}
if(WATER_L>=WATER_H)WATER_L=WATER_H-1; //下限必定小于上限
}
//-----------------------------模式切换------------------------------------ //
if(KEY_MODEL==0)
{
model++;
while(!KEY_MODEL);
}
//当模式等于3的时候清零
if(model==5)
{
model=0;
}
}
}
//
void Init_Timer0()
{
TMOD = 0X21; // TMOD: 设置定时器1工作在方式2, 8-bit 自动重装
TH0 = (65536 - 50000)/256;
TL0 = (65536 - 50000)%256;
TR0 = 1; //开启定时器
ET0 = 1; //开启定时器中断
SCON = 0x50; // SCON: 方式 1, 8-bit, 允许接收数据
TH1 = 0xFD; ///
// TH1: 253 初始值为0xFD 波特率:9600 晶振频率:11.0592MHz //
// 公式: //
// 波特率:11.0592/((256-253)*384)*2^SMOD==9600 //
//SMOD=0,波特率不加倍 //
///
TL1 = 0x0;
TR1 = 1; // TR1: 开启定时器1
EA = 1; //打开总中断
ES = 1; //打开串口中断
// TMOD = 0X02; //T0, 工作模式1
// TH0 = 0x14; //换算成十进制 0x00=256us,0xff=1us
// TL0 = 0x00;
// IE = 0x82;
// TR0 = 1;
}
void Timer0() interrupt 1//定时器0
{
Clock = !Clock;
TH0 = (65536 - 1000)/256;//1ms 定时 模式1非自动重装需要手动重装再次定时
TL0 = (65536 - 1000)%256;
}
// 串口中断处理函数 (串口接收到数据,发送数据完毕都可以引起串口中断)
void uart_interrupt() interrupt 4 //也叫串行中断服务程序
{
unsigned char recv_data;// 用来存放接收到的数据
if(RI) //接收数据(1字节)完毕,RI会被硬件置1
{
RI = 0; // 将 接收中断标志位 清零(让串口可以继续接收数据)
recv_data = SBUF; //读取接收到的数据,并存放到data
//--------------------------------------存放功能区--------------------------------------------------//
switch(recv_data)
{
case '0':hot = 1;send_str("停止加热\n");break;
case '1':hot = 0;send_str("加热\n");break;
case '2':OUT_WATER_ENT_MOTOR=1;send_str("出水\n");break;
case '3':OUT_WATER_ENT_MOTOR=0;send_str("停水\n");break;
case '4':IN_WATER_ENT_MOTOR=1;send_str("抽水\n");break;
case '5':IN_WATER_ENT_MOTOR=0;send_str("停止抽水\n");break;
case '6':model++;send_str("模式切换\n");break;
case '7':if(model==1){HOT_H++;}if(model==2){HOT_L++;}if(model==3){WATER_H++;}if(model==4){WATER_L++;}send_str("加\n");break;
case '8':if(model==1){HOT_H--;}if(model==2){HOT_L--;}if(model==3){WATER_H--;}if(model==4){WATER_L--;}send_str("减\n");break;
case '9':break;
}
}
if(TI)// 发送数据(1字节)完毕
{
TI = 0;// 将 发送中断标志位 清零(让串口可以继续发送数据)
}
}