/*********************************************************
-- 程序名称:温室定(变)量灌溉控制器:
-- 功 能:1).系统菜单; 2).空气湿度测量; 3).温度测量;
4).变量轮灌; 5).定量轮灌; 6).定量点灌;
7).更新定时时间; 8).系统自检.
-- 时 间:2010-11-4
-- 编 程:杨术明 Version:v1.0
-- 修改时间:2010-11-11
;*********************************************************/
//------------包含文件--------
#include<reg52.h>
#include<math.h>
#include<string.h>
#include<INTRINS.H>
#include <absacc.h>
#include <stdio.h>
//#include<stdlib.h>
#include "scancodesysm.h"
#include "STC5A_EEPROM.h"
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
//----------------------
#define BYTE_BIT0 0x01
#define BYTE_BIT1 0x02
#define BYTE_BIT2 0x04
#define BYTE_BIT3 0x08
#define BYTE_BIT4 0x10
#define BYTE_BIT5 0x20
#define BYTE_BIT6 0x40 A
#define BYTE_BIT7 0x80
//---------------------
/***********************JHD19264A接口*****************************
;连线图:
;LCM---89C52 LCM---89C52 LCM-------89C52 LCM----------89C52
;DB0---P0.0 DB4---P0.4 D/I-------P2.2 CS1----------P2.3
;DB1---P0.1 DB5---P0.5 R/W-------P2.1 CS2----------P2.4
;DB2---P0.2 DB6---P0.6 RST--------VCC RST----------P3.4
;DB3---P0.3 DB7---P0.7 E---------P2.0
;注:89C52的晶振频率为11.0592MHz
;写汉字液晶子程 液晶屏分为4行*12列汉字,全部使用模拟接口方式
;******************************************************************/
//-----常用操作命令和参数定义---------
#define DISPON 0x3f //显示on
#define DISPOFF 0x3e //显示off
#define DISPFIRST 0xc0 //显示起始行定义
#define SETX 0x40 //X定位设定指令(页)
#define SETY 0xb8 //Y定位设定指令(列)
#define Lcdbusy 0x80 //LCM忙判断位
//--------显示分区边界位置------------
#define MODL 0x00 //左区
#define MODM 0x40 //左区和中区分界
#define MODR 0x80 //中区和右区分界
#define LCMLIMIT 0xC0 //显示区的右边界
sfr Datalcm =0x80; //数据口
//-----液晶显示器接口引脚定义--------
sbit Elcm =P2^0; //
sbit Rwlcm =P2^1; //
sbit Dilcm =P2^2; //
sbit CS1LCM =P2^3; //
sbit CS2LCM =P2^4; //
//----蜂鸣器,继电器---------------
sbit relay =P2^5;
sbit Beep =P2^6;
bdata uchar keyflag=0;
sbit key0flag=keyflag^0;
sbit key1flag=keyflag^1;
//sbit timeflag=keyflag^2;
sbit serialflag=keyflag^3;
sbit tempflag=keyflag^4;
sbit soilflag=keyflag^5;
//----DHT21-------------------------
sbit DHT21_DAT =P2^7; //DHT21 DATA引脚
uchar data U8FLAG,k,err;
uchar idata U8count,U8temp;
uchar idata U8T_data_H,U8T_data_L,U8RH_data_H,U8RH_data_L,U8checkdata; //16位湿度数据+16位温度数据+8位校验位;
uchar idata U8T_data_H_temp,U8T_data_L_temp,U8RH_data_H_temp,U8RH_data_L_temp,U8checkdata_temp;
uchar idata U8comdata;
float xdata temp=0,humidity=0;
uint xdata U16temp1=0, U16temp2=0;
int xdata adjh=0,adjt=0;
//========继电器组定义(7站)==================
/*sbit RELAY1 = P1^1; //
sbit RELAY2 = P3^7;
sbit RELAY3 = P1^3;
sbit RELAY4 = P1^2;
sbit RELAY5 = P1^4;
sbit RELAY6 = P2^7;
sbit RELAY7 = P3^5; */
//========继电器组定义(4站)==================
sbit RELAY1 = P1^3; //
sbit RELAY2 = P3^7; //
sbit RELAY3 = P1^4;
sbit RELAY4 = P1^2;
//==============PS2键盘=================
sbit Key_CLK =P3^3; //INT1
sbit Key_Data =P3^6; //WR
sbit Redled =P3^5; //T1
//-------------STC12C5A32AD------------
sfr CLK_DIV =0x97; //时钟分频寄存器
sfr AUXR =0x8e; //辅助寄存器
sfr AUXR1 =0xA2; //辅助寄存器1,AUXR1.2为ADRJ:0,10位结果的高8位存放在ADC_RES中,低2位存放在ADC_RES1的低2位;1,10位结果的高2位存放在ADC_RES1的低2位,低8位存放在ADC_RES中
sfr P1ASF =0X9D; //P1口模拟特殊功能选择寄存器,相应位置1,P1.4则当A/D使用
sfr ADC_CONTR =0XBC; //A/D转换控制寄存器,ADC_POWER SPEED1 SPEED2 ADC_FLAG ADC_START CHS2 CHS1 CHS0
sfr ADC_RES =0XBD; //A/D转换结果寄存器
sfr ADC_RESL =0XBE; //A/D转换结果寄存器低
sfr BRT =0x9C; //时钟分频寄存器
sfr WDT_CONTR =0xC1; //看门狗SFR,声明寄存器 STC12c系列
//============命令帧,数据帧头及分机编号,命令类型定义=======
#define RELAYNO1 0x01
#define RELAYNO2 0x02
#define RELAYNO3 0x03
#define RELAYNO4 0x04
#define RELAYNO5 0x05
#define RELAYNO6 0x06
#define RELAYNO7 0x07
#define COMTEMP 0x01
#define COMSOIL 0x02
#define COMTEMP_SOIL 0x03
#define COMOK 0x04
#define COMERR 0x05
#define SOIL_LOWERLIMIT 15
#define SOIL_UPPERLIMIT 20
#define TEMP_LOWERLIMIT 15
#define TEMP_UPPERLIMIT eeprom[6]
#define HUMI_LOWERLIMIT eeprom[5]
#define HUMI_UPPERLIMIT 50
//----------------------------------------------------------------------------------------------------------------
bdata uchar DATA_BUF;
#define DATA7 ((DATA_BUF&BYTE_BIT7) != 0) // 就是一个宏定义, 遇到宏 DATA7 就会替换成 ((DATA_BUF & BYTE_BIT7) != 0)
#define DATA0 ((DATA_BUF&BYTE_BIT0) != 0)
sbit flag =DATA_BUF^7;
sbit flag1 =DATA_BUF^0;
uchar idata str[5]={0};
char xdata timerset[4]={25,25,25};
float xdata soilmoisture=0;
float xdata soil;
//char* soil;
//char txbuf[]; /// 待定
/****************全局变量定义*******************/
uchar col,row,cbyte; //列x,行(页)y,输出数据
bit TimeFlag=0;
bit Hzflag=0;
bit Disflag=0,CheckFlag=0,ESCFlag=0,OKFlag=0;
uint TimeCounter,TimeCnt; //TimeCounter:电磁阀开启时间常数;TimeCnt:计数器
uint xdata timersendcontrol=300;//定时灌溉时间控制参数 300/300=1min
bit numlockflag=0,validflag=0;//收到有效键码标志
uchar IntNum = 0; //中断次数计数
uchar KeyV; //键盘传来的通码或断码
uchar retkey,key;
bit Key_UP=1,Shift = 0;//Key_UP=0是键松开标识,Shift=0是Shift键按下标识
bit BF = 0; //标识是否有键按下标识,有键按下在中断中置1,解码完毕清0
uchar rxflag=0;
// ------------------通信变量-------------------------
//uchar data uc0;//,RetKey;
uchar xdata ComBuf[20]; //register for display
char xdata eeprom[7]; //eerom中参数:T0 T1 T3 AT AH HL TL
//eeprom[0]=timerset[0],eeprom[1]=timerset[1],eeprom[2]=timerset[2]
//eeprom[3]=adjt, eeprom[4]=adjh, eeprom[5]=Humid LOW
//eeprom[6]=Temp LOW
//---------------键值定义-------------------
display[];
#define NoKeyPress 0xff //* 没有键按下
#define KEY_INS 0
#define KEY_END 1
#define KEY_DOWN 2
#define KEY_PgDn 3
#define KEY_LEFT 4
#define KEY_RIGHT 6
#define KEY_HOME 7
#define KEY_UP 8
#define KEY_PgUp 9
#define KEY_ESC 10
#define KEY_OK 13
//--------Menu Definition-------------------
uchar iMenuID; //当前菜单的ID
uchar iMenuNextID; //将要显示菜单的ID,
uchar idata cMenuTemp1;//显示菜单时的临时索引号
//======当前状态索引号定义===========
#define MAX_KEYTABSTRUCT_NUM 20
#define MENU_FACE 0
#define MENU_ROOT 1
#define MENU_Mode 2
#define MENU_Mode_UNIFORMRATE 3
#define MENU_Mode_SELECT 4
#define MENU_Selfcheck 5
#define MENU_Selfcheck_KBCHECK 6
#define MENU_Selfcheck_DHT21 7
#define MENU_Selfcheck_SENSORCHECK 8
#define MENU_Selfcheck_nRF905CHECK 9
#define MENU_SystemSet 10
#define MENU_SystemSet_COM 11
#define MENU_SystemSet_COM_BAUDRATE 12
#define MENU_SystemSet_COM_SELECOM 13
#define MENU_SystemSet_INITIALAMOUNT 14
#define MENU_Experiment 15
#define MENU_Experiment_DHT21_ADJUST 16
#define MENU_Experiment_SENSOR 17
#define MENU_Experiment_WATERMAN 18
#define MENU_Experiment_EMVopen 19
//-------------------------------------------------
typedef struct
{
uchar KeyTab_MenuIndex; //当前状态索引号
uchar KeyTab_MaxItems; //本级菜单最大条目数
uchar KeyTab_PressOk; //按下"回车"键时转向的状态索引号
uchar KeyTab_PressEsc; //按下"返回"键时转向的状态索引号
uchar KeyTab_PressDown; //按下"向下"键时转向的状态索引号
uchar KeyTab_PressUp; //按下"向上"键时转向的状态索引号
void (*CurrentOperate)(); //当前状态应该执行的功能操作
}KeyTabStruct;
void (*KeyFuncPtr)(); //按键功能指针
typedef struct PID
{
int SetPoint; //设定目标 Desired Value
long SumError; //误差累计
double Proportion; //比例常数 Proportional Const
double Integral; //积分常数 Integral Const
double Derivative; //微分常数 Derivative Const
int LastError; //Error[-1]
int PrevError; //Error[-2]
} PID;
static PID sPID;
static PID *sptr = &sPID;
/*****************函数列表**********************/
void Lcminit(void); //液晶模块初始化
void Delay(uchar); //延时,入口数为Ms
void Delay1(uint j);
//void delay1(uint i);
void lcdbusyL(void); //busy判断、等待(左区)
void lcdbusyM(void); //busy判断、等待(中区)
void lcdbusyR(void); //busy判断、等待(右区)
//void Putedot(uchar); //半角字符输出
void Putedot(uchar Order,bit DispAttrib); //半角字符输出
void Putcdot(uchar); //全角(汉字)输出
void Wrdata(uchar); //数据输出给LCM
void Lcmcls( void ); //LCM全屏幕清零(填充0)
void wtcom(void); //公用busy等待
void Locatexy(void); //光标定位
void WrcmdL(uchar); //左区命令输出
void WrcmdM(uchar); //中区命令输出
void WrcmdR(uchar); //右区命令输出
void Putstr(uchar *puts,uchar i); //中英文字符串输出
void Timer0init(void);
void Timer1init(void);
uchar Key_Press(bit b);
void RestWatchdog(void);
void TranDataBy232(uchar d);
void OpeningBeep(uchar OBN);
void InitSBUF(void);
void RecvToBuf(void);
void CheckLED(void);
//void DispFirstmenu(void);
void Lcmclsline(uchar lineNo );
void MenuFunctionDemo1(void);
void JudgeHLight(void);
void DispFace(void);
uchar Decode(uchar ScanCode);
void FlashLed(uchar num);
void Config905(void);
void nRF905Init(void);
void read_humidity(void);
void work_humidity(void);
void SendData(uchar *a);
void eeprom_initialize(void);
void eeprom_save(void);
void work_adc(void);
void IncPIDInit(void);
int IncPIDCalc(int NextPoint);
/******************数组列表*********************/
uchar code Ezk[]; //ASCII常规字符点阵码表0
uchar code Hzk[]; //自用汉字点阵码表
uchar code STR0[];
uchar code STR1[]; //自定义字符串
//uchar code STR2[];
uchar code Hzk1[]; //自用汉字点阵码表1
uchar code Hzk2[]; //自用汉字点阵码表1
//KeyTabStruct code KeyTab[MAX_KEYTABSTRUCT_NUM];
KeyTabStruct xdata KeyTab[MAX_KEYTABSTRUCT_NUM];
uchar code *Menu_Root[4]=
{
" Mode ",
" Check",
" Set ",
" Help "
};
uchar code Menu_RootID[4]=
{
MENU_Mode,
MENU_Selfcheck,
MENU_SystemSet,
MENU_Experiment
};
uchar code *Menu_Mode[2]=
{
" Variable Rate",
" Rotational Rate",
};
uchar code Menu_ModeID[2]=
{
MENU_Mode_UNIFORMRATE,
MENU_Mode_SELECT
};
//
uchar code *Menu_Selfcheck[5]=
{
" Keyboard Check",
" DHT21 Check",
" EEPROM Check",
" nRF905 Check",
};
uchar code Menu_SelfcheckID[4]=
{
MENU_Selfcheck_KBCHECK,
MENU_Selfcheck_DHT21,
MENU_Selfcheck_SENSORCHECK,
MENU_Selfcheck_nRF905CHECK,
};
//
uchar code *Menu_SystemSet[2]=
{
" Set Partime ",
" Set Alltime"
};
uchar code Menu_SystemSetID[2]=
{
MENU_SystemSet_COM,
MENU_SystemSet_INITIALAMOUNT
};
uchar code *Menu_COM[2]=
{
" T0-T3 ",
" Selected Rate"
};
uchar code Menu_COMID[2]=
{
MENU_SystemSet_COM_BAUDRATE,
MENU_SystemSet_COM_SELECOM
};
uchar code *Menu_Experiment[4]=
{
" DHT21 Adjust_H",
" Adj All ",
" Irri Manually",
" DHT21 Adjust_T"
};
uchar code Menu_ExperimentID[4]=
{
MENU_Experiment_DHT21_ADJUST,
MENU_Experiment_SENSOR,
MENU_Experiment_WATERMAN,
MENU_Experiment_EMVopen,
};
//uchar code MenuNULL[]={" "};
/********************************
--------- 主程序---------------
********************************/
void main(void)
{
uchar i;
CLK_DIV=2;
//WDT_CONTR = 0x3E;// 4.55s 启动看门狗
Delay(20);
FlashLed(3);
OpeningBeep(3);
col=0;
row=0;
eeprom_initialize();
//for(i=0;i<4;i++) timerset=25;
TimeFlag=0;
iMenuID=MENU_FACE;
iMenuNextID=MENU_ROOT;//按下回车时显示Menu-root菜单
Timer0init(); Timer1init();
InitSBUF();
Lcminit(); //液晶模块初始化,包括全屏幕清屏
IncPIDInit();
retkey=0xff;
IT1 = 0; //设外部中断1为低电平触发
EX1 = 1; //开中断
DispFace();
i=3;
while(1)
{
key=Key_Press(0);//按键扫描程序
if(i) key= KEY_OK;//directly go to the variable rate irrigation mode
if(i!=0) i=i-1;
switch(key)
{
case KEY_OK://KEY_OK, KEY_UP, KEY_ESC,
if(KeyTab[iMenuID].KeyTab_PressOk!=99)
//if((KeyTab[iMenuID].KeyTab_PressOk!=99)&&(iMenuNextID!=99))//ysm
{ //还有子菜单,将子菜单的索引号作为当前索引号
//iMenuID=KeyTab[iMenuID].KeyTab_PressOk;
iMenuID=iMenuNextID;//用iMenuID暂存父菜单ID,以备按下ESC时能回到先前显示状态,即高亮显示菜单不变.
iMenuNextID=KeyTab[iMenuID].KeyTab_PressOk;//将要高亮显示的子菜单索引号
//TranDataBy232(iMenuID);
//TranDataBy232(iMenuNextID);
JudgeHLight();//显示子菜单
}
KeyFuncPtr=KeyTab[iMenuID].CurrentOperate;//无子菜单则执行该菜单命令
(*KeyFuncPtr)(); //执行当前按键的操作
//TranDataBy232(key);OpeningBeep(1);
break;
case KEY_UP:
if(KeyTab[iMenuNextID].KeyTab_PressUp!=99)//&&(iMenuNextID!=99))
{//当前高亮显示菜单还有兄菜单
//KeyTab[iMenuID].KeyTab_PressOk=KeyTab[iMenuNextID].KeyTab_PressUp;
iMenuNextID=KeyTab[iMenuNextID].KeyTab_PressUp;
//TranDataBy232(iMenuID);
//TranDataBy232(iMenuNextID);
JudgeHLight();
}
break;
case KEY_DOWN:
if(KeyTab[iMenuNextID].KeyTab_PressDown!=99)//&&(iMenuNextID!=99))
{ //当前高亮显示菜单还有弟菜单
iMenuNextID=KeyTab[iMenuNextID].KeyTab_PressDown;
//TranDataBy232(iMenuID);
//TranDataBy232(iMenuNextID);
JudgeHLight();
}
break;
case KEY_ESC:
if(KeyTab[iMenuID].KeyTab_PressEsc!=99)
{ //菜单还没到顶,还有父菜单
iMenuNextID=iMenuID;//YSM:从iMenuID取回进入父菜单的高亮显示菜单的ID
iMenuID=KeyTab[iMenuID].KeyTab_PressEsc;//将父菜单的索引号作为当前索引号
//iMenuNextID=KeyTab[iMenuID].KeyTab_PressOk;
JudgeHLight(); //显示父菜单
//TranDataBy232(iMenuID);
// TranDataBy232(iMenuNextID);
KeyFuncPtr=KeyTab[iMenuID].CurrentOperate;
(*KeyFuncPtr)(); //执行当前按键的操作
}
break;
default:
break;
}
}
}
void Timer0init(void)
{
TR0 = 0; //关闭定时器0
TH0=0x4B; //200ms@(11.0592/4=2.7648)Mhz 12/11.0592=1.085*4=4.34us 65536-46083=19453=0x4BFD
TL0=0xFD;
}
void Timer0_int(void) interrupt 1 using 1
{
TH0=0x4B; //200ms@11.0592Mhz 12/11.0592=1.085us 65535-4608=56319=0xEDFF
TL0=0xFD;
TimeCnt--;
if(TimeCnt==0)
{
TimeFlag=1; TR0=0;TH0=0x4B;TL0=0xFD;
TimeCnt=TimeCounter;
}
}
void Timer1init(void)
{
TR1 = 0; //关闭定时器0
TH1=0; //284ms@(11.0592/4=2.7648)Mhz 12/11.0592=1.085*4=4.34us 65536*4.34=284 426us=284ms
TL1=0;
}
void Timer1_int(void) interrupt 3 using 3
{
TH0=0; //200ms@11.0592Mhz 12/11.0592=1.085us 65535-4608=56319=0xEDFF
TL0=0;
WDT_CONTR = 0x3E;//喂狗
}
/**********************
----- 外部中断0 -----
/**********************/
void External0(void) interrupt 0 using 2
{
CheckFlag=1;
_nop_();
}
/**************************
------ 外部中断1 -------
**************************/
//void External1(void) interrupt 2 using 3
//{
// _nop_();
//}
/****************************************/
/* 一个字串的输出 */
/****************************************/
void Putstr(uchar *puts,uchar i)
{
uchar j,X;
for (j=0;j<i;j++)
{
X = puts[j];
if (X&0x80)
{
Putcdot(X&0x7f); //只保留低7位
}
else Putedot(X-0x20,0); //ascii码表从0x20开始
}
}
/****************************************/
/* 半角字符点阵码数据输出 */
//DispAttrib=0:nomal;=1反显
/****************************************/
void Putedot(uchar Order,bit DispAttrib)
{
uchar i,bakerx,bakery; //共定义4个局部变量
int x; //偏移量,字符量少的可以定义为uchar
bakerx = col; //暂存x,y坐标,已备下半个字符使用
bakery = row;
x=Order * 0x10; //半角字符,每个字符16字节
//上半个字符输出,8列
for(i=0;i<8;i++)
{
cbyte = Ezk[x];
if(DispAttrib) //取点阵码,rom数组
{Wrdata(~cbyte);}
else
{Wrdata(cbyte);} //写输出一字节
x++;
col++;
if (col==LCMLIMIT){col=0;row++;row++;}; //下一列,如果列越界换行
if (row>7) row=0; //如果行越界,返回首行
} //上半个字符输出结束
col = bakerx; //列对齐
row = bakery+1; //指向下半个字符行
//下半个字符输出,8列
for(i=0;i<8;i++)
{
cbyte = Ezk[x]; //取点阵码
if(DispAttrib) //取点阵码,rom数组
{Wrdata(~cbyte);}
else
{Wrdata(cbyte);} //写输出一字节
x++;
col++;
if (col==LCMLIMIT){col=0;row=row+2;}; //下一列,如果列越界换行
if (row>7) row=1; //如果行越界,返回首行 //
} //下半个字符输出结束
row=bakery;
} //整个字符输出结束
/****************************************/
/* 全角字符点阵码数据输出 */
/****************************************/
void Putcdot(uchar Order)
{
uchar i,bakerx,bakery; //共定义3个局部变量
int x; //偏移量,字符量少的可以定义为uchar
bakerx = col; //暂存x,y坐标,已备下半个字符使用
bakery = row;
x=Order * 0x20; //每个字符32字节
//上半个字符输出,16列
for(i=0;i<16;i++)
{
if(Hzflag)
Wrdata(Hzk1[x]); //写输出一字节
else
Wrdata(Hzk2[x]);
x++;
col++;
if (col==LCMLIMIT){ col=0;row++;row++;} //下一列,如果列越界换行
if (row>6) row=0; //如果行越界,返回首行
} //上半个字符输出结束
//下半个字符输出,16列
col = bakerx;
row = bakery+1;
for(i=0;i<16;i++) //下半部分
{
if(Hzflag)
Wrdata(Hzk1[x]); //写输出一字节
else
Wrdata(Hzk2[x]);
x++;
col++;
if (col==LCMLIMIT){col=0;row++;row++;} //下一列,如果列越界换行
if (row>7) row=1; //如果行越界,返回首行
} //下半个字符输出结束
row = bakery;
} &
一周热门 更多>