zoukankan      html  css  js  c++  java
  • Proteus传感器+气体浓度检测的报警方式控制仿真

    Proteus传感器+气体浓度检测的报警方式控制仿真

    1 实验意义理解

    基于前两个实验,我们已经成功的实现:

    • 对传感器的数据进行采样、转换
    • 拟合采样值
    • 对拟合的数据在HDG12864F-1显示屏上显示

    似乎,该得到的数据已经拿到了,还能干啥?

    是的,我们还能利用数据干一些东西,比如说当这个气体浓度超范围的时候我们怎么去控制解决。

    那么就引出了这个实验,怎么控制解决?

    其实,我们在平时生活中见到过很多,当气体浓度超过一定范围:

    • 报警
      • 开警报灯
      • 蜂鸣器出警报声音
    • 疏通
      • 开启风扇通风
      • ……
    • ……

    如上,我们这次实验就是采取了前三个小点的方式来控制解决。

    此外,我们还要优化LCD显示,就是在屏幕上显示转动的风扇。

    2 主要实验器件

    1. CPU处理器

      • AT89C52
    2. LCD显示

      • HDG12864F-1
    3. AD转换器

      • ADC0834
    4. 传感器

      • 温湿度:SHT10
      • 光传感器:TORCH_LDR
      • 瓦斯浓度传感器:LDR
      • 一氧化碳浓度传感器:LDR
      • 气压传感器:MPX4115
    5. 控制相关

      • 报警灯:RGBLED-CC
      • 蜂鸣器:SOUNDER
      • 通风控制:FAN

    3 实验参考电路

    1. 未运行时

    2. 运行时

    3. 说明

      • 有蜂鸣器声音
      • 显示中第一行的channel后面的字母会根据当前正在采样转换的通道不同而改变
      • 所有数据仅为转换后显示,并未存储下来,若要存储显示,只需要开几个全局变量保存一下即可

    4 实验中的问题思考

    4.1 实现转动的风扇

    要实现这个功能,我们只要知道两个关键点就好了:

    • HDG12864F-1液晶显示如果你不对一个像素覆盖写入值,则会保持显示上次写入的值
    • 任何动态效果实质上是由一个个静态图画“快速”播放而成的

    因此,实现这个就很容易了:

    • 找到几个不一样(转动角度不一样)的静态风扇图(最好大小一样,这样方便写入,完全覆盖)
    • 对这几个静态风扇图取模
    • 调用HDG12864F-1绘制图片函数将一个静态图写入
    • 让处理器去干别的事情,比如:执行几句其他的语句,或者直接延时等待
    • 调用HDG12864F-1绘制图片函数写入另一个静态图
    • ……

    那么,中间为什么会有“让处理器去干别的事情,比如:执行几句其他的语句,或者直接延时等待”这一点呢?

    其实这是一个控制模拟风扇转动速度的。你想想如果快速切换两张图片,你眼睛还没视觉残留呢,就没了,估计会闪瞎狗眼……所以,选择一个合适的切换时间间隔也是挺重要的……

    第二个,这个静态图画至少两幅,这个大家应该很好理解,如果一幅的话,没有变化,换来换去不就那个玩意儿吗……

    4.2 控制部分

    首先,我们来看一下控制部分的原理图:

    下面,我们分别说一下各个部分。

    1. 报警灯

      这个RGBLED-CC要想让它工作,首先就是K端给个低电平。

      RGB端,输入1为亮,0为不亮。

      然后,在这个实验中,其实我们只需要用到红和绿两种颜色,所以直接给B端接地,然后R和G端分别绑定到处理器的引脚上。

      运行中判断,如果达到危险值或者恢复至安全值,则处理器重置相应的引脚值。

    2. 蜂鸣器

      主要是SOUNDER元件,一端加电压,另一端需要给脉冲信号

      这个脉冲信号很重要,一开始,本菜狗就对这个输入的脉冲信号没有设置(默认频率很小),因此都听不出来发声了……

      后来双击输入的SW1(A),调整了一下参数,然后就听到了,可参考下图是我调整的:

      当然这里拓展一下,怎么让它放音乐呢??

      这里有两段经历让我对这个有了进一步的认识:

      • 大二学校暑假实习的时候,做电子钟,当时用verilog写的,那个如果要让蜂鸣器放出来的不仅仅是那种很难听的一直尖叫,而是播放音乐啊啥的,需要给不同的频率

      • 大三上微机原理课设,使用笔记本内置的芯片,做了一个基于x86的时钟(用的汇编语言写的)。其中,闹钟功能,铃声我想换成音乐怎么办?

        • 找到音乐的谱子和对应的音符频率,相对延时
        • 分别将频率和延时写成“表”,依次延时输出

        这里,再次拓展一下,如果你想听快速版的音乐怎么办?想要听降调,升调的版本怎么办?

        • 频率:控制音调
        • 延时:控制速度

      然后,再说一下,怎么控制这个声音的开关

      这里使用的是DSWITCH元件,可以把它看成一个三态门

      • BP端置为1,接收SW1(A)的输入
      • BP端置为0,高阻态,不发声
    3. 避风控制

      这个模块主要是由FAN+继电器PCJ-112D3MH来实现的,这个我在IC网上也没找到它的DATASHEET,所以,就照着老师的原理图画了之后个人理解了一下。

      首先,怎么控制它的开关

      • 我们可以看到它左边连接了一个NPN型的三极管,主要使用也就是

        • FAN置为1,打开电风扇
        • FAN置为0,打开电风扇

        至于,关于这个型号的三极管的具体功能,还有与PNP类型的三极管有啥区别?

        我就上网搜了一下问答,可以参考:NPN与PNP三极管的详解与区别

      或许……大家按照上面的写完代码之后发现……为啥我明明程序给它关了,这个仿真的风扇还在转着?!

      是我输入的时长不够吗?!FAN=0,FAN=0,FAN=0,FAN=0,……nm(不能爆粗口)还是不对……

      实质上吧,这个风扇的实际停止是根据它下面的显示方框中的数字来决定的

      • 当风扇开启的时候,这个数字会增长;
    • 当风扇关闭的时候,这个数字会下降;
      • 当为0.00的时候,自己就会停止。

    当然,不立即停止也是符合现实生活中的情形的,我认为这主要是因为继电器的问题,这个了解了一下是用来用弱电控制强电的(如果有兴趣的话,大家可以自行去了解)……

    当然,这个风扇的具体参数可以双击这个元件之后进去修改。

    5 实验参考代码

    下面给出参考代码,这里的控制标准是:

    • CH4浓度<20,则正常-绿色-风扇关闭-蜂鸣器关闭
    • CH4浓度>=20 & <40,则警示-黄色-风扇开启-蜂鸣器关闭
    • CH4浓度>=40,则危险-红色-风扇关闭-蜂鸣器开启
    #include <reg52.h> 
    #include <intrins.h>
    #include<math.h>
    #define NOP    _nop_()
    #define uint unsigned int
    #define uchar unsigned char
    #define ACK 1
    #define noACK 0
    #define DISPLAY_LEFT_TO_RIGHT    1 //从左边数计算列位置,每写完一个字节,列数自动向右移动一个
    #define DISPLAY_RIGHT_TO_LEFT    0 //从右边数计算列位置,每写完一个字节,列数自动向左移动一个
    
    //SHT10指令集
    //写状态寄存器
    #define STATUS_REG_W 0x06
    //读状态寄存器
    #define STATUS_REG_R 0x07
    //温度测量
    #define MEASURE_TEMP 0x03
    //湿度测量
    #define MEASURE_HUMI 0x05
    //软复位
    #define RESET 0x1E
    //枚举选择温度/湿度测量
    enum {TEMP,HUMI};
    //ADC0834
    sbit CS=P1^1;//ADC0834片选信号
    sbit CLK=P1^0;//ADC0834时钟信号
    //sbit SARS0834=P1^2;//转换状态输出,低电平表示转换完成
    sbit DO=P1^5;//ADC0834数据接口
    sbit DI=P1^4;//ADC0834通道选择
    //HDG12864F-1
    sbit cs1 = P2^4;//-cs,片选,低电平有效
    sbit rst = P2^3;//-rst,复位,低电平有效
    sbit a0 = P2^2;//写命令、写数据控制位。1=Display data; 0=Control data;
    sbit scl = P2^1;//Shift clock input,时钟输入
    sbit si = P2^0;//Serial data input,串口数据输入
    //SHT10
    sbit SCK=P1^2;
    sbit DATA=P1^3;
    //控制相关
    sbit LEDR=P1^6;
    sbit LEDG=P1^7;
    sbit FAN=P2^5;
    sbit BP=P2^6;
    //ADC
    unsigned int temp,humi;
    unsigned char ad_res = 0;
    unsigned char ad_res1 = 0;
    unsigned char ad_res2 = 0;
    unsigned char ad_res3 = 0;
    unsigned char ad_res4 = 0;
    double dat=0.0;
    //ADC0834通道切换
    unsigned int code channel0834[8]={0,0,1,0,0,1,1,1};
    //风扇
    uchar code pic_data1[]=
    {
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0xFC,0xFE,0xFE,0xFE,
    0xFE,0xFE,0xFE,0xFC,0xF8,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0xC0,0xF0,0xFC,0xFC,0xFE,0xFE,0xFE,0xFE,0xFC,0xFC,0xBC,0xE8,0xF7,0xFF,0xFF,
    0xFF,0xFF,0xFF,0xEF,0xEF,0xE3,0xF0,0xF0,0xF8,0xFC,0xFC,0xFC,0xF8,0xF0,0xC0,0x00,
    0x00,0x01,0x07,0x0F,0x1F,0x1F,0x1F,0x0F,0x07,0x07,0xE3,0xFB,0xFB,0xFF,0xFF,0xFF,
    0xFF,0xFF,0xF7,0x8F,0x0E,0x1F,0x1F,0x3F,0x3F,0x3F,0x3F,0x1F,0x0F,0x07,0x01,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x0F,0x1F,0x3F,0x3F,0x3F,
    0x3F,0x3F,0x3F,0x1F,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    };
    uchar code pic_data2[]=
    {0x00,0x80,0xE0,0xF0,0xF8,0xFC,0xFC,0xFC,0xFE,0xFE,0xFE,0xFE,0xFC,0xF8,0xF0,0xE0,
    0x00,0x00,0x00,0x80,0xF8,0xFC,0xFC,0xFE,0xFE,0xFC,0xFC,0xF8,0xF8,0xF0,0xC0,0x00,
    0x00,0x03,0x0F,0x1F,0x1F,0x1F,0x1F,0x1F,0x3F,0x3F,0x7F,0xDF,0xEF,0xF7,0xFF,0xFF,
    0xFF,0xF8,0xFC,0xFF,0xEF,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x7F,0x3F,0x1F,0x06,
    0x00,0xE0,0xF8,0xFC,0xFC,0xFE,0xFE,0xFF,0xFF,0xFF,0xFF,0xF7,0xEF,0xDF,0x3F,0x3F,
    0xFF,0xFF,0xDF,0xFF,0xFF,0xFB,0xFD,0xF9,0xF9,0xF0,0xF0,0xF0,0xF0,0xF0,0xC0,0x00,
    0x00,0x03,0x0F,0x1F,0x3F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x3F,0x1F,0x00,0x00,0x00,
    0x03,0x0F,0x1F,0x7F,0x7F,0xFF,0xFF,0xFF,0x7F,0x7F,0x7F,0x3F,0x1F,0x0F,0x07,0x00,
    };
    
    //字符库
    uchar code BMP[][6]=
    {
    //字符显示对应的二维十六进制数组
    {0x00,0x00,0x00,0x00,0x00,0x00}, //   0位  显示空白
    {0x00,0x00,0x00,0x00,0x00,0x00}, //   1
    {0x00,0x00,0x00,0x00,0x00,0x00}, //   2
    {0x00,0x00,0x00,0x00,0x00,0x00}, //   3
    {0x00,0x00,0x00,0x00,0x00,0x00}, //   4
    {0x00,0x00,0x00,0x00,0x00,0x00}, //   5
    {0x00,0x00,0x00,0x00,0x00,0x00}, //   6
    {0x00,0x00,0x00,0x00,0x00,0x00}, //   7
    {0x00,0x00,0x00,0x00,0x00,0x00}, //   8
    {0x00,0x00,0x00,0x00,0x00,0x00}, //   9
    {0x00,0x00,0x00,0x00,0x00,0x00}, //   10
    {0x00,0x00,0x00,0x00,0x00,0x00}, //   11
    {0x00,0x00,0x00,0x00,0x00,0x00}, //   12
    {0x00,0x00,0x00,0x00,0x00,0x00}, //   13
    {0x00,0x00,0x00,0x00,0x00,0x00}, //   14
    {0x00,0x00,0x00,0x00,0x00,0x00}, //   15
    {0x00,0x00,0x00,0x00,0x00,0x00}, //   16
    {0x00,0x00,0x00,0x00,0x00,0x00}, //   17
    {0x00,0x00,0x00,0x00,0x00,0x00}, //   18
    {0x00,0x00,0x00,0x00,0x00,0x00}, //   19
    {0x00,0x00,0x00,0x00,0x00,0x00}, //   20
    {0x00,0x00,0x00,0x00,0x00,0x00}, //   21
    {0x00,0x00,0x00,0x00,0x00,0x00}, //   22
    {0x00,0x00,0x00,0x00,0x00,0x00}, //   23
    {0x00,0x00,0x00,0x00,0x00,0x00}, //   24
    {0x00,0x00,0x00,0x00,0x00,0x00}, //   25
    {0x00,0x00,0x00,0x00,0x00,0x00}, //   26
    {0x00,0x00,0x00,0x00,0x00,0x00}, //   27
    {0x00,0x00,0x00,0x00,0x00,0x00}, //   28
    {0x00,0x00,0x00,0x00,0x00,0x00}, //   29
    {0x00,0x00,0x00,0x00,0x00,0x00}, //   30
    {0x00,0x00,0x00,0x00,0x00,0x00}, //   31
    {0x00,0x00,0x00,0x00,0x00,0x00}, // sp 32
    {0x00,0x00,0x2f,0x00,0x00,0x00},   // ! 33
    {0x00,0x07,0x00,0x07,0x00,0x00},   // " 34 
    {0x14,0x7f,0x14,0x7f,0x14,0x00},   // # 35
    {0x24,0x2a,0x7f,0x2a,0x12,0x00},   // $ 36
    {0xc4,0xc8,0x10,0x26,0x46,0x00},   // % 37
    {0x36,0x49,0x55,0x22,0x50,0x00},   // & 38 
    {0x00,0x05,0x03,0x00,0x00,0x00},   // ' 39
    {0x00,0x1c,0x22,0x41,0x00,0x00},   // ( 40
    {0x00,0x41,0x22,0x1c,0x00,0x00},   // ) 41
    {0x14,0x08,0x3E,0x08,0x14,0x00},   // * 42
    {0x08,0x08,0x3E,0x08,0x08,0x00},   // + 43
    {0x00,0x00,0x50,0x30,0x00,0x00},   // , 44
    {0x10,0x10,0x10,0x10,0x10,0x00},   // - 45
    {0x00,0x60,0x60,0x00,0x00,0x00},   // . 46
    {0x20,0x10,0x08,0x04,0x02,0x00},   // / 47
    {0x3E,0x51,0x49,0x45,0x3E,0x00},   // 0 48
    {0x00,0x42,0x7F,0x40,0x00,0x00},   // 1 49
    {0x42,0x61,0x51,0x49,0x46,0x00},   // 2 50
    {0x21,0x41,0x45,0x4B,0x31,0x00},   // 3 51
    {0x18,0x14,0x12,0x7F,0x10,0x00},   // 4 52
    {0x27,0x45,0x45,0x45,0x39,0x00},   // 5 53
    {0x3C,0x4A,0x49,0x49,0x30,0x00},   // 6 54
    {0x01,0x71,0x09,0x05,0x03,0x00},   // 7 55
    {0x36,0x49,0x49,0x49,0x36,0x00},   // 8 56
    {0x06,0x49,0x49,0x29,0x1E,0x00},   // 9 57
    {0x00,0x36,0x36,0x00,0x00,0x00},   // : 58
    {0x00,0x56,0x36,0x00,0x00,0x00},   // ; 59
    {0x08,0x14,0x22,0x41,0x00,0x00},   // < 60
    {0x14,0x14,0x14,0x14,0x14,0x00},   // = 61
    {0x00,0x41,0x22,0x14,0x08,0x00},   // > 62
    {0x02,0x01,0x51,0x09,0x06,0x00},   // ? 63
    {0x32,0x49,0x59,0x51,0x3E,0x00},   // @ 64
    {0x7E,0x11,0x11,0x11,0x7E,0x00},   // A 65
    {0x7F,0x49,0x49,0x49,0x36,0x00},   // B 66
    {0x3E,0x41,0x41,0x41,0x22,0x00},   // C 67
    {0x7F,0x41,0x41,0x22,0x1C,0x00},   // D 68
    {0x7F,0x49,0x49,0x49,0x41,0x00},   // E 69
    {0x7F,0x09,0x09,0x09,0x01,0x00},   // F 70
    {0x3E,0x41,0x49,0x49,0x7A,0x00},   // G 71
    {0x7F,0x08,0x08,0x08,0x7F,0x00},   // H 72
    {0x00,0x41,0x7F,0x41,0x00,0x00},   // I 73
    {0x20,0x40,0x41,0x3F,0x01,0x00},   // J 74
    {0x7F,0x08,0x14,0x22,0x41,0x00},   // K 75
    {0x7F,0x40,0x40,0x40,0x40,0x00},   // L 76
    {0x7F,0x02,0x0C,0x02,0x7F,0x00},   // M 77
    {0x7F,0x04,0x08,0x10,0x7F,0x00},   // N 78
    {0x3E,0x41,0x41,0x41,0x3E,0x00},   // O 79
    {0x7F,0x09,0x09,0x09,0x06,0x00},   // P 80
    {0x3E,0x41,0x51,0x21,0x5E,0x00},   // Q 81
    {0x7F,0x09,0x19,0x29,0x46,0x00},   // R 82
    {0x46,0x49,0x49,0x49,0x31,0x00},   // S 83
    {0x01,0x01,0x7F,0x01,0x01,0x00},   // T 84
    {0x3F,0x40,0x40,0x40,0x3F,0x00},   // U 85
    {0x1F,0x20,0x40,0x20,0x1F,0x00},   // V 86
    {0x3F,0x40,0x38,0x40,0x3F,0x00},   // W 87
    {0x63,0x14,0x08,0x14,0x63,0x00},   // X 88
    {0x07,0x08,0x70,0x08,0x07,0x00},   // Y 89
    {0x61,0x51,0x49,0x45,0x43,0x00},   // Z 90
    {0x00,0x7F,0x41,0x41,0x00,0x00},   // [ 91
    {0x55,0x2A,0x55,0x2A,0x55,0x00},   //55 92
    {0x00,0x41,0x41,0x7F,0x00,0x00},   // ] 93
    {0x04,0x02,0x01,0x02,0x04,0x00},   // ^ 94
    {0x40,0x40,0x40,0x40,0x40,0x00},   // _ 95
    {0x00,0x01,0x02,0x04,0x00,0x00},   // ' 96
    {0x20,0x54,0x54,0x54,0x78,0x00},   // a 97
    {0x7F,0x48,0x44,0x44,0x38,0x00},   // b 98
    {0x38,0x44,0x44,0x44,0x20,0x00},   // c 99
    {0x38,0x44,0x44,0x48,0x7F,0x00},   // d 100
    {0x38,0x54,0x54,0x54,0x18,0x00},   // e 101
    {0x08,0x7E,0x09,0x01,0x02,0x00},   // f 102 
    {0x0C,0x52,0x52,0x52,0x3E,0x00},   // g 103 
    {0x7F,0x08,0x04,0x04,0x78,0x00},   // h 104
    {0x00,0x44,0x7D,0x40,0x00,0x00},   // i 105
    {0x20,0x40,0x44,0x3D,0x00,0x00},   // j 106
    {0x7F,0x10,0x28,0x44,0x00,0x00},   // k 107
    {0x00,0x41,0x7F,0x40,0x00,0x00},   // l 108
    {0x7C,0x04,0x18,0x04,0x78,0x00},   // m 109
    {0x7C,0x08,0x04,0x04,0x78,0x00},   // n 110
    {0x38,0x44,0x44,0x44,0x38,0x00},   // o 111
    {0x7C,0x14,0x14,0x14,0x08,0x00},   // p 112
    {0x08,0x14,0x14,0x18,0x7C,0x00},   // q 113
    {0x7C,0x08,0x04,0x04,0x08,0x00},   // r 114
    {0x48,0x54,0x54,0x54,0x20,0x00},   // s 115
    {0x04,0x3F,0x44,0x40,0x20,0x00},   // t 116
    {0x3C,0x40,0x40,0x20,0x7C,0x00},   // u 117
    {0x1C,0x20,0x40,0x20,0x1C,0x00},   // v 118
    {0x3C,0x40,0x30,0x40,0x3C,0x00},   // w 119
    {0x44,0x28,0x10,0x28,0x44,0x00},   // x 120
    {0x0C,0x50,0x50,0x50,0x3C,0x00},   // y 121
    {0x44,0x64,0x54,0x4C,0x44,0x00},   // z 122
    {0xD5,0x01,0x80,0x01,0x80,0xAB},  // <50        123
    {0xFF,0x81,0x81,0x81,0x81,0xFF},  //50<= <100   124
    {0xFF,0x81,0xBD,0xBD,0x81,0xFF},  //100<= <150  125
    {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},  //>=150       126
    {0x00,0x00,0x00,0x00,0x00,0x00}   // sp         127
    };
    
    unsigned char code myChannel[7]={'C','h','a','n','n','e','l'};
    unsigned char code myTemp[4]={'T','e','m','p'};
    unsigned char code myHumi[4]={'H','u','m','i'};
    unsigned char code myCO[2]={'C','O'};
    unsigned char code myCH4[3]={'C','H','4'};
    unsigned char code myLight[5]={'L','i','g','h','t'};
    unsigned char code myAir[7]={'A','i','r','-','p','r','e'};
    unsigned char code **msg[7]={myChannel,myTemp,myHumi,myCO,myCH4,myLight,myAir};
    
    //延时函数
    void Delayms(uint x )
    {
    	uint t; 
    	while(x--) 
    		for (t= 0; t<120; t++);
    }
    
    //HDG12864F-1
    //写命令
    void wrt_cmd(unsigned char command)
    {
        unsigned char i = 8;//8位
        cs1 = 0;//片选,低电平有效
        a0 = 0;//0=Control data,命令置0
        while(i--)
    	{
    		scl = 0;
    		si = (bit) (command & 0x80);//先写高位
    		scl = 1;//上升沿
    		command <<= 1;//左移一位
        }
        scl = 0;
    }
    //写数据
    void wrt_dt(unsigned char data_)
    {
        unsigned char i = 8;//8位
        cs1 = 0;//片选,低电平有效
        a0 = 1;//1=Display data,写数据置1
        while(i--)
    	{
    		scl = 0;
    		si = (bit) (data_ & 0x80);//先写高位
    		scl = 1;//上升沿
    		data_ <<= 1;//左移一位				     0
        }
        scl = 0;
    }
    //设置列位置,其中参数address:0~127
    void HDG12864F1_SetColumnAddress(unsigned char address)
    {	//写列要分成两步走,先写高四位,再写低四位
    	//手册Column Address Set
    	wrt_cmd(0x10 + (address >> 4 & 0x0f));//C中右移是算术右移,必须&0x0f去掉高4位才能得到正确的结果
    	wrt_cmd(address & 0x0f);
    }
    //设置纵向位置,其中参数pageAddress:0~8
    void HDG12864F1_SetPageAddress(unsigned char pageAddress)
    {	//手册Page Address Set
        wrt_cmd(0xb0 + pageAddress);//1011+页码
    }
    //写数据
    void HDG12864F1_WriteData(unsigned char data_)
    {
        wrt_dt(data_);
    }
    //设置写的方向:从右向左为正
    void HDG12864F1_Direction(unsigned char direction)
    {	//手册ADC Select
        wrt_cmd(0xa0+direction);
    }
    //对写好的屏幕内容向上滚屏,滚出上边的部分会从屏幕下边冒出来
    void HDG12864F1_SetStartLine(unsigned char line)
    {	//参数line取值范围0~63
        wrt_cmd(0x40 + line);
    }
    
    //写英文字符,数字占上下1个8*6点阵
    void HDG12864F1_WriteEnglishChar(unsigned char *pEChar, unsigned char column, unsigned char page)
    {
        unsigned char i;
        HDG12864F1_Direction(DISPLAY_LEFT_TO_RIGHT);//DISPLAY_LEFT_TO_RIGHT是一个宏,值为1,代表从屏幕左侧写入
        HDG12864F1_SetColumnAddress(column);//设开始写的横向坐标
        HDG12864F1_SetPageAddress(page);//设开始写的纵向Page
        for(i=0; i<6; i++)
    		HDG12864F1_WriteData(*(pEChar + i));//连续写英文
    }
    //图片32*32
    void HDG12864F1_DrawPic(unsigned char *pChar, unsigned char column, unsigned char page)
    {
    	unsigned char i,j;
        HDG12864F1_Direction(DISPLAY_LEFT_TO_RIGHT);//DISPLAY_LEFT_TO_RIGHT是一个宏,值为1,代表从屏幕左侧写入
        for(i=0;i<4;i++)
    	{
    		HDG12864F1_SetColumnAddress(column);//设开始写的横向坐标
        	HDG12864F1_SetPageAddress(page+i);//设开始写的纵向Page
    		for(j=0;j<32;j++)
    		{
    			HDG12864F1_WriteData(*(pChar + i*32+j));//连续写英文
    		}
    	}
    }
    
    //ADC0834
    unsigned char AD0834_conv(unsigned int n)
    {
    	unsigned char i,com;
    	CS=1;
    	CS=0;	_nop_();	_nop_();//CS置低,启动转换
    	DI=1; 	_nop_();	_nop_();//启动,准备输出数据 第一个脉冲
    	CLK=1;	_nop_();	_nop_();
    	CLK=0;	_nop_();	_nop_();
    	//选择通道,第二个脉冲
    	DI=1;
    	CLK=1;	_nop_();	_nop_();	
    	CLK=0;	_nop_();	_nop_();
    
    	DI=channel0834[n*2];
    	CLK=1;	_nop_();	_nop_();
    	CLK=0;	_nop_();	_nop_();
    
    	DI=channel0834[n*2+1];
    	CLK=1;	_nop_();	_nop_();
    	CLK=0;	_nop_();	_nop_();
    
    	DI=1;
    	CLK=1;	_nop_();	_nop_();
    	CLK=0;	_nop_();	_nop_();
    	
    	//开始采集转换数据	
    	for(i=8;i>0;i--)
    	{	
    		com<<=1;//左移,先采最高位
    		if(DO)com=com|0x01;//采当前数据
    		CLK=1;
    		CLK=0;
    		_nop_();
    	    _nop_();	
    	}	
    	CS=1;//关闭片选,禁用
    	return com;
    }
    
    //LDR传感器数据拟合
    unsigned char ChangeDataLDR(unsigned char res)
    {
    	unsigned char com;
    	com=0.00000000221308*res*res*res*res*res
    		-0.0000009287723*res*res*res*res 
    		+ 0.0001465584*res*res*res 
    		- 0.008997464*res*res 
    		+ 0.2657836*res - 0.5918848;
    	return com;
    }
    
    //MPX4115传感器数据拟合
    unsigned char ChangeDataMPX(unsigned char res)
    {
    	unsigned char com;
    	//自己拟合
    	com=0.436*res+9.053;
    	return com;
    }
    
    //SHT10
    //写字节
    char s_write_byte(uchar value)
    {
    	uchar i,error=0;
    	//分别取出指令的对应位串传输
    	//从高位开始
    	for(i=0x80;i>0;i>>=1)
    	{
    		if(i&value) DATA=1;
    		else DATA=0;
    		SCK=1;
    		//保持SCK高电平
    		_nop_();_nop_();_nop_();
    		SCK=0;
    	}
    	DATA=1;
    	SCK=1;
    	error=DATA;//ACK
    	_nop_();_nop_();_nop_();
    	SCK=0;
    	DATA=1;
    	return  error;		
    }
    
    //读字节
    char s_read_byte(uchar ack)
    {
    	uchar i,val=0;
    	DATA=1;
    	//读取一个字节的数据
    	for(i=0x80;i>0;i>>=1)
    	{
    		SCK=1;
    		if(DATA) val=(val|i);
    		SCK=0;
    	}
    	if(ack==1)DATA=0;//通过下拉DATA为低电平以确认每个字节
    	else DATA=1;  //如果是校验 (ack==0) ,读取完后保持ACK高电平结束通讯
    	_nop_();_nop_();_nop_();  //pulswith approx. 3 us
    	SCK=1;  //clk #9 for ack
    	_nop_();_nop_();_nop_();  //pulswith approx. 3 us
    	SCK=0;
    	_nop_();_nop_();_nop_();  //pulswith approx. 3 us
    	DATA=1;  //释放DATA-line
    	return val;
    }
    
    //启动传输
    void s_transstart(void)
    {
    	DATA=1; SCK=0;
    	_nop_();
    	SCK=1;
    	_nop_();
    	DATA=0;
    	_nop_();
    	SCK=0;
    	_nop_();_nop_();_nop_();
    	SCK=1;
    	_nop_();
    	DATA=1;
    	_nop_();
    	SCK=0;
    }
    
    //连接复位
    void s_connectionreset(void)
    {
    //通讯中断需要通讯复位
    //DATA保持高电平并触发SCK时钟9次或更多
    	uchar i;
    	DATA=1;SCK=0;
    	for(i=0;i<9;i++)
    	{
    		SCK=1;
    		SCK=0;
    	}
    //发送一个传输启动时序
    	s_transstart();
    //复位串口而状态寄存器内容仍然保留
    }
    
    //温湿度测量
    char s_measure(uchar *p_value,uchar *p_checksum,uchar mode)
    {
    	unsigned error=0;
    	unsigned int i;
    
    	s_transstart();
    	switch(mode)
    	{
    		case TEMP:
    			error+=s_write_byte(MEASURE_TEMP); break;
    		case HUMI:
    			error+=s_write_byte(MEASURE_HUMI); break;
    		default: break;
    	}
    	//在结束测量后Sensor会把DATA线拉低
    	//等待测量结束时间根据不同位数的测量不同
    	for(i=0;i<65535;i++) if(DATA==0) break;//2^16
    	if(DATA) error+=1;//说明没有结束
    	//传输2个字节的测量数据和1个字节的CRC奇偶校验
    	*(p_value)=s_read_byte(ACK);
    	*(p_value+1)=s_read_byte(ACK);
    	*p_checksum=s_read_byte(noACK);
    	return error;
    }
    
    //温湿度值标度变换及温度补偿
    void calc_sth10(float *p_humidity,float *p_temperature)
    {
    // input :  humi [Ticks] (12 bit)
    // temp [Ticks] (14 bit)
    // output:  humi [%RH]
    	const float C1=-2.0468;	// for 12 Bit
    	const float C2=+0.0367;	    // for 12 Bit
    	const float C3=-0.0000015955;	// for 12 Bit
    	const float T1=+0.01;		// for 12 Bit @ 5V
    	const float T2=+0.00008;	// for 12 Bit @ 5V
    	float rh=*p_humidity;// rh:  Humidity [Ticks] 12 Bit
    	float t=*p_temperature;	// t:  Temperature [Ticks] 14 Bit
    	float rh_lin;// rh_lin:  Humidity linear
    	float rh_ture;// rh_true: Temperature compensated humidity
    	float t_C;// t_C  :  Temperature [C]
    	t_C=t*0.01-40;//温度转换[C]
    	rh_lin=C3*rh*rh+C2*rh+C1;//相对湿度非线性补偿[%RH]
    	rh_ture=(t_C-25)*(T1+T2*rh)+rh_lin;//湿度信号的温度补偿[%RH]
    	//超范围处理
    	if(rh_ture>100) rh_ture=100;
    	if(rh_ture<0.1) rh_ture=0.1;
    	//将结果传输回去
    	*p_temperature=t_C;//[C]
    	*p_humidity=rh_ture;//[%RH]
    }
    
    
    typedef union
    {
     unsigned int i;
     float f;
    }value;
    
    void main(void)
    {
       int i=0;
       int j=0;
    	int mycol=0;
       value humi_val,temp_val;
       uchar error;
    	uchar check_sum;//校验和
    	int flag;//判断温度符号
    	BP=0;
    	FAN=0;
       while(1)
    	{
    	mycol=0;
    	for(i=0;i<7;i++)
    		HDG12864F1_WriteEnglishChar(BMP[myChannel[i]],i*8,mycol);
    	HDG12864F1_WriteEnglishChar(BMP[':'],7*8,mycol);
    	HDG12864F1_WriteEnglishChar(BMP['A'],8*8,mycol);
    	mycol=mycol+1;
    	//温湿度
     	  error=0;
    	  error+=s_measure((uchar*)&humi_val.i,&check_sum,HUMI);
    	  error+=s_measure((uchar*)&temp_val.i,&check_sum,TEMP);
    	  
    	  if(error!=0)//说明通讯中断且没有测量完
    	  	s_connectionreset();
    	  else//已经测量完
    	  {
    	  	humi_val.f=(float)humi_val.i;
    		temp_val.f=(float)temp_val.i;
    		//温湿度补偿
    		calc_sth10(&humi_val.f,&temp_val.f);
    		//判断符号
    		if(temp_val.f<0)
    		{
    			flag='-';
    			temp_val.f=-temp_val.f+2;
    		}
    		else
    			flag='+';
    		//可以显示小数位后一位
    		temp=temp_val.f*10;
    	    humi=humi_val.f*10;			 
    	  }
    	//温度
    	for(i=0;i<4;i++)
    		HDG12864F1_WriteEnglishChar(BMP[myTemp[i]],i*8,mycol);
    	HDG12864F1_WriteEnglishChar(BMP[':'],4*8,mycol);
    	HDG12864F1_WriteEnglishChar(BMP[flag],5*8,mycol);
    	HDG12864F1_WriteEnglishChar(BMP[temp/1000+'0'],6*8,mycol);
    	HDG12864F1_WriteEnglishChar(BMP[temp%1000/100+'0'],7*8,mycol);
    	HDG12864F1_WriteEnglishChar(BMP[temp%100/10+'0'],8*8,mycol);
    	HDG12864F1_WriteEnglishChar(BMP['C'],9*8,mycol);
    	mycol=mycol+1;
    	//湿度
    	for(i=0;i<4;i++)
    		HDG12864F1_WriteEnglishChar(BMP[myHumi[i]],i*8,mycol);
    	HDG12864F1_WriteEnglishChar(BMP[':'],4*8,mycol);
    	HDG12864F1_WriteEnglishChar(BMP[humi/1000+'0'],5*8,mycol);
    	HDG12864F1_WriteEnglishChar(BMP[humi%1000/100+'0'],6*8,mycol);
    	HDG12864F1_WriteEnglishChar(BMP[humi%100/10+'0'],7*8,mycol);
    	HDG12864F1_WriteEnglishChar(BMP['%'],8*8,mycol);
    	mycol=mycol+1;
    
    	ad_res=AD0834_conv(0);
    	ad_res1=ad_res;
    	for(i=0;i<5;i++)
    		HDG12864F1_WriteEnglishChar(BMP[myLight[i]],i*8,mycol);
    	HDG12864F1_WriteEnglishChar(BMP[':'],5*8,mycol);
    	HDG12864F1_WriteEnglishChar(BMP[ad_res1%1000/100+'0'],6*8,mycol);
    	HDG12864F1_WriteEnglishChar(BMP[ad_res1%100/10+'0'],7*8,mycol);
    	HDG12864F1_WriteEnglishChar(BMP[ad_res1%10+'0'],8*8,mycol);
    	HDG12864F1_WriteEnglishChar(BMP['L'],9*8,mycol);
    	HDG12864F1_WriteEnglishChar(BMP['x'],10*8,mycol);
    	mycol=mycol+1;
    
    	ad_res=AD0834_conv(1);
    	ad_res2=ChangeDataLDR(ad_res);
    	for(i=0;i<2;i++)
    		HDG12864F1_WriteEnglishChar(BMP[myCO[i]],i*8,mycol);
    	HDG12864F1_WriteEnglishChar(BMP[':'],2*8,mycol);
    	HDG12864F1_WriteEnglishChar(BMP[ad_res2%1000/100+'0'],3*8,mycol);
    	HDG12864F1_WriteEnglishChar(BMP[ad_res2%100/10+'0'],4*8,mycol);
    	HDG12864F1_WriteEnglishChar(BMP[ad_res2%10+'0'],5*8,mycol);
    	HDG12864F1_WriteEnglishChar(BMP['p'],6*8,mycol);
    	HDG12864F1_WriteEnglishChar(BMP['p'],7*8,mycol);
    	HDG12864F1_WriteEnglishChar(BMP['m'],8*8,mycol);
    	mycol=mycol+1;
    
    	ad_res=AD0834_conv(2);
    	ad_res3=ChangeDataLDR(ad_res);
    	//控制RGB-LED与BP与FAN
    	if(ad_res3<20)//正常-绿色-风扇关闭-蜂鸣器关闭
    	{
    		LEDR=0;
    		LEDG=1;
    		BP=0;
    		FAN=0;
    	}
    	else if(ad_res3>=20 & ad_res3<40)//警示-黄色-风扇开启-蜂鸣器关闭
    	{
    		LEDR=1;
    		LEDG=1;
    		BP=0;
    		FAN=1;
    	}
    	else//危险-红色-风扇关闭-蜂鸣器开启
    	{
    		LEDR=1;
    		LEDG=0;
    		BP=1;
    		FAN=0;
    	}
    	for(i=0;i<3;i++)
    		HDG12864F1_WriteEnglishChar(BMP[myCH4[i]],i*8,mycol);
    	HDG12864F1_WriteEnglishChar(BMP[':'],3*8,mycol);
    	HDG12864F1_WriteEnglishChar(BMP[ad_res3%1000/100+'0'],4*8,mycol);
    	HDG12864F1_WriteEnglishChar(BMP[ad_res3%100/10+'0'],5*8,mycol);
    	HDG12864F1_WriteEnglishChar(BMP[ad_res3%10+'0'],6*8,mycol);
    	HDG12864F1_WriteEnglishChar(BMP['p'],7*8,mycol);
    	HDG12864F1_WriteEnglishChar(BMP['p'],8*8,mycol);
    	HDG12864F1_WriteEnglishChar(BMP['m'],9*8,mycol);
    	mycol=mycol+1;
    
    	ad_res=AD0834_conv(3);
    	ad_res4=ChangeDataMPX(ad_res);
    	for(i=0;i<7;i++)
    		HDG12864F1_WriteEnglishChar(BMP[myAir[i]],i*8,mycol);
    	HDG12864F1_WriteEnglishChar(BMP[':'],7*8,mycol);
    	HDG12864F1_WriteEnglishChar(BMP[ad_res4%1000/100+'0'],8*8,mycol);
    	HDG12864F1_WriteEnglishChar(BMP[ad_res4%100/10+'0'],9*8,mycol);
    	HDG12864F1_WriteEnglishChar(BMP[ad_res4%10+'0'],10*8,mycol);
    	HDG12864F1_WriteEnglishChar(BMP['k'],11*8,mycol);
    	HDG12864F1_WriteEnglishChar(BMP['P'],12*8,mycol);
    	HDG12864F1_WriteEnglishChar(BMP['a'],13*8,mycol);
    	//转动的风扇
    	HDG12864F1_DrawPic(&pic_data1,90,0);
    	Delayms(800);//延时显示
    	HDG12864F1_DrawPic(&pic_data2,90,0);
    	Delayms(700);//延时显示
        }
    }
    

    其中,HDG12864F-1部分的程序是参考:使用Proteus模拟操作HDG12864F-1液晶屏

  • 相关阅读:
    重要的API运算函数
    Chicken的代码解剖 :4 ChickenPawn_Chicken一小部分
    Chicken的代码解剖:5 Chicken中的两个接口及其相关
    项目实例:深投控股star rating评分插件
    项目实例:深投控股JQueryXmlMenu
    编程经验:VS2008注册方法
    编程经验:SQL Server Management Studio使用注意事项
    程序员面试题精选100题(07)翻转句子中单词的顺序
    程序员面试100题精选(8)
    Ogre框架的搭建过程
  • 原文地址:https://www.cnblogs.com/liujiaxin-alpha/p/12858783.html
Copyright © 2011-2022 走看看