⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lcd_main.c

📁 LCD显示温控器制作成功 参考了明浩的温度控制器V1.5和使用1602液晶显示和PS/2键盘的示例
💻 C
📖 第 1 页 / 共 2 页
字号:
/*----------------------------------------------------------------
                
					***LCD显示温控器***  2004-8-12

参考资料:《温度控制器V1.5》、《使用1602液晶显示和PS/2键盘的示例》

本软件仅供学习与参考,引用时请注明版权
本程序源码只供学习参考,不得应用于商业用途,如有需要请联系作者。
http://www.cdle.net
明浩 2004/1/2
pnzwzw@cdle.net
----------------------------------------------------------------*/



#include <REGX51.H>
#include <string.h>
#include <intrins.h>

#define LCM_RW P2_0 //定义引脚
#define LCM_RS P2_1
#define LCM_E P2_2
#define LCM_Data P1
#define Busy 0x80 //用于检测LCM状态字中的Busy标识

#define Key_UP            P2_3    //上调温度
#define Key_DOWN          P2_5    //下调温度
#define Key_SET           P2_4    //设定键(温度设定,长按开电源)
#define RelayOutPort      P2_6    //继电器输出
#define TMPort			  P2_7	  //DS1820 DataPort

unsigned char code LCDDis[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x20,0x2d}; //0-9的ASCII码,0x20为空,0x2d为负号

unsigned char i;

static unsigned char bdata StateREG;	//可位寻址的状态寄存器
sbit DS1820ON = StateREG^0;	          //DS1820是否存在
sbit SetTF = StateREG^1;              //是否是在温度设置状态
sbit KeySETDown = StateREG^2;         //是否已按过SET键标识
sbit PowTF = StateREG^3;              //电源标识
sbit KeyTF = StateREG^4;		    //键盘是否允许

//sbit KeySETDowning = StateREG^5;			//SET是否正在按下
static unsigned char bdata TLV _at_ 0x0029;         //温度变量高低位
static unsigned char bdata THV _at_ 0x0028;
static signed char TMV;       //转换后的温度值
static unsigned char KeyV,TempKeyV;      //键值
static signed char TMRomV _at_ 0x0027;    //高温限制
static signed char TMSetV _at_ 0x0026;    //温度设定值
static unsigned char KSDNum;    //SET键连按时的采集次数
static unsigned char IntNum,IntNum2,IntNum3;    //中断发生次数,IntNum用于SET长按检测,IntNum2用于设定状态时LCD闪烁
static signed char LCD_One,LCD_Two,LCD_Three;  //LCD的显示位 LCD_One为十位,LCD_Two为个位
static signed char LCD_One_set,LCD_Two_set,LCD_Three_set;	//设置时的LCD值
static unsigned char Sign, Sign_Set; //负号标识

void WriteDataLCM(unsigned char WDLCM);
void WriteCommandLCM(unsigned char WCLCM,BuysC);
unsigned char ReadDataLCM(void);
unsigned char ReadStatusLCM(void);
void LCMInit(void);
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData);
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData);
void Delay5Ms(void);
void Delay400Ms(void);

unsigned char code cdle_net[] = {"    WellCome!   "};
unsigned char code email[] = {" Press Power Key"};
unsigned char cur_temper[]={"Current Temp:   "};
unsigned char cur_temper_set[]={"T_Set:          "};
unsigned char BF = 0;	//定时中断标志,=1时显示当前温度值,=0显示欢迎

void main(void)
{
	void InitDS1820(void);   //定义函数
	void ROMDS1820(void);
	void TMVDS1820(void);
	void TMRDS1820(void);
	void TMWDS1820(void);
	void TMREDS1820(void);
	void TMERDS1820(void);
	void ReadDS1820(void);
	void WriteDS1820(void);
	void Delay_510(void);
	void Delay_110(void);
	void Delay_10ms(void);
	void Delay_4s(void);
	void V2ToV(void);

	StateREG = 0;   //初始化变量
	//SetTF = 1;	
	PowTF = 1;			//关电源
	//KeyTF = 1;
	THV = 0;
	TLV = 0;
	TMV = 0;
	KeyV = 0;
	TempKeyV = 0;
	KSDNum = 0;
	IntNum = 0;
	IntNum2 = 0;
	IntNum3 = 0;


	
	InitDS1820(); //初始化
	ROMDS1820(); 	//跳过ROM
	TMERDS1820();  //E2PRAM中温度上限值调入RAM
	InitDS1820(); //初始化
	ROMDS1820(); 	//跳过ROM
	TMRDS1820(); 	//读出温度指令
	ReadDS1820(); //读出温度值和上限值
	TMSetV = TMRomV;  //拷贝保存在DS18B20ROM里的上限值到TMSetV

	Delay400Ms(); //启动等待,等LCM讲入工作状态
	LCMInit(); //LCM初始化
	Delay5Ms(); //延时片刻(可不要)

	EA = 1;					//允许CPU中断
	ET0 = 1; 				//定时器0中断打开
	TMOD = 0x1;			//设定时器0为模式1,16位模式
	TH0=0xB1;
	TL0=0xDF;				//设定时值为20000us(20ms)
	TR0 = 1;				//开始定时

	do
		{
			if (BF==0)
				{
					DisplayListChar(0, 0, cdle_net);	//显示欢迎信息
					DisplayListChar(0, 1, email);
					Delay_4s();
					//PowTF = 1;
					EA=1;
				}
			if (BF==1)
				{
					for (i=0;i<16;i++)
						{
							DisplayOneChar(i,0,cur_temper[i]);//LCD的第1行显示当前温度
						}
					for (i=0;i<16;i++)
						{
							DisplayOneChar(i,1,cur_temper_set[i]);//LCD的第二行显示设置温度和继电器状态
						}
					//ReadDataLCM();//测试用句无意义	
					EA=1;
				}
		}
	while(1);
}

//定时器0中断外理中键扫描和处理要显示的值
void KeyAndDis_Time0(void) interrupt 1 using 2
{
	TH0=0xB1;
	TL0=0xDF;				//设定时值为20000us(20ms)

	if (!Key_UP)	KeyV = 1;
	if (!Key_DOWN)	KeyV = 2;
	if (!Key_SET)	KeyV = 3;
	//KeySETDowning = 0;  //清除
	if (KeyV != 0)      //有键按下
		{
			Delay_10ms();   //延时防抖  按下10ms再测
			if (!Key_UP)	TempKeyV = 1;
			if (!Key_DOWN)	TempKeyV = 2;
			if (!Key_SET)	TempKeyV = 3;

			if (KeyV == TempKeyV)   //两次值相等为确定接下了键
				{
					if (KeyV == 3)      //按下SET键,如在SET状态就退出,否则进入
						{
							//KeySETDowning = 1; //表明SET正在按下
							PowTF = 0;      //电源标识开
							if (!KeyTF)		//KeyTF=0,键盘允许
								if (SetTF)
									{
										SetTF = 0;    //标识位标识退出设定
										InitDS1820(); //初始化
										ROMDS1820(); 	//跳过ROM
										TMWDS1820(); 	//写温度上限指令
										WriteDS1820(); 	//写温度上限到DS18B20ROM
										WriteDS1820(); 	//写温度上限到DS18B20ROM
										WriteDS1820(); 	//写温度上限到DS18B20ROM
										InitDS1820(); //初始化
										ROMDS1820(); 	//跳过ROM
										TMREDS1820(); 	//温度上限值COPY回E2PRAM
										//	V2ToV();
									}
								else
									SetTF = 1;
							if (!KeySETDown) //没有第一次按下SET时,KeySETDown标识置1
								KeySETDown = 1;
							else
								KSDNum = KSDNum + 1;  //前一秒内有按过SET则开始计数
						}
					if (SetTF==1)  //在SET状态下
						{
							cur_temper_set[9]=0x3d;		//"="	显示set标志
							cur_temper_set[10]=0x73;	//"s"
							cur_temper_set[11]=0x65;	//"e"
							cur_temper_set[12]=0x74;	//"t"
							if ((KeyV == 1) && (!KeyTF))
								TMSetV = TMSetV + 1;    //上调温度
							if ((KeyV == 2) && (!KeyTF))
								TMSetV = TMSetV - 1;    //下调温度
							if (TMSetV <= -55)          //限制温度上下限
								TMSetV = -55;
							if (TMSetV >= 125)
								TMSetV = 125;
						}
					if ((!KeyTF) && (IntNum3 == 0))
						{
							KeyTF = 1; //当键盘处于可用时,锁定
							cur_temper_set[9]=0x20;		//	显示空白
							cur_temper_set[10]=0x20;
							cur_temper_set[11]=0x20;
							cur_temper_set[12]=0x20;
						}
				}

				if (KeySETDown)         //在2秒内按下了SET则计中断发生次数用于长按SET时计时用
					IntNum = IntNum + 1;  
				if (IntNum > 55)     //中断发生了55次时(大约1.2秒)75为1.5秒左右
					{
						IntNum = 0;
						KeySETDown = 0;
						if (KSDNum == 55)      //如一直长按了SET1.2秒左右
							{
								RelayOutPort = 1;  //关闭继电器输出
								PowTF = 1;         //电源标识关  
								//Delay_4s();        //延时
								IntNum = 0;
								IntNum2 = 0;
								IntNum3 = 0;
								BF = 0;			//显示欢迎信息		
								EA=0;
							}
						KSDNum = 0;
					}
		}

		KeyV = 0;
		TempKeyV = 0;   //清空变量准备下次键扫描

		if (PowTF==0)
			{
				InitDS1820();	//初始化
				ROMDS1820(); 	//跳过ROM
				TMVDS1820();  //温度转换指令
				Delay_510();
				Delay_510();  //延时等待转换完成
				InitDS1820(); //初始化
				ROMDS1820(); 	//跳过ROM
				TMRDS1820(); 	//读出温度指令
				ReadDS1820(); //读出温度值
				V2ToV();        //转换显示值
				if (TMV > TMSetV)   //根据采集到的温度值控制继电器
					{
						RelayOutPort = 0;
						cur_temper_set[13]=0x20;	//" "
						cur_temper_set[14]=0x4f;	//"O"
						cur_temper_set[15]=0x4e;	//"N"
					}
				else
					{
						RelayOutPort = 1;
						cur_temper_set[13]=0x4f;	//"O"
						cur_temper_set[14]=0x46;	//"F"
						cur_temper_set[15]=0x46;	//"F"
					}

				if (SetTF)	IntNum2 = IntNum2 + 1; //用于闪烁计数
				if (IntNum2 > 50 )	IntNum2 = 0;
				if (KeyTF) IntNum3 = IntNum3 + 1; //用于防止按键连按
				if (IntNum3 > 25) 
					{
						IntNum3 = 0;
						KeyTF = 0;
					}
				if ((SetTF) && (IntNum2 < 25)) goto InitEnd;  //计数在后半段时显示
				BF=1;	//让显示温度值
				EA=0;	//关中断
			}
			InitEnd:;
}



void V2ToV(void)	//数值转换
{
	TLV = TLV >> 4;			
	THV = THV << 4;			//读出的高低位数值移位
	TMV = TLV | THV;		//合并高低位放入TM为实际温度值
	Sign = 0; Sign_Set=0;
    Sign_Set = TMSetV >> 7;          //取符号
    Sign = TMV >> 7;

	if (Sign)
		{
    		LCD_One = (~TMV) / 100;							//转换百位值		
    		LCD_Two = ((~TMV) - LCD_One * 100)/10;
			LCD_Three = (~TMV) - LCD_One * 100 - LCD_Two * 10;
		}
	else
		{
			LCD_One = (TMV) / 100;							//转换百位值		
    		LCD_Two = (TMV - LCD_One * 100)/10;
			LCD_Three = TMV - LCD_One * 100 - LCD_Two * 10;
		}

	if (Sign_Set)
		{
    		LCD_One_set = (~(TMSetV-1)) / 100;          //SET状态下显示设定值
    		LCD_Two_set = ((~(TMSetV-1)) - LCD_One_set * 100)/10;
			LCD_Three_set = (~(TMSetV-1)) - LCD_One_set * 100 - LCD_Two_set * 10;
		}
	else
		{
			LCD_One_set = (TMSetV) / 100;          //SET状态下显示设定值
    		LCD_Two_set = (TMSetV - LCD_One_set * 100)/10;
			LCD_Three_set = TMSetV - LCD_One_set * 100 - LCD_Two_set * 10;
		}

//转LCD字段  温度值	
	if (LCD_One) //超过百时十位的处理
		LCD_Two = LCDDis[LCD_Two];		
	else
		{
			if (LCD_Two == 0)
				LCD_Two = LCDDis[10];
			else
				LCD_Two = LCDDis[LCD_Two];
		}
	if (Sign)
		LCD_One = LCDDis[11];
	else
		{
			if (LCD_One == 0)
				LCD_One = LCDDis[10];
			else
				LCD_One = LCDDis[LCD_One];
		}
	LCD_Three = LCDDis[LCD_Three];


				cur_temper[13]=LCD_One;		//把温度值的ASCII码放入cur_temper的13,14,15位
				cur_temper[14]=LCD_Two;		
				cur_temper[15]=LCD_Three;	


//转LCD字段  设置值	
	if (LCD_One_set) //超过百时十位的处理
		LCD_Two_set = LCDDis[LCD_Two_set];		
	else
		{
			if (LCD_Two_set == 0)
				LCD_Two_set = LCDDis[10];
			else
				LCD_Two_set = LCDDis[LCD_Two_set];
		}
	if (Sign_Set)
		LCD_One_set = LCDDis[11];
	else
		{
			if (LCD_One_set == 0)
				LCD_One_set = LCDDis[10];
			else
				LCD_One_set = LCDDis[LCD_One_set];
		}
	LCD_Three_set = LCDDis[LCD_Three_set];

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -