|
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
ADC用的TLC2543
單片機源程序如下:- #include <reg51.h>
- #include "lcd.h"
- #include "UART.h"
- #include "Delay.h"
- #include <intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- #define ulong unsigned long
- #define NACK 0
- #define ACK 1
- #define MEASURE_TEMP 0x03 //000 0001 1
- #define MEASURE_HUMI 0x05 //000 0010 1
- #define STATUS_REG_W 0x06 //000 0011 0
- #define STATUS_REG_R 0x07 //000 0011 1
- #define RESET 0x1E //000 1111 0
- ulong volt;//測量的電壓值
- sbit Data=P2^3; //定義數據線
- sbit CLK=P3^3;//定義時鐘信號口
- sbit DIN=P3^4;//定義2543數據寫入口
- sbit DOUT=P3^5;//定義2543數據讀取口
- sbit CS=P3^2;//定義2543片選信號口
- sbit Data_P = P2^4; // SHT11傳感器的數據管腳
- sbit Sck_P = P2^3; // SHT11傳感器的時鐘管腳
- sbit BEEP =P2^5;
- uchar tmpe,h;
- uchar rec_dat[9]; //用于顯示的接收數據數組
- uchar temp_max = 50;
- ulong C2_max = 7500000;
- ulong LUX_max = 8500000;
- ulong C2_now = 0;
- ulong LUX_now = 0;
- unsigned char temp; // 保存溫度
- unsigned char humi; // 保存濕度
- enum { TEMP,HUMI };
- typedef union //定義共用同類型
- {
- unsigned int i;
- float f;
- }value;
- int display = 0;
- void delay(uchar ms)
- { // 延時子程序
- uchar i;
- while(ms--)
- {
- for(i = 0;i<250;i++);
- }
- }
- char ShtWriteByte(unsigned char value)
- {
- unsigned char i,error=0;
- for(i=128;i>0;i>>=1) // 高位為1,循環右移
- {
- if (i&value)
- Data_P=1; // 和要發送的數相與,結果為發送的位
- else
- Data_P=0;
- Sck_P=1;
- _nop_(); // 延時3us
- _nop_();
- _nop_();
- Sck_P=0;
- }
- Data_P=1; // 釋放數據線
- Sck_P=1;
- error=Data_P; // 檢查應答信號,確認通訊正常
- _nop_();
- _nop_();
- _nop_();
- Sck_P=0;
- Data_P=1;
- return error; // error=1 通訊錯誤
- }
- char ShtReadByte(unsigned char ack)
- {
- unsigned char i,val=0;
- Data_P=1; // 釋放數據線
- for(i=0x80;i>0;i>>=1) // 高位為1,循環右移
- {
- Sck_P=1;
- if(Data_P)
- val=(val|i); // 讀一位數據線的值
- Sck_P=0;
- }
- Data_P=!ack; // 如果是校驗,讀取完后結束通訊
- Sck_P=1;
- _nop_(); // 延時3us
- _nop_();
- _nop_();
- Sck_P=0;
- _nop_();
- _nop_();
- _nop_();
- Data_P=1; // 釋放數據線
- return val;
- }
- void ShtTransStart(void)
- {
- Data_P=1;
- Sck_P=0;
- _nop_();
- Sck_P=1;
- _nop_();
- Data_P=0;
- _nop_();
- Sck_P=0;
- _nop_();
- _nop_();
- _nop_();
- Sck_P=1;
- _nop_();
- Data_P=1;
- _nop_();
- Sck_P=0;
- }
- void ShtConnectReset(void)
- {
- unsigned char i;
- Data_P=1; //準備
- Sck_P=0;
- for(i=0;i<9;i++) //DATA保持高,SCK時鐘觸發9次,發送啟動傳輸,通迅即復位
- {
- Sck_P=1;
- Sck_P=0;
- }
- ShtTransStart(); //啟動傳輸
- }
- char ShtMeasure(unsigned char *p_value, unsigned char *p_checksum, unsigned char mode)
- {
- unsigned error=0;
- unsigned int i;
- ShtTransStart(); // 啟動傳輸
- switch(mode) // 選擇發送命令
- {
- case 1 : // 測量溫度
- error+=ShtWriteByte(0x03);
- break;
- case 2 : // 測量濕度
- error+=ShtWriteByte(0x05);
- break;
- default:
- break;
- }
- for(i=0;i<65535;i++)
- if(Data_P==0)
- break; // 等待測量結束
- if(Data_P)
- error+=1; // 如果長時間數據線沒有拉低,說明測量錯誤
- *(p_value) =ShtReadByte(1); // 讀第一個字節,高字節 (MSB)
- *(p_value+1)=ShtReadByte(1); // 讀第二個字節,低字節 (LSB)
- *p_checksum =ShtReadByte(0); // read CRC校驗碼
- return error; // error=1 通訊錯誤
- }
- void CalcSHT11(float *p_humidity ,float *p_temperature)
- {
- const float C1=-4.0; // 12位濕度精度 修正公式
- const float C2=+0.0405; // 12位濕度精度 修正公式
- const float C3=-0.0000028; // 12位濕度精度 修正公式
- const float T1=+0.01; // 14位溫度精度 5V條件 修正公式
- const float T2=+0.00008; // 14位溫度精度 5V條件 修正公式
- float rh=*p_humidity; // rh: 12位 濕度
- float t=*p_temperature; // t: 14位 溫度
- float rh_lin; // rh_lin: 濕度 linear值
- float rh_true; // rh_true: 濕度 ture值
- float t_C; // t_C : 溫度 ℃
- t_C=t*0.01 - 40; //補償溫度
- rh_lin=C3*rh*rh + C2*rh + C1; //相對濕度非線性補償
- rh_true=(t_C-25)*(T1+T2*rh)+rh_lin; //相對濕度對于溫度依賴性補償
- *p_temperature=t_C; //返回溫度結果
- *p_humidity=rh_true; //返回濕度結果
- }
- unsigned char TempCorrect(int temp)
- {
- if(temp<0) temp=0;
- if(temp>970) temp=970;
- if(temp>235) temp=temp+10;
- if(temp>555) temp=temp+10;
- if(temp>875) temp=temp+10;
- temp=(temp%1000)/10;
- return temp;
- }
- unsigned char HumiCorrect(unsigned int humi)
- {
- if(humi>999) humi=999;
- if((humi>490)&&(humi<951)) humi=humi-10;
- humi=(humi%1000)/10;
- return humi+4;
- }
- void ReadShtData()
- {
- value humi_val,temp_val; // 定義兩個共同體,一個用于濕度,一個用于溫度
- unsigned char error; // 用于檢驗是否出現錯誤
- unsigned char checksum; // CRC
- unsigned int temp1,humi1; // 臨時讀取到的溫濕度數據
- error=0; //初始化error=0,即沒有錯誤
- error+=ShtMeasure((unsigned char*)&temp_val.i,&checksum,1); //溫度測量
- error+=ShtMeasure((unsigned char*)&humi_val.i,&checksum,2); //濕度測量
- if(error!=0) //如果發生錯誤,系統復位
- ShtConnectReset();
- else
- {
- humi_val.f=(float)humi_val.i; //轉換為浮點數
- temp_val.f=(float)temp_val.i; //轉換為浮點數
- CalcSHT11(&humi_val.f,&temp_val.f); //修正相對濕度及溫度
- temp1=temp_val.f*10;
- temp=TempCorrect(temp1);
- humi1=humi_val.f*10-50;
- humi=HumiCorrect(humi1);
- humi1=humi1-1;
- }
- }
- void read2543(uchar addr)
- {
- uint ad=0;
- uchar i;
- CLK=0;
- CS=0;//片選段,啟動2543
- addr<<=4;//對地址位預處理
- for(i=0;i<12;i++) //12個時鐘走完,完成一次讀取測量
- {
- if(DOUT==1)
- ad=ad|0x01;//單片機讀取ad數據
- DIN=addr&0x80;//2543讀取測量地址位
- CLK=1;
- ;;;//很短的延時
- CLK=0;//產生下降沿,產生時鐘信號
- ;;;
- addr<<=1;
- ad<<=1;//將數據移位準備下一位的讀寫
- }
- CS=1;//關2543
- ad>>=1;
- volt=ad;//取走轉換結果
- volt=volt*1221;//例子的滿量程為5V,轉換分辯率為12位(2的12次方=4096) 。即最大值是255,5/4096=1221mV,即例子中的1V代表實際1221mV
- }
- void main(void)
- {
- LcdInit();
- ShtConnectReset();
- UART_Init();
-
- while(1)
- {
- ReadShtData();
- DisplayListChar(4,0,"temp:");
- DisplayOneChar(10,0,(char)(temp/10+'0'));
- DisplayOneChar(11,0,(char)(temp%10+'0'));
- DisplayOneChar(12,0,(char)(' '));
- DisplayOneChar(13,0,(char)('C'));
- Uart1Send( 'T' );
- Uart1Send( (char)(temp/10+'0') );
- Uart1Send( (char)(temp%10+'0') );
-
- read2543(0);//調用2543驅動程序測量地址為
- LUX_now=volt*2;
- DisplayListChar(0,1,"ZD:");
- DisplayOneChar(3,1,(char)(volt*2/1000000+'0'));
- DisplayOneChar(4,1,(char)((volt*2/100000)%10+'0'));
- DisplayOneChar(6,1,(char)('%'));
- Uart1Send( 'Z' );
- Uart1Send( (char)(volt*2/1000000+'0') );
- Uart1Send( (char)((volt*2/100000)%10+'0') );
- read2543(1);//調用2543驅動程序測量地址為
- C2_now=volt*2;
- DisplayListChar(10,1,"PH:");
- DisplayOneChar(13,1,(char)(volt*2/1000000+'0'));
- DisplayOneChar(14,1,(char)('.'));
- DisplayOneChar(15,1,(char)((volt*2/100000)%10+'0'));
- Uart1Send( 'P' );
- Uart1Send( (char)(volt*2/1000000+'0') );
- Uart1Send( '.' );
- Uart1Send( (char)((volt*2/100000)%10+'0') );
-
- if(LUX_now>LUX_max || C2_now>C2_max || temp>temp_max)
- {
-
- BEEP=0;
- }else
- {
- BEEP=1;
- }
- }
- }
復制代碼 下載:
|
-
-
軟件.rar
2024-3-14 18:53 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
73.95 KB, 下載次數: 25, 下載積分: 黑幣 -5
-
-
硬件.rar
2024-3-14 18:53 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
92.29 KB, 下載次數: 21, 下載積分: 黑幣 -5
評分
-
查看全部評分
|