奇迹飞翔 发表于 2023-12-20 16:12

51单片机驱动空气传感器显示在lcd

#include<reg52.h>
#include<intrins.h>
#define LCD1602_DBP0//LCD数据收发8位并行口
bit flag1s = 0;
bit state=0;
bit temp=0;//数据更新位定义

sbit clk=P1^2;
sbit dout=P1^0;
sbit cs=P1^1;
sbit LCD1602_RS = P2^6;
sbit LCD1602_RW = P2^5;
sbit LCD1602_E= P2^7;//LCD控制接口
sbit IO_18B20 = P3^7;//温度传感器接口
sbit beep=P3^6;//蜂鸣器控制接口

sbit key1=P2^0;

unsigned int flag,time=1,temper=0,result=0,xinlv=0,num=0,water=0,sulv=0;//数据更新时间计数值

//unsigned char IntToString(unsigned char *str, int dat);
void ShowDistance();
void InitLcd1602();

void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);
bit Get18B20Temp(int *temp);
bit Start18B20();//函数声明
void DelayX10us(unsigned char t)//us级别延时
{
    do {
      _nop_();
      _nop_();
      _nop_();
      _nop_();
      _nop_();
      _nop_();
      _nop_();
      _nop_();
    } while (--t);
}
void delayms(unsigned int ms)//ms级别延时
{
    unsigned int i;
    for(i=0;i<123*ms;i++);
}
void keyscan()//按键读取
{
    if(key1==0)
    {
      key1=1;
      delayms(50); //消抖
      if(key1==0)
      {
            water++;//判断是否计数
      }
    }

}
unsigned char TLC549_ADC()
{
    unsigned char i,adc;
    clk=0;
    cs=0;
    for(i=0;i<8;i++)
    {
      adc<<=1;
      adc|=dout;
      clk=1;
      clk=0;
    }
    cs=1;
    delayms(1);
    return adc;
}
void main()
{
    bit res;                  
    int temp;      
    int intT, decT;
    unsigned char len,co2;//变量定义
    unsigned char t,display,sudu;
    unsigned char name[]="T:";//初始显示内容
    unsigned char CO2[]="CO2:";//初始显示内容
    unsigned char water[]="W:";
    EA = 1;         
    TMOD=0x01;   
    TH0 = 0xFC;      
    TL0 = 0x18;
    ET0 = 1;         
    TR0 = 1;//定时器0初始化      
    EX1=1;//定时器1中断初始化      
    IT1 = 1;         
    InitLcd1602();
    Start18B20();//传感器初始化
    LcdShowStr(0,1,name);
    LcdShowStr(8,1,CO2);
    LcdShowStr(11,0,water);
    beep=0;
    len=0;         
    while(1)
    {   
      co2=TLC549_ADC();
      display=co2*195/10000+'0';
      display='.';
      display=co2*195%10000/1000+'0';
      display=co2*195%1000/100+'0';
      display='\0';
      keyscan();//读取按键值
      if(flag == 1) //每过100ms更新
      {    flag = 0;
            ShowDistance();
      }
      if(state == 1) //每过100ms更新
      {    state = 0;
            LcdShowStr(12,1,display);
      }
      if (flag1s)//每过100ms更新温度值
      {   
            flag1s = 0;
            res = Get18B20Temp(&temp);
            if (res)                  
            {    intT = temp >> 4;            
                decT = temp & 0xF;                  
                decT = (decT*10) / 16;      
            }
            Start18B20();
      }
      t =intT/100+'0';   
      t =(intT/10)%10+'0';                  
      t =intT%10+'0';
      t ='.';
      t =decT/10+'0';   

      t = '\0';            
      LcdShowStr(2,1, t);//动态显示温度

      sudu=sulv/10+'0';
      sudu=sulv%10+'0';
      sudu='\0';
      LcdShowStr(13,0,sudu);
      if(temp)//每过100ms判断温度是否超过设定温度
      {
            temp=0;
            if(intT>=38||xinlv>=100||xinlv<=50||sulv<=40||sulv>=80||(co2*195/10000)>=2)
            {
                beep=1;
            }
            else
            {
               beep=0;
            }
               
      }
   
    }
}
void Interrupt1() interrupt 2
{
    time++;
}
void InterruptTimer0() interrupt 1
{
    static unsigned int cnt = 0;   
    static unsigned char tmr1s = 0;
    TH0 = 0xFC;      
    TL0 = 0x18;
    temper++;
    if(temper>=100)//数据更新时间计数值
    {
      temper=0;
      temp=1;
      state=1;
    }
    cnt++;
    if(cnt >=1000)//数据更新时间计数值   
    {
      cnt = 0;   
      flag = 1;
      //time=time+1;
      num++;
      xinlv=result*60/num;
      result=time;
      sulv=water*60/num;
    }
    tmr1s++;
    if (tmr1s >= 100)//数据更新时间计数值
    {
      tmr1s = 0;
      flag1s = 1;
    }
   
}
void ShowDistance()   
{
    unsigned char buff;
    unsigned int Distance ;
    Distance=xinlv;
   
    buff = Distance%10 + '0';
    buff = (Distance/10)%10 + '0';
    buff = Distance/100 + '0';    //在lcd上显示
   
    LcdShowStr(0, 0, "HR:");
    LcdShowStr(3, 0, &buff);
    LcdShowStr(6, 0, "/min");
}

/*unsigned char IntToString(unsigned char *str, int dat) //数据格式转换
{
    signed char i = 0;
    unsigned char len = 0;
    unsigned char buf;
   
    if (dat < 0)
    {
      dat = -dat;
      *str++ = '-';
      len++;
    }
    do {         
      buf = dat % 10;
      dat /= 10;
    } while (dat > 0);
    len += i;   
    while (i-- > 0)   
    {
      *str++ = buf + '0';
    }
    *str = '\0';
   
    return len;   
}*/
bit Get18B20Ack() //温度传感器时钟应答判断是否连接
{
    bit ack;
   
    EA = 0;   
    IO_18B20 = 0;
    DelayX10us(50);
    IO_18B20 = 1;
    DelayX10us(6);   
    ack = IO_18B20;   
    while(!IO_18B20);
    EA = 1;
   
    return ack;
}
void Write18B20(unsigned char dat)//写命令
{
    unsigned char mask;
   
    EA = 0;   
    for (mask=0x01; mask!=0; mask<<=1)
    {
      IO_18B20 = 0;         
      _nop_();
      _nop_();
      if ((mask&dat) == 0)
            IO_18B20 = 0;
      else
            IO_18B20 = 1;
      DelayX10us(6);      
      IO_18B20 = 1;      
    }
    EA = 1;
}
unsigned char Read18B20()//读温度数据
{
    unsigned char dat;
    unsigned char mask;
   
    EA = 0;   
    for (mask=0x01; mask!=0; mask<<=1)
    {
      IO_18B20 = 0;         
      _nop_();
      _nop_();
      IO_18B20 = 1;      
      _nop_();            
      _nop_();
      if (!IO_18B20)      
            dat &= ~mask;
      else
            dat |= mask;
      DelayX10us(6);      
    }
    EA = 1;

    return dat;
}
bit Start18B20()//起始时钟
{
    bit ack;
   
    ack = Get18B20Ack();   
    if (ack == 0)         
    {
      Write18B20(0xCC);
      Write18B20(0x44);
    }
    return ~ack;   
}
bit Get18B20Temp(int *temp)//温度数据转换为十进制
{
    bit ack;
    unsigned char LSB, MSB;
   
    ack = Get18B20Ack();   
    if (ack == 0)         
    {
      Write18B20(0xCC);   
      Write18B20(0xBE);
      LSB = Read18B20();
      MSB = Read18B20();
      *temp = ((int)MSB << 8) + LSB;
    }
    return ~ack;
}

void LcdWaitReady()//lcd初始化函数
{
    unsigned char sta;
   
    LCD1602_DB = 0xFF;
    LCD1602_RS = 0;
    LCD1602_RW = 1;
    do {
      LCD1602_E = 1;
      sta = LCD1602_DB;
      LCD1602_E = 0;
    } while (sta & 0x80);
}

void LcdWriteCmd(unsigned char cmd)    //lcd写命令函数
{
    LcdWaitReady();
    LCD1602_RS = 0;
    LCD1602_RW = 0;
    LCD1602_DB = cmd;
    LCD1602_E= 1;
    LCD1602_E= 0;
}

void LcdWriteDat(unsigned char dat)//lcd写数据函数
{
    LcdWaitReady();
    LCD1602_RS = 1;
    LCD1602_RW = 0;
    LCD1602_DB = dat;
    LCD1602_E= 1;
    LCD1602_E= 0;
}

void LcdSetCursor(unsigned char x, unsigned char y)//设置光标
{
    unsigned char addr;
   
    if (y == 0)
    {
      addr = 0x00 + x;
    }
    else
    {
      addr = 0x40 + x;
    }
    LcdWriteCmd(addr | 0x80);
}
void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str)//lcd显示字符串
{
    LcdSetCursor(x, y);   
    while (*str != '\0')
    {
      LcdWriteDat(*str++);
    }
}


void InitLcd1602()//lcd初始化
{
    LcdWriteCmd(0x38);
    LcdWriteCmd(0x0C);
    LcdWriteCmd(0x06);
    LcdWriteCmd(0x01);
}

敏行 发表于 2023-12-20 17:01

longxuekai 发表于 2023-12-21 06:17

来看看吧看吧

chinachen 发表于 2023-12-21 08:45

声声 发表于 2023-12-21 08:57

学习

techlink81 发表于 2023-12-21 08:58

ize 发表于 2023-12-21 09:29

linyuwen 发表于 2023-12-22 08:56

页: [1]
查看完整版本: 51单片机驱动空气传感器显示在lcd