找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1816|回复: 4
打印 上一主题 下一主题
收起左侧

[求助]用8591单片机采集环境温度湿度,并在lcd1602显示

[复制链接]
跳转到指定楼层
楼主
ID:943129 发表于 2021-6-23 13:31 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
要求:在1602上显示某一变量的数值,正常范围,并判断当前状态
如:t:50            60
      comfort         40
表示当前温度为50,正常温度为40-60,当前温度正常

红绿字为自己添加的代码,代码可通过keil编译,但在单片机上无法正常显示。如果将绿字部分注释掉单片机就可以正常运行实现功能
**********************************************************************************
* 【函数功能】: DA-AD试验                                                      
* 【使用说明】: 单片机:STC89C52
                 串口波特率:9600
                 串口一共发送4个字节  
                 1 光敏电阻
                 2 热敏电阻
                 3 悬空
                 4 可调0-5V电压(蓝色电位器调节)
                 
**********************************************************************************/
/********************************************************************************************/

#include<reg52.h>    //包含单片机寄存器的头文件
#include <I2C.H>

#define uchar unsigned char
#define  PCF8591 0x90    //PCF8591 地址

/********IO引脚定义***********************************************************/
sbit LCD_RS=P1^0;//定义引脚
sbit LCD_RW=P1^1;
sbit LCD_E=P1^2;

/********宏定义***********************************************************/
#define LCD_Data P0
#define Busy    0x80 //用于检测LCD状态字中的Busy标识

/********数据定义*************************************************************/
unsigned char code uctech[] = {"Thank"};
unsigned char code net[] = {"you!"};
unsigned char code clear[] = {"               "};
unsigned char code net1[] = {"t:"};
unsigned char code net2[] = {"l:"};
unsigned char code net3[] = {"v:"};
unsigned char t;
//温度
uchar code limit[]={"60"};
uchar code limit1[]={"40"};
unsigned char code condition[]={"too hot"};
uchar code condition1[]={"comfort"};
uchar code condition2[]={"too cold"};

//光
uchar code limit2[]={"100"};
uchar code limit3[]={"60"};
unsigned char code condition3[]={"too bright"};
uchar code condition4[]={"comfort"};
uchar code condition5[]={"too dim"};
//电压
uchar code limit4[]={"200"};
uchar code limit5[]={"100"};
unsigned char code condition6[]={"too big"};
uchar code condition7[]={"comfort"};
uchar code condition8[]={"too small"};

// 变量定义
unsigned char AD_CHANNEL;
unsigned long xdata  LedOut[8];
unsigned int  D[32];
sbit P2_0 = P2^0;
sbit P2_1 = P2^1;
sbit P2_2 = P2^2;
sbit P2_3 = P2^3;
unsigned char data a;


//按钮
sbit K1=P3^7;
sbit K2=P3^6;
sbit K3=P3^5;
sbit K4=P3^4;


//unsigned char date ;

/*uchar code table[]={0xC0,0xF9,0xA4,0xB0,
                            0x99,0x92,0x82,0xF8,
                            0x80,0x90,0x88,0x83,
                            0xC6,0xA1,0x86,0x8E};     */


  // 函数申明
//void delay(uchar i);
bit DACconversion(unsigned char sla,unsigned char c,  unsigned char Val);
bit ISendByte(unsigned char sla,unsigned char c);
unsigned char IRcvByte(unsigned char sla);
void Initial_com(void);
void WriteDataLCD(unsigned char WDLCD);                    //写数据
void WriteCommandLCD(unsigned char WCLCD,BuysC);        //写命令
unsigned char ReadDataLCD(void);                        //读数据
unsigned char ReadStatusLCD(void);                        //读状态
void LCDInit(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);                                    //延时
//******************************************************************/
/*void delay_1ms()
{
    unsigned char temp=249;
    while(--temp);
    temp=249;
    while(--temp);
}      */
main()
{  

    Initial_com();
    Delay400Ms();     //启动等待,等LCD讲入工作状态
    LCDInit();         //初始化
    Delay5Ms();     //延时片刻(可不要)
    DisplayListChar(0, 1, uctech);
    ReadDataLCD();
    while(1)
    {

    /********以下AD-DA处理*************/  
   
        switch(AD_CHANNEL)
        {
            case 0: ISendByte(PCF8591,0x41);
                 D[0]=IRcvByte(PCF8591);  //ADC0 模数转换1      电压
                 break;  
            
            case 1: ISendByte(PCF8591,0x42);
                 D[1]=IRcvByte(PCF8591);  //ADC1  模数转换2      光
                 break;  
            
            case 2: ISendByte(PCF8591,0x43);
                 D[2]=IRcvByte(PCF8591);  //ADC2    模数转换3       温度
                 break;  
            
            case 3: ISendByte(PCF8591,0x40);
                 D[3]=IRcvByte(PCF8591);  //ADC3   模数转换4       可调0-5v
                 break;  
            
            case 4: DACconversion(PCF8591,0x40, D[4]); //DAC      数模转换
                 break;
         
        }
        D[4]=D[3];  //把模拟输入采样的信号 通过数模转换输出
        if(K1==0)
         {
            a=1;
            DisplayListChar(0, 1, clear);
            DisplayListChar(0, 0, clear);
            DisplayListChar(14, 0, limit);
            DisplayListChar(14, 1, limit1);   
         }
         if(K2==0)
         {
             a=2;  //0
            DisplayListChar(0, 1, clear);
            DisplayListChar(0, 0, clear);
            DisplayListChar(14, 0, limit2);
            DisplayListChar(14, 1, limit3);

         }
         if(K3==0)
         {
             a=3;    //1
            DisplayListChar(0, 1, clear);
            DisplayListChar(0, 0, clear);
            DisplayListChar(14, 0, limit4);
            DisplayListChar(14, 1, limit5);;

         }
         if(K4==0)
         {
             a=4;    //1
            DisplayListChar(0, 1, clear);
            DisplayListChar(0, 0, clear);
         }
        if(a==1)
        {
        
             DisplayListChar(0, 0, net1);
             DisplayOneChar(2, 0,D[2]/100+0x30);
             DisplayOneChar(3, 0,D[2]%100/10+0x30);
             DisplayOneChar(4, 0,D[2]%10+0x30);
             if(D[2]>60)
             {
                   DisplayListChar(0, 1, condition);
             }
             if(D[2]<40)
             {
                   DisplayListChar(0, 1, condition2);
             }
             else
             {
                   DisplayListChar(0, 1, condition1);
             }


        }
        if(a==2)
        {
            
             DisplayListChar(0, 0, net2);
             DisplayOneChar(2, 0,D[1]/100+0x30);
             DisplayOneChar(3, 0,D[1]%100/10+0x30);
             DisplayOneChar(4, 0,D[1]%10+0x30);
             if(D[1]>100)
             {
                   DisplayListChar(0, 1, condition3);
             }
             if(D[1]<60)
             {
                   DisplayListChar(0, 1, condition5);
             }
             else
             {
                   DisplayListChar(0, 1, condition4);
             }

        }
        if(a==3)
        {     
             DisplayListChar(0, 0, net3);
             DisplayOneChar(2, 0,D[0]/100+0x30);
             DisplayOneChar(3, 0,D[0]%100/10+0x30);
             DisplayOneChar(4, 0,D[0]%10+0x30);
             if(D[0]>200)
             {
                   DisplayListChar(0, 1, condition6);
             }
             if(D[0]<100)
             {
                   DisplayListChar(0, 1, condition8);
             }
             else
             {
                   DisplayListChar(0, 1, condition7);
             }

        }
        if(a==4)
        {
             DisplayListChar(0, 0, net1);
             DisplayOneChar(2, 0,D[2]/100+0x30);
             DisplayOneChar(3, 0,D[2]%100/10+0x30);
             DisplayOneChar(4, 0,D[2]%10+0x30);

             DisplayListChar(0, 1, net2);
             DisplayOneChar(2, 1,D[1]/100+0x30);
             DisplayOneChar(3, 1,D[1]%100/10+0x30);
             DisplayOneChar(4, 1,D[1]%10+0x30);

             DisplayListChar(6, 0, net3);
             DisplayOneChar(8, 0,D[0]/100+0x30);
             DisplayOneChar(9, 0,D[0]%100/10+0x30);
             DisplayOneChar(10, 0,D[0]%10+0x30);

        }   
       if(++AD_CHANNEL>4) AD_CHANNEL=0;
   
       /********以下将AD的值通过串口发送出去*************/
    /* delay(200);   
     SBUF=D[0];                  
     delay(200);         
     SBUF=D[1];               
     delay(200);   
     SBUF=D[2];
     delay(200);
     SBUF=D[3];
     delay(200);      
     if(RI)
    {
        date=SBUF;    //单片机接受
        SBUF=date;    //单片机发送
        RI=0;
    }*/     
   }
}


/*void delay(uchar i)
{
  uchar j,k;
  for(j=i;j>0;j--)
    for(k=125;k>0;k--);
}*/              

/*******************************************************************
DAC 变换, 转化函数               
*******************************************************************/
bit DACconversion(unsigned char sla,unsigned char c,  unsigned char Val)
{
   Start_I2c();              //启动总线
   SendByte(sla);            //发送器件地址
   if(ack==0)return(0);
   SendByte(c);              //发送控制字节
   if(ack==0)return(0);
   SendByte(Val);            //发送DAC的数值  
   if(ack==0)return(0);
   Stop_I2c();               //结束总线
   return(1);
}

/*******************************************************************
ADC发送字节[命令]数据函数               
*******************************************************************/
bit ISendByte(unsigned char sla,unsigned char c)
{
   Start_I2c();              //启动总线
   SendByte(sla);            //发送器件地址
   if(ack==0)return(0);
   SendByte(c);              //发送数据
   if(ack==0)return(0);
   Stop_I2c();               //结束总线
   return(1);
}

/*******************************************************************
ADC读字节数据函数               
*******************************************************************/
unsigned char IRcvByte(unsigned char sla)
{  unsigned char c;

   Start_I2c();          //启动总线
   SendByte(sla+1);      //发送器件地址
   if(ack==0)return(0);
   c=RcvByte();          //读取数据0

   Ack_I2c(1);           //发送非就答位
   Stop_I2c();           //结束总线
   return(c);
}


//*****串口初始化函数***********

//******************************
void Initial_com(void)
{
EA=1;        //开总中断
ES=1;        //允许串口中断
ET1=1;        //允许定时器T1的中断
TMOD=0x20;   //定时器T1,在方式2中断产生波特率
PCON=0x00;   //SMOD=0
SCON=0x50;   // 方式1 由定时器控制
TH1=0xfd;    //波特率设置为9600
TL1=0xfd;
TR1=1;       //开定时器T1运行控制位

}
/***********写数据********************************************************/   
void WriteDataLCD(unsigned char WDLCD)
{
     ReadStatusLCD(); //检测忙
     LCD_Data = WDLCD;
     LCD_RS = 1;
     LCD_RW = 0;
     LCD_E = 0;         //若晶振速度太高可以在这后加小的延时
     LCD_E = 0;         //延时
     LCD_E = 1;
}

/***********写指令********************************************************/   
void WriteCommandLCD(unsigned char WCLCD,BuysC) //BuysC为0时忽略忙检测
{
     if (BuysC) ReadStatusLCD(); //根据需要检测忙
     LCD_Data = WCLCD;
     LCD_RS = 0;
     LCD_RW = 0;
     LCD_E = 0;
     LCD_E = 0;
    LCD_E = 1;
}

/***********读数据********************************************************/   
unsigned char ReadDataLCD(void)
{
     LCD_RS = 1;
     LCD_RW = 1;
     LCD_E = 0;
     LCD_E = 0;
     LCD_E = 1;
     return(LCD_Data);
}

/***********读状态*******************************************************/   
unsigned char ReadStatusLCD(void)
{
     LCD_Data = 0xFF;
     LCD_RS = 0;
     LCD_RW = 1;
     LCD_E = 0;
     LCD_E = 0;
     LCD_E = 1;
     while (LCD_Data & Busy); //检测忙信号
     return(LCD_Data);
}

/***********初始化********************************************************/   
void LCDInit(void)
{
     LCD_Data = 0;
     WriteCommandLCD(0x38,0);     //三次模式设置,不检测忙信号
     Delay5Ms();
     WriteCommandLCD(0x38,0);
     Delay5Ms();
     WriteCommandLCD(0x38,0);
     Delay5Ms();

     WriteCommandLCD(0x38,1);     //显示模式设置,开始要求每次检测忙信号
     WriteCommandLCD(0x08,1);     //关闭显示
     WriteCommandLCD(0x01,1);     //显示清屏
     WriteCommandLCD(0x06,1);     //显示光标移动设置
     WriteCommandLCD(0x0C,1);     //显示开及光标设置
}

/***********按指定位置显示一个字符*******************************************/   
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)
{
     Y &= 0x1;
     X &= 0xF;                 //限制X不能大于15,Y不能大于1
     if (Y) X |= 0x40;         //当要显示第二行时地址码+0x40;
     X |= 0x80;             //算出指令码
     WriteCommandLCD(X, 0); //这里不检测忙信号,发送地址码
     WriteDataLCD(DData);
}

/***********按指定位置显示一串字符*****************************************/   
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData)
{
     unsigned char ListLength;

     ListLength = 0;
     Y &= 0x1;
     X &= 0xF;                 //限制X不能大于15,Y不能大于1
     while (DData[ListLength]>=0x20){ //若到达字串尾则退出
           if (X <= 0xF){         //X坐标应小于0xF
             DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符
             ListLength++;
             X++;
        }
      }
}

/***********短延时********************************************************/   
void Delay5Ms(void)
{
     unsigned int TempCyc = 5552;
     while(TempCyc--);
}

/***********长延时********************************************************/   
void Delay400Ms(void)
{
     unsigned char TempCycA = 5;
     unsigned int TempCycB;
     while(TempCycA--){
          TempCycB=7269;
          while(TempCycB--);
     }
}


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:123289 发表于 2021-6-23 15:11 | 只看该作者
自己能画出程序流程图吗?
回复

使用道具 举报

板凳
ID:811711 发表于 2021-6-23 15:31 | 只看该作者
好代码 太长 谁也帮不了你啊
回复

使用道具 举报

地板
ID:943129 发表于 2021-6-23 17:25 | 只看该作者
yzwzfyz 发表于 2021-6-23 15:11
自己能画出程序流程图吗?

不能,师傅只要求会用:),这东西我不是很懂才学
回复

使用道具 举报

5#
ID:390416 发表于 2021-7-6 20:33 | 只看该作者
LCD1602显示℃ 这种自定义符号 http://www.51hei.com/bbs/dpj-200685-1.html
LCD1602液晶最新资料 说明了具体的时间要求 http://www.51hei.com/bbs/dpj-205768-1.html
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表