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液晶屏


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM