找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1255|回复: 7
收起左侧

单片机dht11在仿真时,通过按钮转到调湿度上限和湿度下限画面时,显示光标乱窜的情况

[复制链接]
ID:941024 发表于 2021-6-20 18:28 | 显示全部楼层 |阅读模式
由于本论坛禁止直接求程序,禁止伸手党,所以向大家请教一下大致的实现方法与思路,理清头绪后我自己去实现,谢谢大家

用的51单片机和DHT11做的控制湿度系统。
现在出现问题是:在仿真时,通过按钮转到调湿度上限和湿度下限画面时,显示光标乱窜的情况。
希望大佬们帮我看看!谢谢!

湿度控制.zip

175.82 KB, 下载次数: 7

回复

使用道具 举报

ID:941024 发表于 2021-6-20 22:50 | 显示全部楼层
这个是LCD的代码
#include<reg51.h>
#include<intrins.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <absacc.h>
#include <math.h>
#define U8INT unsigned     char
#define U16INT unsigned            int
#define U32INT unsigned           long
#define LCD_Port P0
//定义LCD1602端口

sbit EN=P1^3;                //使能
sbit RW=P2^6;                //读写
sbit RS=P1^2;                //数据/命令选择
U8INT humidity;
U8INT temperature;
U8INT Mode;
bit bdata humid,dry,BJ;

void delay_ms(U16INT x)          //延时
{
           U8INT i=0;
           while(x--)
           {
            for(i=0;i<120;i++);
           }
}
void Busy_Wait()                //忙等待
{
        U8INT LCD_Status=0x00;
        do
        {
                LCD_Port=0xFF;
                EN=0;RS=0;RW=1;
                EN=1;_nop_();
                LCD_Status=LCD_Port        ;
                EN=0;_nop_();
        }
        while(LCD_Status&0x80);
}
void LCD_Write_CMD(U8INT cmd)          //写入LCD的命令
{
        Busy_Wait();
        EN=0;RS=0;RW=0;
        LCD_Port=cmd;
        EN=1;_nop_();
        EN=0;_nop_();

//        delay_ms(10);        //
}
void LCD_Write_Data(U8INT dat)          //写入LDE的数据
{
        Busy_Wait();
        EN=0;RS=1;RW=0;
        LCD_Port=dat;
        EN=1;_nop_();
        EN=0;_nop_();
        Busy_Wait();
//        delay_ms(10);          //
}
void LCD_Init()                                   //初始化LCD
{
                LCD_Write_CMD(0x38);//设置显示模式:16x2显示,5x7点阵,8位数据接口
                LCD_Write_CMD(0x0c);//开显示,不显示光标,光标不闪烁
                LCD_Write_CMD(0x06);//写一个字符后地址指针加1,且光标加1,整屏显示不移动
                LCD_Write_CMD(0x01);//清屏

}
void L1602_char(U8INT hang,U8INT lie,U8INT sign) //行、列、单个字符
{
        U8INT a;
        if(hang == 1) a = 0x80;                 //上行首地址
        if(hang == 2) a = 0xc0;                  //下行首地址
        a = a + lie - 1;                        //从第零位加(lie-1)位开始显示
        LCD_Write_CMD(a);
        LCD_Write_Data(sign);
}
void L1602_string(U8INT hang,U8INT lie,U8INT *p)   //行、列、字符串
{
        U8INT a;
        if(hang == 1) a = 0x80;                //
        if(hang == 2) a = 0xc0;                  //
        a = a + lie - 1;
        LCD_Write_CMD(a);
        while(1)
        {
                if(*p == '\0') break;         //从P字符串第一个字符打到最后一个字符
                LCD_Write_Data(*p);                 //每次循环加一个P,‘\0’是加在字符串后的结束标志
                p++;                                         //         当碰到结束标志就break结束循环
        }
}
void L1602_int(U8INT hang, U8INT lie, int num)        //行、列、整形   / /显示整形的湿度
{
   U16INT temp;
   U16INT gewei,shiwei,baiwei,sign;         //geshibai
   if (num >= 0)
   sign = 0;
   else
   sign = 1;
   temp = abs(num);                                   //绝对值
   baiwei = temp / 100;                                   // 百
   temp = temp - baiwei*100;
   shiwei = temp / 10;                                  //   十
   gewei = temp - shiwei*10;                  //        个
   num = abs(num);
   if (num>=100)
   {
   
          L1602_char(hang, lie+2, shiwei+48);          //ASCII码48起0
          L1602_char(hang, lie+3, gewei+48);  
   }
   else if (num>=10)
   {
      if (sign == 1)          
          L1602_char(hang, lie+1, ' ');
          L1602_char(hang, lie+2, shiwei+48);  
      L1602_char(hang, lie+3, gewei+48);
   }
   else
   {
      if (sign == 1)          
          L1602_char(hang, lie+1, ' ');
          else
          L1602_char(hang, lie+2, ' ');
      L1602_char(hang, lie+3, gewei+48);  
   }
}
void display()          //显示湿度状态
{
        if(Mode==0)
        {
                L1602_int(1,3,humidity);
                if(humid==1&&dry==0)
                {L1602_string(2,1,"It's very humid!");BJ=1;}
                else if(humid==0&&dry==1)
                {L1602_string(2,1," It's very dry! ");BJ=1;}
                else if(humid==0&&dry==0)
                {L1602_string(2,1," It's normal!   ");BJ=0;}
        }                                                                          
}
回复

使用道具 举报

ID:941024 发表于 2021-6-20 22:50 | 显示全部楼层
这个是DHT11的代码
#include<reg51.h>
#include<intrins.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <absacc.h>
#include <math.h>
#define U8INT unsigned char
#define U16INT unsigned int
sbit Led_jiashi=P3^4;//定义湿度控制功能               
sbit Led_qushi=P3^3;               
sbit DATA= P1^7;        //定义DHT11数据口
sbit buzz= P3^5;
sbit SCL = P1^0;        //定义24C02数据口
sbit SDA = P1^1;
U8INT U8checkdata_temp;
U8INT U8RH_data_H_temp;
U8INT U8RH_data_L_temp;
U8INT U8T_data_H_temp;        //
U8INT U8T_data_L_temp;        //
U8INT U8RH_data_H;            //高8位湿度整数
U8INT U8RH_data_L;           //低8位湿度小数
U8INT U8T_data_H;            
U8INT U8T_data_L;
U8INT U8checkdata;        //8位数据检查数据
U8INT U8temp;           //8位数据寄存(用来对比检差数据
U8INT U8FLAG;                // 用来计数溢出等待
U8INT U8comdata;        //8位数据寄存(用来存湿度数据
bit bdata FlagStartRH;//定义一个位变量flag
extern bit        humid,dry,BJ; // 0或者1
void Timer0_Init()           //初始化定时器0
{
        ET0 = 1;        //允许定时器0中断
        TMOD = 0x11;       //定时器工作方式选择
        TL0 = 0xFF;     
        TH0 = 0x4B;     //定时器赋予初值
        TR0 = 1;        //启动定时器
}

void Timer0_ISR (void) interrupt 1 using 0         //定时器0中断
{                                                                                         //第0组寄存器
        U8INT RHCounter;
        TL0 = 0xFF;
        TH0 = 0x4B;     //定时器赋予初值
        RHCounter++;
        if(RHCounter%10==0&&BJ==1)
        buzz=!buzz;
        else if(BJ==0)
        buzz=1;
        //每1秒钟启动一次温湿度转换
    if (RHCounter >= 20)
    {
       FlagStartRH = 1;
           RHCounter = 0;
    }
}

void DELAY (U16INT t)         //           延时
{
        while(t!=0)
        t--;
}                                                                //SCL 时钟线           //SDA 双向控制线
void IICStart(void)                           //开始
{
     SCL=0;                                             //SCL为高电平,SDA由高跳低,开始传送数据
         DELAY(1);
     SDA=1; SCL=1; DELAY(1);       
     SDA=0; DELAY(1);                        //脉冲表示应答信号,无反应为故障
     SCL=0;                                         //钳住I2C总线,准备发送或接收数据
}

void IICStop(void)                           // 结束
{
         SDA=0;SCL=1; DELAY(1);           //SCL为高电平,SDA由低跳高,结束传送数据
     SDA=1; DELAY(1);
     SCL=0;                                         //发送I2C总线结束信号
}
void SEND0(void)                         //发送数据函数
{                                                        //sda为0时,传输状态,scl由高变低
        SDA=0;
        SCL=1;
        DELAY(1);
        SCL=0;
}

void SEND1(void)       
{                                                           //sda为1时,空闲状态,scl由高变低
        SDA=1;
        DELAY(1);
        SCL=1;
        DELAY(1);
        SCL=0;
}
void  Delay_10us(void)          //延时10毫秒
{
    U8INT i;
    i--;
    i--;
    i--;
    i--;
    i--;
    i--;
}
void Delay1(U16INT j)
{
    U8INT i;
    for(;j>0;j--)
    {        
                for(i=0;i<27;i++);
    }
}
bit Check_Ack(void)                //返回信号
{
        U8INT errtime=250;
        DELAY(1);
        SCL=1;
        DELAY(1);
        CY=SDA;
        while(CY)
        {
                errtime--;
                CY=SDA;
                if (!errtime)
                {
                        IICStop();
                        return 1;
                }
        }
        DELAY(1);
        SCL=0;
        return 0;
}
void Write_byte(U8INT dat)
{
    U8INT i;
        for(i=0;i<8;i++)
        {       
                if((dat<<i)&0x80)
                SEND1();
                else
                SEND0();
        }
}

U8INT Read_byte(void)
{
        U8INT i,temp=0;     
        for(i=0;i<8;i++)
        {
        SDA=1;
            SCL=1;
            DELAY(1);  
                if(SDA==1)
                {
                        temp=temp<<1;
                        temp=temp|0x01;
                }
                else
                temp=temp<<1;
                 SCL=0;       
          }
          return temp;
}
U8INT rdeeprom(U8INT addr)
{
        U8INT temp=0;
                bit flag=0;
                IICStart();
                Write_byte(0xa0);
        Check_Ack();
                Write_byte(addr);
                Check_Ack();
                IICStart();
                Write_byte(0xa1);
                Check_Ack();
                temp=Read_byte();
                SEND1();
                IICStop();
            return temp;   
}  
   
   
void wrteeprom(U8INT addr,U8INT dat)
{
               IICStart();
                Write_byte(0xa0);
                Check_Ack();
                Write_byte(addr);
                Check_Ack();
                Write_byte(dat);
                Check_Ack();
                IICStop();
}

                       
void Data_Init()                         //数据初始化
{
   Led_qushi  = 1;                               //qushi
   Led_jiashi = 1;                            //jiashi
  
}
void  COM(void)                                //存8位数据
{
    U8INT i;
    for(i=0;i<8;i++)          
    {
              U8FLAG=2;
                   while((!DATA)&&U8FLAG++);
                Delay_10us();           //yan时30us
                Delay_10us();
                Delay_10us();
                  U8temp=0;
        if(DATA)U8temp=1;          //30us后当DHT11信号为为高,收到的数据为1        否则为0
                    U8FLAG=2;
                while((DATA)&&U8FLAG++);         //超时则跳出for循环                             
                   if(U8FLAG==1)break;        //判断数据位是0还是1   如果高电平高过预定0高电平值则数据位为 1
                U8comdata<<=1;                   //左移1位
                   U8comdata|=U8temp;        //0
    }
}
U8INT RH(void)                          //工作DH11
{
   
    DATA=0;                           //主机拉低18ms
        Delay1(180);  //原来为5
        DATA=1;                                //再拉高电平  主机延时40us        不然会乱码
        Delay_10us();          
        Delay_10us();
        Delay_10us();
        Delay_10us();
        DATA=1;                                   //主机设为输入 判断从机响应信号           
        if(!DATA)                 //T !                  //判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行
        {                                                          
            U8FLAG=2;                     
            while((!DATA)&&U8FLAG++);   //判断从机是否发出 80us 的低电平   响应信号是否结束
            U8FLAG=2;            
            while((DATA)&&U8FLAG++);   //判断从机是否发出 80us 的高电平   如发出则进入数据接收状态
            //数据接收状态                 
            COM();
            U8RH_data_H_temp=U8comdata;
            COM();
            U8RH_data_L_temp=U8comdata;
            COM();
                U8T_data_H_temp=U8comdata;         //           必须要有,不然检验不了数据
            COM();
            U8T_data_L_temp=U8comdata;        //
            COM();
            U8checkdata_temp=U8comdata;
            DATA=1;          
            U8temp=(U8T_data_H_temp+U8T_data_L_temp+U8RH_data_H_temp+U8RH_data_L_temp);          //数据校验         ????
            if(U8temp==U8checkdata_temp)
            {
                      U8RH_data_H=U8RH_data_H_temp;
                      U8RH_data_L=U8RH_data_L_temp;
                   U8T_data_H=U8T_data_H_temp;
                      U8T_data_L=U8T_data_L_temp;
                      U8checkdata=U8checkdata_temp;
            }
                return 1;
        }
        else   //传感器不响应                 没有检测到低电位所以不响应
        {
           return 0;
        }
}

回复

使用道具 举报

ID:941024 发表于 2021-6-20 22:51 | 显示全部楼层
这个是主函数的代码
#include<reg51.h>
#include<intrins.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <absacc.h>
#include <math.h>
#define U8INT unsigned char
#define U16INT unsigned          int
#define U32INT unsigned           long int
sbit Key_SET = P2^0; //定义三个设置按键
sbit Key_ADD = P2^1;
sbit Key_SUB = P2^2;
sbit Key_OK  = P2^3;
sbit Led_jiashi=P3^4;//定义湿度控制功能               
sbit Led_qushi=P3^3;

extern Mode;
extern  humidity;
char HH,HL;
extern U8RH_data_H;        //高8位湿度整数
extern U8RH_data_L;           //低8位湿度小数
extern void L1602_string(U8INT hang,U8INT lie,U8INT *p);
extern void L1602_char(U8INT hang,U8INT lie,U8INT sign);
extern void L1602_int(U8INT hang, U8INT lie, int num);
extern void LCD_Write_Data(U8INT dat);
extern void LCD_Write_CMD(U8INT cmd);
extern void LCD_Init();
extern void display();
extern void wrteeprom(U8INT addr,U8INT dat);
extern void IICStart(void);       
extern void IICStop(void);
extern void Timer0_Init();
extern void Timer0_ISR (void) ;        //         interrupt 1 using 0
extern void SEND0(void);
extern void SEND1(void);
extern void  Delay_10us(void)         ;
extern void Delay1(U16INT j);
extern void Write_byte(unsigned char dat) ;
extern void Data_Init();
extern void  COM(void)        ;
extern bit Check_Ack(void);
extern void Delay1(U16INT j);
extern void Data_Init() ;
U8INT Read_byte(void)  ;
U8INT RH(void)        ;
U8INT rdeeprom(U8INT addr);
extern bit FlagStartRH,humid,dry,BJ;

void KEY()                         //设置按键
{
        if(Key_SET==0)
        {
                Delay1(200);
                //解决不了问题LCD_Write_CMD(0x01);
                if(Key_SET==0)                        //一开始是0
                {
                        Mode++;
                        if(Mode==1)                           //后加一
                        {
                                L1602_string(1,1," HH:    % HL:  %");         //初始显示
                                L1602_int(1,4,HH);
                                L1602_int(1,12,HL);
                                LCD_Write_CMD(0x80+6);                  
                                LCD_Write_CMD(0x0f);                  //闪烁
                        }
                        else if(Mode>=2)
                        {                                                           //2
                               
                                LCD_Write_CMD(0x80+14);
                                LCD_Write_CMD(0x0f);
                        }
                        else if(Mode>=3)
                        {                                                           //循环条件
                                Mode=1;
                                LCD_Write_CMD(0x80+6);                  
                                LCD_Write_CMD(0x0f);
                        }
                        while(!Key_SET);
                }
        }
        else if(Key_ADD==0)                        //增加
        {
                Delay1(100);
                if(Key_ADD==0)
                {
                        if(Mode==1)
                        {
                                HH++;
                                if(HH>=100)
                                HH=99;
                                L1602_int(1,4,HH);
                                LCD_Write_CMD(0x80+6);
                        }
                        else if(Mode==2)
                        {
                                HL++;
                                if(HL>=HH)
                                HL=HH-1;
                                L1602_int(1,12,HL);
                                LCD_Write_CMD(0x80+14);
                        }
                        while(!Key_ADD);
                }
        }
        else if(Key_SUB==0)
        {
                Delay1(100);
                if(Key_SUB==0)
                {
                        if(Mode==1)
                        {
                                HH--;
                                if(HH<=HL)
                                HH=HL+1;
                                L1602_int(1,4,HH);
                                LCD_Write_CMD(0x80+6);
                        }
                        else if(Mode==2)
                        {
                                HL--;
                                if(HL<=0)
                                HL=0;
                                L1602_int(1,12,HL);
                                LCD_Write_CMD(0x80+14);
                        }
                        while(!Key_SUB);
                }
        }
        if(Key_OK==0&&Mode!=0)
        {
                Delay1(100);
                if(Key_OK==0)
                {
                        L1602_string(1,1,"Hum:   %        ");
                        L1602_string(2,1,"Good environment");
                        Mode=0;
                        wrteeprom(0,HH);
                        Delay1(20);
                        wrteeprom(1,HL);
                        Delay1(20);
                        LCD_Write_CMD(0x0c);        //xia
                        while(Key_OK==0);
                }
        }
}


void main()
{
    U16INT i, j, testnum;
    EA = 0;                                //di wai  gao nei
        Timer0_Init();   
    Data_Init();
        EA = 1;
        LCD_Init();
        L1602_string(1,1,"Welcome Humidity");
        L1602_string(2,1,"Control System! ");
         for (i=0;i<500;i++)
           for (j=0;j<500;j++)
           {;}   
        L1602_string(1,1,"                ");
        L1602_string(2,1,"                ");
    L1602_string(1,1,"Hum:  %         ");
        L1602_string(2,1,"Good environment");  
        HH=rdeeprom(0);         
        Delay1(20);                  
        HL=rdeeprom(1);
        Delay1(20);
        while(1)
        {
      
                 if (FlagStartRH == 1)         //湿度转换标志检查
                 {
                     TR0 = 0;
             testnum = RH();
                         FlagStartRH = 0;
                         TR0 = 1;
                         humidity = U8RH_data_H;         //读出湿度,只取整数部分
                         

                         
                         if(Mode==0)                //湿度控制
                         {
                                if (humidity > HH)
                                {
                                        Led_qushi = 0;
                                        humid=1;
                                        Led_jiashi = 1;
                                        dry=0;
                       
                                }
                                else if(humidity<HL)
                                {
                                        Led_jiashi = 0;
                                        dry=1;
                                        Led_qushi = 1;
                                        humid=0;
                       
                                }               
                                else
                                {
                                        Led_qushi=1;
                                        Led_jiashi=1;
                                        humid=0;
                                        dry=0;
                                }       
                         }       
                }
                display();
                KEY();
        }       
}
回复

使用道具 举报

ID:941024 发表于 2021-6-21 17:14 | 显示全部楼层
有大佬吗,暖一下
回复

使用道具 举报

ID:941024 发表于 2021-6-24 00:16 | 显示全部楼层
问题还有一个:跳转到控制台的时候,湿度SUM:60会一直在lcd显示屏
回复

使用道具 举报

ID:748788 发表于 2021-6-24 16:07 | 显示全部楼层
程序有没有上真机测试?应该以真机为准。
回复

使用道具 举报

ID:941024 发表于 2021-6-28 23:49 | 显示全部楼层
wwh2382 发表于 2021-6-24 16:07
程序有没有上真机测试?应该以真机为准。

用的仿真
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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