微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 求个大神帮忙改下程序,程序是烟雾警报器,麻烦改成液晶屏显示浓度曲线的,之前是显示数值的

求个大神帮忙改下程序,程序是烟雾警报器,麻烦改成液晶屏显示浓度曲线的,之前是显示数值的

时间:10-02 整理:3721RD 点击:

#include <reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义

#include "intrins.h"                                                                                          

#define     u8                          unsigned char

#define     u16                   unsigned int

#define     uchar                          unsigned char

#define     uint                   unsigned int

uchar yushe_wendu=50;                                //温度预设值

uchar yushe_yanwu=45;                                //烟雾预设值

uint wendu;                                                                 //温度值全局变量

uchar yanwu;                                                                 //用于读取ADC数据

//运行模式  

uchar Mode=0;                                                                 //=1是设置温度阀值  =2是设置烟雾阀值        =0是正常监控模式

//管脚声明

sbit Led_Reg                 =P2^2;                                 //红灯

sbit Led_Yellow  =P2^4;                                 //黄灯

sbit Buzzer             =P2^0;                                 //蜂鸣器

sbit Fan                      =P3^3;                                 //

/********************************************************************

* 名称 : delay_1ms()

* 功能 : 延时1ms函数

* 输入 : q

* 输出 : 无

***********************************************************************/

void delay_ms(uint q)

{

        uint i,j;

        for(i=0;i<q;i++)

                for(j=0;j<110;j++);

}

/***********************************************************************************************************

LCD1602相关函数

***********************************************************************************************************/

//LCD管脚声明 (RW引脚实物直接接地,因为本设计只用到液晶的写操作,RW引脚一直是低电平)

sbit LCDRS = P2^7;

sbit LCDEN = P2^6;

sbit D0                 = P0^0;

sbit D1                 = P0^1;

sbit D2                 = P0^2;

sbit D3                 = P0^3;

sbit D4                 = P0^4;

sbit D5                 = P0^5;

sbit D6                 = P0^6;

sbit D7                 = P0^7;

//LCD延时

void LCDdelay(uint z)                  //该延时大约100us(不精确,液晶操作的延时不要求很精确)

{

  uint x,y;

  for(x=z;x>0;x--)

    for(y=10;y>0;y--);

}

void LCD_WriteData(u8 dat)          

{

        if(dat&0x01)D0=1;else D0=0;

        if(dat&0x02)D1=1;else D1=0;

        if(dat&0x04)D2=1;else D2=0;

        if(dat&0x08)D3=1;else D3=0;

        if(dat&0x10)D4=1;else D4=0;

        if(dat&0x20)D5=1;else D5=0;

        if(dat&0x40)D6=1;else D6=0;

        if(dat&0x80)D7=1;else D7=0;

}

//写命令

void write_com(uchar com)

{

  LCDRS=0;                                  

        LCD_WriteData(com);

//  DAT=com;

  LCDdelay(5);

  LCDEN=1;

  LCDdelay(5);

  LCDEN=0;

}

//写数据

void write_data(uchar date)

{

  LCDRS=1;

        LCD_WriteData(date);

//  DAT=date;

  LCDdelay(5);

  LCDEN=1;

  LCDdelay(5);

  LCDEN=0;

}

/*------------------------------------------------

              选择写入位置

------------------------------------------------*/

void SelectPosition(unsigned char x,unsigned char y)

{     

        if (x == 0)

        {     

                write_com(0x80 + y);     //表示第一行

        }

        else

        {      

                write_com(0xC0 + y);      //表示第二行

        }        

}

/*------------------------------------------------

              写入字符串函数

------------------------------------------------*/

void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s)

{     

        SelectPosition(x,y) ;

        while (*s)

        {     

                write_data( *s);     

                s ++;     

        }

}

//========================================================================

// 函数: void LCD_Write_Char(u8 x,u8 y,u16 s,u8 l)

// 应用: LCD_Write_Char(0,1,366,4) ;

// 描述: 在第0行第一个字节位置显示366的后4位,显示结果为 0366

// 参数: x:行,y:列,s:要显示的字,l:显示的位数

// 返回: none.

// 版本: VER1.0

// 日期: 2013-4-1

// 备注: 最大显示65535

//========================================================================

void LCD_Write_Char(u8 x,u8 y,u16 s,u8 l)

{     

        SelectPosition(x,y) ;

        if(l>=5)

                write_data(0x30+s/10000%10);        //万位

        if(l>=4)

                write_data(0x30+s/1000%10);                //千位

        if(l>=3)

                write_data(0x30+s/100%10);                //百位

        if(l>=2)

                write_data(0x30+s/10%10);                        //十位

        if(l>=1)

                write_data(0x30+s%10);                //个位

}

/*1602指令简介

  write_com(0x38);//屏幕初始化

  write_com(0x0c);//打开显示 无光标 无光标闪烁

  write_com(0x0d);//打开显示 阴影闪烁

  write_com(0x0d);//打开显示 阴影闪烁

*/

//1602初始化

void Init1602()

{

  uchar i=0;

  write_com(0x38);//屏幕初始化

  write_com(0x0c);//打开显示 无光标 无光标闪烁

  write_com(0x06);//当读或写一个字符是指针后一一位

  write_com(0x01);//清屏

       

}

void Display_1602(yushe_wendu,yushe_yanwu,c,temp)

{

        //显示预设温度

        LCD_Write_Char(0,6,yushe_wendu,2) ;

       

        //显示预设烟雾

        LCD_Write_Char(0,13,yushe_yanwu,3) ;

       

        //时时温度

        LCD_Write_Char(1,6,c/10,2) ;

        write_data('.');

        LCD_Write_Char(1,9,c%10,1) ;

       

        //时时烟雾

        LCD_Write_Char(1,13,temp,3) ;

}

/***********************************************************************************************************

ADC0832相关函数

***********************************************************************************************************/

sbit ADCS         =P1^5; //ADC0832 片选

sbit ADCLK  =P1^2; //ADC0832 时钟

sbit ADDI         =P1^3; //ADC0832 数据输入                /*因为单片机的管脚是双向的,且ADC0832的数据输入输出不同时进行,

sbit ADDO         =P1^3; //ADC0832 数据输出                /*为节省单片机引脚,简化电路所以输入输出连接在同一个引脚上

//========================================================================

// 函数: unsigned int Adc0832(unsigned char channel)

// 应用:                 temp=Adc0832(0);

// 描述: 读取0通道的AD值

// 参数: channel:通道0和通道1选择

// 返回: 选取通道的AD值

// 版本: VER1.0

// 日期: 2015-05-29

// 备注:

//========================================================================

unsigned int Adc0832(unsigned char channel)

{

        uchar i=0;

        uchar j;

        uint dat=0;

        uchar ndat=0;

        uchar  Vot=0;

        if(channel==0)channel=2;

        if(channel==1)channel=3;

        ADDI=1;

        _nop_();

        _nop_();

        ADCS=0;//拉低CS端

        _nop_();

        _nop_();

        ADCLK=1;//拉高CLK端

        _nop_();

        _nop_();

        ADCLK=0;//拉低CLK端,形成下降沿1

        _nop_();

        _nop_();

        ADCLK=1;//拉高CLK端

        ADDI=channel&0x1;

        _nop_();

        _nop_();

        ADCLK=0;//拉低CLK端,形成下降沿2

        _nop_();

        _nop_();

        ADCLK=1;//拉高CLK端

        ADDI=(channel>>1)&0x1;

        _nop_();

        _nop_();

        ADCLK=0;//拉低CLK端,形成下降沿3

        ADDI=1;//控制命令结束

        _nop_();

        _nop_();

        dat=0;

        for(i=0;i<8;i++)

        {

                dat|=ADDO;//收数据

                ADCLK=1;

                _nop_();

                _nop_();

                ADCLK=0;//形成一次时钟脉冲

                _nop_();

                _nop_();

                dat<<=1;

                if(i==7)dat|=ADDO;

        }

        for(i=0;i<8;i++)

        {

                j=0;

                j=j|ADDO;//收数据

                ADCLK=1;

                _nop_();

                _nop_();

                ADCLK=0;//形成一次时钟脉冲

                _nop_();

                _nop_();

                j=j<<7;

                ndat=ndat|j;

                if(i<7)ndat>>=1;

        }

        ADCS=1;//拉低CS端

        ADCLK=0;//拉低CLK端

        ADDO=1;//拉高数据端,回到初始状态

        dat<<=8;

        dat|=ndat;

        return(dat);            //return ad data

}

/***********************************************************************************************************

DS18B20相关函数

***********************************************************************************************************/

sbit DQ = P1^0;                                 //ds18b20的数据引脚

/*****延时子程序:该延时主要用于ds18b20延时*****/

void Delay_DS18B20(int num)

{

  while(num--) ;

}

/*****初始化DS18B20*****/

void Init_DS18B20(void)

{

  unsigned char x=0;

  DQ = 1;         //DQ复位

  Delay_DS18B20(8);    //稍做延时

  DQ = 0;         //单片机将DQ拉低

  Delay_DS18B20(80);   //精确延时,大于480us

  DQ = 1;         //拉高总线

  Delay_DS18B20(14);

  x = DQ;           //稍做延时后,如果x=0则初始化成功,x=1则初始化失败

  Delay_DS18B20(20);

}

/*****读一个字节*****/

unsigned char ReadOneChar(void)

{

  unsigned char i=0;

  unsigned char dat = 0;

  for (i=8;i>0;i--)

  {

    DQ = 0;     // 给脉冲信号

    dat>>=1;

    DQ = 1;     // 给脉冲信号

    if(DQ)

    dat|=0x80;

    Delay_DS18B20(4);

  }

  return(dat);

}

/*****写一个字节*****/

void WriteOneChar(unsigned char dat)

{

  unsigned char i=0;

  for (i=8; i>0; i--)

  {

    DQ = 0;

    DQ = dat&0x01;

    Delay_DS18B20(5);

    DQ = 1;

    dat>>=1;

  }

}

/*****读取温度*****/

unsigned int ReadTemperature(void)

{

  unsigned char a=0;

  unsigned char b=0;

  unsigned int t=0;

  float tt=0;

  Init_DS18B20();

  WriteOneChar(0xCC);  //跳过读序号列号的操作

  WriteOneChar(0x44);  //启动温度转换

  Init_DS18B20();

  WriteOneChar(0xCC);  //跳过读序号列号的操作

  WriteOneChar(0xBE);  //读取温度寄存器

  a=ReadOneChar();     //读低8位

  b=ReadOneChar();    //读高8位

  t=b;

  t<<=8;

  t=t|a;

  tt=t*0.0625;

  t= tt*10+0.5;     //放大10倍输出并四舍五入

  return(t);

}

//=====================================================================================

//=====================================================================================

//=====================================================================================

/*****校准温度*****/

u16 check_wendu(void)

{

        u16 c;

        c=ReadTemperature()-5;                          //获取温度值并减去DS18B20的温漂误差

        if(c<1) c=0;

        if(c>=999) c=999;

        return c;

}

/***********************************************************************************************************

按键检测相关函数

***********************************************************************************************************/

//按键

sbit Key1=P1^6;                                 //设置键

sbit Key2=P1^7;                                 //加按键

sbit Key3=P3^2;                                 //减按键

#define KEY_SET                 1                //设置

#define KEY_ADD                        2                //加

#define KEY_MINUS                3                //减

//========================================================================

// 函数: u8 Key_Scan()

// 应用: temp=u8 Key_Scan();

// 描述: 按键扫描并返回按下的键值

// 参数: NONE

// 返回: 按下的键值

// 版本: VER1.0

// 日期: 2015-05-29

// 备注: 该函数带松手检测,按下键返回一次键值后返回0,直至第二次按键按下

//========================================================================

u8 Key_Scan()

{         

        static u8 key_up=1;//按键按松开标志

        if(key_up&&(Key1==0||Key2==0||Key3==0))

        {

                delay_ms(10);//去抖动

                key_up=0;

                if(Key1==0)                        return 1;

                else if(Key2==0)return 2;

                else if(Key3==0)return 3;

        }

        else if(Key1==1&&Key2==1&&Key3==1)

                key_up=1;             

        return 0;// 无按键按下

}

void main (void)

{

        u8 key;

        wendu=check_wendu();                  //初始化时调用温度读取函数 防止开机85°C

        Init1602();                          //调用初始化显示函数

        LCD_Write_String(0,0,"SET T:00   E:000");  //开机界面

        LCD_Write_String(1,0,"NOW T:00.0 E:000");  

        delay_ms(1000);

        wendu=check_wendu();                  //初始化时调用温度读取函数 防止开机85°C

        while (1)                                                //主循环

        {

                key=Key_Scan();                                        //按键扫描

                yanwu=Adc0832(0);                                //读取烟雾值

                wendu=check_wendu();          //读取温度值

               

                if(key==KEY_SET)

                {

                        Mode++;

                }

               

                switch(Mode)                                                //判断模式的值

                {

                        case 0:                                                                //监控模式

                        {

                                Display_1602(yushe_wendu,yushe_yanwu,wendu,yanwu);  //显示预设温度,预设烟雾,温度值,烟雾值

                                if(yanwu>=yushe_yanwu)          //烟雾值大于等于预设值时

                                {

                                        Led_Reg=0;                                          //烟雾指示灯亮

                                        Fan=0;

                                        Buzzer=0;                                                  //蜂鸣器报警

                                }

                                else                                                                                  //烟雾值小于预设值时

                                {

                                        Led_Reg=1;                                          //关掉报警灯

                                        Fan=1;

                                }

                                if(wendu>=(yushe_wendu*10))          //温度大于等于预设温度值时(为什么是大于预设值*10:因为我们要显示的温度是有小数点后一位,是一个3位数,25.9°C时实际读的数是259,所以判断预设值时将预设值*10)

                                {

                                        Buzzer=0;                                                  //打开蜂鸣器报警

                                        Led_Yellow=0;                                          //打开温度报警灯

                                }

                                else                                                                                  //温度值小于预设值时

                                {

                                        Led_Yellow=1;                                          //关闭报警灯

                                }

                                if((yanwu<yushe_yanwu)&&(wendu<(yushe_wendu*10)))          //当烟雾小于预设值并且温度也小于预设值时 (&&:逻辑与,左右两边的表达式都成立(都为真,也就是1)时,该if语句才成立)

                                {

                                        Buzzer=1;                                                  //停止报警

                                }

                                break;

                        }

                        case 1://预设温度模式

                        {

                                SelectPosition(0,5) ;                                        //指定位置

                           write_com(0x0d);                                                        //阴影闪烁

                                if(key==KEY_ADD)                                                        //加键按下

                                {

                                        yushe_wendu++;                                            //预设温度值(阀值)加1

                                        if(yushe_wendu>=99)                                         //当阀值加到大于等于99时

                                        yushe_wendu=99;                                                         //阀值固定为99

                                        LCD_Write_Char(0,6,yushe_wendu,2) ;//显示预设温度

                                }

                                if(key==KEY_MINUS)                                                 //减键按下

                                {

                                        if(yushe_wendu<=1)                                        //当温度上限值减小到1时

                                        yushe_wendu=1;                          //固定为1

                                        yushe_wendu--;                                                        //预设温度值减一,最小为0

                                        LCD_Write_Char(0,6,yushe_wendu,2) ;//显示预设温度

                                }

                                break;                                                                                          //执行后跳出switch

                        }

                        case 2:                                //预设烟雾模式

                        {

                                SelectPosition(0,12) ;                                //指定位置       

                           write_com(0x0d);                                                        //打开显示 无光标 光标闪烁

                                if(key==KEY_ADD)                                                        //加键按下

                                {

                                        if(yushe_yanwu>=255)        //当阀值加到大于等于255时

                                        yushe_yanwu=254;            //阀值固定为254

                                        yushe_yanwu++;                                            //预设烟雾值(阀值)加1,最大为255

                                        LCD_Write_Char(0,13,yushe_yanwu,3) ;//显示预设烟雾

                                }

                                if(key==KEY_MINUS)                                                //减键按下

                                {

                                        if(yushe_yanwu<=1)                                        //当烟雾上限值减小到1时

                                                yushe_yanwu=1;                  //固定为1

                                        yushe_yanwu--;                                                        //预设温度值减一,最小为0          

                                        LCD_Write_Char(0,13,yushe_yanwu,3) ;//显示预设烟雾

                                }

                                break;

                        }

                        default        :       

                        {

                                write_com(0x38);//屏幕初始化

                                write_com(0x0c);//打开显示 无光标 无光标闪烁

                                Mode=0;                        //恢复正常模式

                                break;

                        }

                }

               

        }

}



已退回9积分

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top