1. 头文件及相关定义

#include<reg52.h>
int write_com(unsigned char);//声明写命令函数
int write_date(unsigned char);

sbit RS = P2^0;
sbit RW = P2^1;
sbit EN = P2^2;
sbit TRH = P3^2;//温湿度传感器DHT11数据接入
sbit key1=P1^0;
sbit key2=P1^1;
sbit key3=P1^2;
sbit key4=P1^3;
sbit sp=P3^7;
sbit led1=P3^3;
sbit led2=P3^4;
sbit led3=P3^5;
sbit led4=P3^6;

sbit SDO=P2^3;							//定AD芯片端口义端口
sbit SDI=P2^4;
sbit CS=P2^5;
sbit CLK=P2^6;
sbit EOC=P2^7;


sbit relay1=P1^4;
sbit relay2=P1^5;
sbit relay3=P1^6;
sbit relay4=P1^7;


unsigned char code table[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x2e,0x00};
unsigned char code table2[6]='Temp: ';
unsigned char code table3[6]='Humi: ';
unsigned char code table4[6]='Dust: ';
unsigned char code table5[6]='SF6:  ';
unsigned char code table6[6]='TH:   ';
unsigned char code table7[6]='HL:   ';
unsigned char code table8[6]='DH:   ';
unsigned char code table9[6]='SH:   ';
unsigned char code table10[6]='mg/m3 ';
unsigned char code table11[6]='ppm   ';
unsigned char str;
unsigned char DHT11[5],RTflag=0;
unsigned char  FLAG;   //超时标志位
unsigned char m,r,r2,a,th1,th2,rh1,rh2,q,zs,kz1,kz2,kz3,set_fg;
int k1=40,k2=75,k3=50,k4=1000;
unsigned int dust,sf6,ad1,ad2;

bit y1,y2,y3;

  • #include<reg52.h>: 包含了单片机8051的寄存器定义文件,方便使用单片机的各种寄存器。
  • int write_com(unsigned char);int write_date(unsigned char);: 声明了两个函数,分别用于向LCD显示器写入命令和数据。
  • sbit 定义: 使用sbit关键字定义了各个端口的引脚,用于控制LCD显示器、按键、继电器、LED灯、温湿度传感器等外围设备。
  • unsigned char code table[]: 定义了一个字符数组,用于存放数字和'.'的ASCII码,方便将数值转换为字符显示。
  • unsigned char code table2[]-table11[]: 定义了几个字符串数组,用于存放LCD显示器需要显示的文字信息。
  • unsigned char str: 定义了一个无符号字符变量,用于存放字符串。
  • unsigned char DHT11[5],RTflag=0: 定义了一个数组用于存放DHT11传感器读取的5个字节数据,其中RTflag为数据校验标志位。
  • unsigned char FLAG: 定义了一个无符号字符变量,用于存放超时标志位。
  • unsigned char m,r,r2,a,th1,th2,rh1,rh2,q,zs,kz1,kz2,kz3,set_fg: 定义了一系列无符号字符变量,用于存储不同的数据信息。
  • int k1=40,k2=75,k3=50,k4=1000: 定义了4个整型变量,用于存放各个传感器设置的阈值。
  • unsigned int dust,sf6,ad1,ad2: 定义了4个无符号整型变量,用于存放粉尘浓度、SF6气体浓度和AD芯片读取的数值。
  • bit y1,y2,y3: 定义了3个位变量,用于存放一些控制状态。

2. 延时函数

void delay (unsigned int xms)
{
	unsigned int i,j;
	for(i=xms;i>0;i--)
	 for(j=110;j>0;j--);
}

void  delay_10us() //10us延时函数
{
        unsigned char i;
         i--;
         i--;
         i--;
         i--;
         i--;
 //        i--;
}

void Delay_t(unsigned int j)
{      unsigned char i;
	    for(;j>0;j--)
	  { 	
		for(i=0;i<27;i++);	
	  }
}
  • delay(unsigned int xms): 这是一个通用的延时函数,根据输入的参数xms,实现毫秒级的延时。
  • delay_10us(): 这是一个10微秒的延时函数。
  • Delay_t(unsigned int j): 这是一个自定义的延时函数,用于控制DHT11传感器的数据读取过程。

3. 字节转字符串函数

typedef unsigned char BYTE;
BYTE *ByteToStr(BYTE n)
{
BYTE str[4];
BYTE * pStr;
pStr = str;
if (n>99)
{
*pStr = n/100;
n %= 100;
*pStr += '0';
pStr ++ ;
*pStr = n/10;
n%=10;
*pStr +='0';
pStr ++ ;
}
if (n>9)
{
*pStr = n/10;
n %= 10;
*pStr += '0';
pStr++ ;
}
if (n<10)
{
*pStr = n+'0';
pStr++;
}
*pStr = 0;
return str;
}
  • ByteToStr(BYTE n): 该函数用于将一个字节的数值转换为字符串,以便于显示。

4. 发送字符串函数

void send(char *dis) 
{ 
    while(*dis!='�') { 
        SBUF=*dis; 
        dis++;  
        while(!TI); 
        TI=0; //软件请发送中断 
    } 
} 
  • send(char *dis): 该函数用于通过串口发送字符串。

5. 读取AD芯片函数

unsigned int read2543(unsigned char con_word)
{
  unsigned int ad=0,i;
  CLK=0;								//时钟首先置低
  CS=0;						  			//片选为0,芯片工作
  for(i=0;i<12;i++)				  
  {
    if(SDO)					  			//首先读TLC2543的一位数据
	 ad=ad|0x01;
	 SDI=(bit)(con_word&0x80);			//向TLC2543写一位数据
	 CLK=1;					  			//时钟上升沿,TLC2543输出使能
	 delay(3);
	 CLK=0;					  			//时钟下降沿,TLC2543输入使能
	 delay(3);
	 con_word<<=1;
	 ad<<=1;
   }
   CS=1;
   ad>>=1;
   return(ad);
}
  • read2543(unsigned char con_word): 该函数用于读取TLC2543 AD芯片的数值。

6. AD值转换函数

void volt_result()	  //AD值转温度
{

ad1=read2543(0x00);
ad2=read2543(0x10);

dust=ad1*(100.0/4096);	
sf6=ad2*(2000.0/4096);	
}
  • volt_result(): 该函数用于将读取的AD值转换为粉尘浓度和SF6气体浓度。

7. LCD初始化函数

int init()//初始化函数体
{
    EN = 0;
    write_com(0X38);//设置16*2显示,5*7点阵,8位数据接口
    write_com(0X0C);//设置开显示,不显示光标
    write_com(0X06);//写一个字符时,整屏右移
    write_com(0X01);//显示清零
    return 0;
}
  • init(): 该函数用于初始化LCD显示器。

8. LCD写命令函数

int write_com(unsigned char com)//写命令的函数体
{
    RS = 0;
    RW = 0;
    P0 = com;
    delay(5);
    EN = 1;
    delay(5);
    EN = 0;
    return 0;        
}
  • write_com(unsigned char com): 该函数用于向LCD显示器写入命令。

9. LCD写数据函数

int write_date(unsigned char TRHe)//写数据的函数体
{
    RS = 1;
    RW = 0;
    P0 = TRHe;
    delay(5);
    EN = 1;
    delay(5);
    EN = 0;
    return 0;        
}
  • write_date(unsigned char TRHe): 该函数用于向LCD显示器写入数据。

10. 读取DHT11数据函数

unsigned char write_byte1() //读一个字节
{
	  unsigned char i,comdata,temp1;
       for(i=0;i<8;i++)	   
	    {
	   	    FLAG=2;	
	   	while((!TRH)&&FLAG++);//判断数据位是0还是1
			delay_10us();
		    delay_10us();
			delay_10us();
	  		temp1=0;
	     if(TRH)temp1=1;	// 如果高电平高过预定0高电平值则数据位为 1 
		    FLAG=2;
		 while((TRH)&&FLAG++);//flag先与后加1 如果dat一直为1   uchar型变量 flag  溢出变为0  再自加1  
	   	  
	   	 if(FLAG==1)break;		//超时则跳出for循环	
	   		 
	   	   
	
		   comdata<<=1;//左移一位   高位在前  低位在后
	   	   comdata|=temp1;
	     }
		 return (comdata);  
}

void DHT11_5() //读5个字节数据  两个字节为温度数据  两个字节为湿度数据 最后一个字节为校验
{
	  unsigned char i,temp;
	  //主机拉低18ms 
       TRH=0;
	   Delay_t(180);
	   TRH=1;
	 //总线由上拉电阻拉高 主机延时20us
	   delay_10us();
	   delay_10us();
	   delay_10us();
	   delay_10us();
	 //主机设为输入 判断从机响应信号 
	   TRH=1;
	 //判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行	  
	   if(!TRH)		 //T !	  
	   {
		FLAG=2;	   //超时标志位
				 
		while((!TRH)&&FLAG++);//判断从机是否发出 80us 的低电平响应信号是否结束
			FLAG=2;
		ET0=0;	
		while((TRH)&&FLAG++); //判断从机拉高80us是否结束
			for(i=0;i<5;i++)//数据接收状态
			{
				DHT11[i]=write_byte1();	
			}		 
			TRH=1;	//释放数据总线  为下一次读取做好准备 
		 
			temp=(DHT11[0]+DHT11[1]+DHT11[2]+DHT11[3]);
			if(temp==DHT11[4])	//数据校验 	
			{	  	   	  
				RTflag=1;		  
			}
			if(RTflag==1) //如果RTflag=1 说明读取到得数据正确
		   {	  			
				RTflag=0;
		
		  		rh1=DHT11[0]/10;
				rh2=DHT11[0]%10;

				th1=DHT11[2]/10;
				th2=DHT11[2]%10;
			   ET0=1;
		  
		   }

		}

}	 	  
  • write_byte1(): 该函数用于读取DHT11传感器的一个字节数据。
  • DHT11_5(): 该函数用于读取DHT11传感器5个字节数据,并进行数据校验。

11. LCD显示函数

void display()
	{
		unsigned char i;


if(m==0)
{
if(set_fg==0)
{
	write_com(0x80);
   for(i=0;i<6;i++)
	 	write_date(table2[i]);	
		write_date(table[th1]);
		write_date(table[th2]);
		write_date(0xdf);
		write_date('C');
    for(i=0;i<8;i++)
	 	write_date(' ');

		write_com(0xc0);
   for(i=0;i<6;i++)
	 	write_date(table3[i]);	
		write_date(table[rh1]);
		write_date(table[rh2]);
		write_date('%');
	  for(i=0;i<8;i++)
	 	write_date(' ');
}
else
{

	write_com(0x80);
   for(i=0;i<6;i++)
	 	write_date(table6[i]);	
		write_date(table[k1/10]);
		write_date(table[k1%10]);
	  for(i=0;i<8;i++)
	 	write_date(' ');
	
		
	 write_com(0xc0);
   for(i=0;i<6;i++)
	 	write_date(table7[i]);	
		write_date(table[k2/10]);
		write_date(table[k2%10]);
	  for(i=0;i<8;i++)
	 	write_date(' ');	
}
}
if(m==1)
{
if(set_fg==0)
{
	write_com(0x80);
   for(i=0;i<6;i++)
	 	write_date(table4[i]);	
		write_date(table[dust/100]);
		write_date(table[dust%100/10]);
	  write_date('.'); 
    write_date(table[dust%10]);
    for(i=0;i<6;i++)
	 	write_date(table10[i]);


		write_com(0xc0);
   for(i=0;i<6;i++)
	 	write_date(table5[i]);
		write_date(table[sf6/1000]);	
		write_date(table[sf6%1000/100]);
		write_date(table[sf6%100/10]); 
    write_date(table[sf6%10]);
    for(i=0;i<6;i++)
	 	write_date(table11[i]);
}
else
{

	write_com(0x80);
   for(i=0;i<6;i++)
	 	write_date(table8[i]);	
    if(k3/100==0)write_date(' ');
    else write_date(table[k3/100]);
		write_date(table[k3%100/10]);
	  write_date('.'); 
		write_date(table[k3%10]);
    for(i=0;i<8;i++)
	 	write_date(' ');

		write_com(0xc0);
   for(i=0;i<6;i++)
	 	write_date(table9[i]);	
    write_date(table[k4/1000]);
		write_date(table[k4%1000/100]);	
		write_date(table[k4%100/10]);
		write_date(table[k4%10]);
    for(i=0;i<8;i++)
	 	write_date(' ');	
}

}


	}	  
  • display(): 该函数用于控制LCD显示器显示不同的数据信息,包括温湿度、粉尘浓度、SF6气体浓度、报警阈值等。

12. 按键处理函数

 void keys()
	{
	 if(key1==0)
	{
	while(!key1);
	m=!m;
	set_fg=0;	
	}

	 if(key2==0)
	{
	while(!key2);
	if(m==0)
	{
		if(set_fg==1)k1++;
		if(set_fg==2)k2++;
	}
	if(m==1)
	{
		if(set_fg==1)k3++;
		if(set_fg==2)k4=k4+100;
	}
	
	}
	
	 if(key3==0)
	{
	while(!key3);
	if(m==0)
	{
		if(set_fg==1)k1--;
		if(set_fg==2)k2--;
	}
	if(m==1)
	{
		if(set_fg==1)k3--;
		if(set_fg==2)k4=k4-100;
	}
	}
	
	 if(key4==0)
	{
	while(!key4);
	set_fg++;
	if(set_fg>2)set_fg=0;	
	}
	
	  if(k1>50)k1=50;	
	  if(k1<0)k1=0;		

	  if(k2>90)k2=90;	
	  if(k2<0)k2=0;		

	  if(k3>100)k3=100;	
	  if(k3<0)k3=0;		

	  if(k4>2000)k4=2000;	
	  if(k4<0)k4=0;		
	}
  • keys(): 该函数用于处理按键的输入,实现对LCD显示内容的切换和对报警阈值的调节。

13. 环境参数判断函数

void temp()
{
 if(th1*10+th2>=k1)
 {
	 led1=0;
	 relay1=0;
 }
 else
 {
	 led1=1;
	 relay1=1;
 }

 if(rh1*10+rh2>=k2)
 {
	 led2=0;
	 relay2=0;
 } 
 else
 {
	 led2=1;
	 relay2=1;
 } 

 if(dust>=k3)
 {
	 led3=0;
	 relay3=0;
 }
 else
 {
	 led3=1;
	 relay3=1;
 } 

 if(sf6>=k4)
 {
	 led4=0;
	 relay4=0;
 }
 else
 {
	 led4=1;
	 relay4=1;
 } 

 if((th1*10+th2<k1)&&(rh1*10+rh2<k2)&&(dust<k3)&&(sf6<k4))sp=1;
 else sp=0;
 
}
  • temp(): 该函数用于判断各个环境参数是否超过设定的报警阈值,并控制对应的LED灯和继电器,实现报警功能。

14. 串口初始化函数

	void t0_init()
	{
	TMOD=0x20;
//	SCON=0x50;
//	PCON=0X80;
	TH1=0xfd;  
    TL1=0xfd; //装入初值 
    TR1=1;//计时中断允许 
    SM0=0; 
    SM1=1;//串行口工作于方式2 
    ES=1;//串行口中断允许 
    REN=1;//接收允许 
    EA=1;// 总中断允许 
	RI=1;
	}
  • t0_init(): 该函数用于初始化串口,用于接收来自上位机的控制指令。

15. 串口发送数据函数

void serial()
{

send('T');
send(ByteToStr(th1));
send(ByteToStr(th2));
send('H');
send(ByteToStr(rh1));
send(ByteToStr(rh2));
send('D');
send(ByteToStr(dust/100));
send(ByteToStr(dust%100/10));
send('.');	
send(ByteToStr(dust%10));		
send('S');	
send(ByteToStr(sf6/1000));
send(ByteToStr(sf6%1000/100));
send(ByteToStr(sf6%100/10));
send(ByteToStr(sf6%10));
	
send('l');
send(ByteToStr(k1/10));
send(ByteToStr(k1%10));
send('m');
send(ByteToStr(k2/10));
send(ByteToStr(k2%10));
send('n');
send(ByteToStr(k3/100));
send(ByteToStr(k3%100/10));
send('.');	
send(ByteToStr(k3%10));
send('o');		
send(ByteToStr(k4/1000));
send(ByteToStr(k4%1000/100));
send(ByteToStr(k4%100/10));
send(ByteToStr(k4%10));

}
  • serial(): 该函数用于通过串口发送各种数据信息,包括温湿度、粉尘浓度、SF6气体浓度和报警阈值等。

16. 串口中断函数

void serial_INT() interrupt 4
{
unsigned char c;

if(RI)
ES=0;
RI=0;

c=SBUF;
if(c=='1')
{
	m=!m;
	set_fg=0;	
}

if(c=='+')
{
	if(m==0)
	{
		if(set_fg==1)k1++;
		if(set_fg==2)k2++;
	}
	if(m==1)
	{
		if(set_fg==1)k3++;
		if(set_fg==2)k4=k4+100;
	}	
}

if(c=='-')
{
	if(m==0)
	{
		if(set_fg==1)k1--;
		if(set_fg==2)k2--;
	}
	if(m==1)
	{
		if(set_fg==1)k3--;
		if(set_fg==2)k4=k4-100;
	}	
}

if(c=='2')
{
	set_fg++;
	if(set_fg>2)set_fg=0;		
}

ES=1;
}
  • serial_INT(): 该函数用于处理串口中断,接收来自上位机的控制指令,并对相应的参数进行调整。

17. 主函数

 void main() 
 { 
    t0_init();
	init();
	while(1)
 {	 	   
	 serial();
   write_byte1();
   DHT11_5();
   keys();
   display();
	 volt_result();
   temp();
 }			            
 }   
  • main(): 该函数是程序的入口,用于初始化相关硬件和软件,并进入循环,不断地读取传感器数据、处理按键输入、更新LCD显示、发送数据到上位机等。

原文地址: https://www.cveoy.top/t/topic/nDeu 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录