|
40黑幣
我采用TSW-30濁度傳感器,利用51單片機(jī)做了一個水質(zhì)監(jiān)測系統(tǒng),AD用的是PCF8591,用LCD1602顯示,但是顯示過程中總是顯示0(最小值),3000(最大值),然后是一些數(shù)字在變化,例如,1180,3000,1135,3000,1101,3000,不管是在清水中,還是在濁水中變化都一樣,且模擬輸入電壓在不同的濁度水中變化明顯,以下是程序資料,求諸位大神幫幫我
公式圖
公式圖
- /********************(C) COPRIGHT 2019 Crownto electronic **************************
- * 文件名 :main.c
- * 描述 :
- * 硬件連接:
- * PCF8591:VCC -> 5V; GND -> GND; SCL -> P1.6;SDA -> P1.7;
- * OUT1~OUT8 -> P3口
- * LCD1602:RS -> P2.5; RW -> P2.6; E -> P2.7;
- * D0~D7 -> P0口
- * 濁度傳感器模塊: VCC -> 5V; GND -> GND; AO -> AIN0;
- *
- * 功能描述:測量濁度值液晶顯示;
- 串口接收測量所得的濁度值(波特率9600);
- * 可連接上位機(jī)顯示濁度值;
- **********************************************************************************/
- #include <reg52.h>
- #include <include.h>
- typedef unsigned char uchar;
- typedef unsigned char uint;
- /**************外部變量定義************************/
- int num=0;
- /**************變量定義***************************/
- //double PH=0.0;
- //unsigned char disbuff[5]={0};
- double ADC_Voltage=0.0;
- float TU=0.0;
- float TU_value=0.0;
- float TU_calibration=0.0;
- unsigned char disbuff[13]={0};
- float temp_data=25.0;
- float K_Value=3047.19;
- /*
- * 函數(shù)名:Get_Voltage_Value
- * 描述 :獲取ADC0809的轉(zhuǎn)換電壓值
- *
- * 輸入 :無
- * 輸出 :無
- * 說明 :
- * AIN0(0X40):熱敏電阻
- * AIN1(0X41):懸空
- * AIN2(0X42):滑動變阻器
- * AIN3(0X43):光敏電阻
- */
- void Get_Voltage_Value()
- {
- ISendByte(PCF8591,0x40);
- num=IRcvByte(PCF8591); //ADC0 模數(shù)轉(zhuǎn)換1 PH電極
- // TU =num * 5.0/ 255; //轉(zhuǎn)換為電壓值
- }
- /*
- * 函數(shù)名:Character_Conversion
- * 描述 :延時函數(shù)
- *
- * 輸入 :unsigned char n:延時量
- * 輸出 :無
- * 說明 :
- */
- void TU_Value_Conversion()
- {
- Get_Voltage_Value();
- TU=(num*5.0)/256;
- TU_calibration=-0.0192*(temp_data-25)+TU;
- TU_value=-865.68*TU_calibration + K_Value;
-
- if(TU_value<=0){TU_value=0;}
- if(TU_value>=3000){TU_value=3000;}
-
- /*顯示酸堿度*/
- disbuff[0]=(int)(TU_value)/1000+'0';
- disbuff[1]=(int)(TU_value)%1000/100+'0';
- disbuff[2]=(int)(TU_value)%100/10+'0';
- disbuff[3]=(int)(TU_value)%10+'0';
-
-
- DisplaySingleChar(0x03,0,disbuff[0]);
- DisplaySingleChar(0x04,0,disbuff[1]);
- DisplaySingleChar(0x05,0,disbuff[2]);
- DisplaySingleChar(0x06,0,disbuff[3]);
- }
- void StartUART( void )
- { //波特率9600
- SCON = 0x50;
- TMOD = 0x20;
- TH1 = 0xFD;
- TL1 = 0xFD;
- PCON = 0x00;
- TR1 = 1;
- }
- //**********通過串口將接收到數(shù)據(jù)發(fā)送給PC端**************
- void R_S_Byte(uchar R_Byte)
- {
- SBUF = R_Byte;
- while( TI == 0 ); //查詢法
- TI = 0;
- }
- /*
- * 函數(shù)名:main
- * 描述 :主函數(shù)
- * 輸入 :無
- * 輸出 :無
- */
- void main(void)
- {
- int i;
- LCDInit();
- StartUART();
-
- DisplayString(0x0,0," Welcome TU ");
- DisplayString(0x0,1,"Detection system");
- delay_1s();
- WriteCmd(LCD_CLS);
-
- DisplayString(0x0,0,"TU=");
- DisplaySingleChar(0x08,0,'p');
- DisplaySingleChar(0x09,0,'p');
- DisplaySingleChar(0x0A,0,'m');
-
-
- while(1)
- {
- TU_Value_Conversion();
- // display_value();
- for(i=0;i<5;i++)
- {
- R_S_Byte(disbuff[i]);
- }
- // R_S_Byte('\r');//發(fā)送回車換行符
- // R_S_Byte('\n');
- delay_1s();
- }
- }
- /******************** (C) COPYRIGHT 2015 Silicone shell electronic studio **************************
- * 文件名 :Lcd1602.c
- * 描述 : 1602液晶顯示屏庫函數(shù)
- * 硬件連接: EN:P2.5
- * RW:P2.6
- * RS:P2.7
- * D0~D7:P0口
- *
- * 實驗平臺:SHELL1.0開發(fā)板
- *
- * 作者 :Silicone shell electronic studio
- * 淘寶 :[url=http://shop111698447.taobao.com/shop/view_shop.htm?spm=a1z0e.1.10010.5.GCUiZL]http://shop111698447.taobao.com/ ... 0e.1.10010.5.GCUiZL[/url]
- **********************************************************************************/
- #include "lcd.h"
- #include <intrins.h>
- #include <reg52.h>
- /*********************LCD1602端口定義***************************/
- sbit LCD_E =P2^7; //執(zhí)行使能端
- sbit LCD_RW =P2^5; //讀寫控制端
- sbit LCD_RS =P2^6; //數(shù)據(jù)命令選擇端
- /*
- * 函數(shù)名:delay_1s
- * 描述 :延時函數(shù)1s
- *
- * 輸入 :unsigned int time:延時量
- * 輸出 :無
- * 說明 :液晶顯示用延時函數(shù)
- */
- void delay_1s() //延時1s
- {
- unsigned char i, j, k;
- _nop_();
- i = 8;
- j = 1;
- k = 243;
- do
- {
- do
- {
- while (--k);
- } while (--j);
- } while (--i);
- }
- /*
- * 函數(shù)名:Delay
- * 描述 :延時函數(shù)
- *
- * 輸入 :unsigned int time:延時量
- * 輸出 :無
- * 說明 :
- */
- void Delay(unsigned int time)
- {
- unsigned int timeCounter = 0;
- for (timeCounter = time;timeCounter > 0 ;timeCounter --)
- DelayUs(255);
- }
- /*
- * 函數(shù)名:DelayUs
- * 描述 :延時函數(shù)(微秒)
- *
- * 輸入 :unsigned int time:延時量
- * 輸出 :無
- * 說明 :
- */
- void DelayUs(unsigned int time)
- {
- unsigned int timeCounter = 0;
- for (timeCounter = 0;timeCounter < time;timeCounter ++)
- _nop_();
- }
- /****************************************************************************************\
- ** LCD驅(qū)動模塊 **
- \****************************************************************************************/
- /*
- * 函數(shù)名:LCDInit
- * 描述 :液晶初始化函數(shù)
- *
- * 輸入 :無
- * 輸出 :無
- * 說明 :
- */
- void LCDInit(void)
- {
- //三次顯示模式設(shè)置
- LCD_Data=0;
- LCD_E=Disable;
- Delay(5);
- WriteCmd(LCD_Init);
- Delay(5);
- WriteCmd(LCD_Init);
- Delay(5);
- WriteCmd(LCD_Init);
- WriteCmd(LCD_Init); //初始化
- WriteCmd(LCD_CloseCtr); //關(guān)顯示
- WriteCmd(LCD_CLS); //清屏幕
- WriteCmd(LCD_EnterSet); //光標(biāo)移動設(shè)置
- WriteCmd(LCD_DispCtr); //顯示開以及光標(biāo)設(shè)置
-
- }
- /*--------------------------------- LCD模式設(shè)置函數(shù)--------------------------------------*\
-
- SetWriteCmd() 設(shè)置LCD為寫命令模式
- SetReadCmd() 設(shè)置LCD為讀命令模式
- SetWriteData() 設(shè)置LCD為寫數(shù)據(jù)模式
-
- \*----------------------------------------------------------------------------------------*/
- /*
- * 函數(shù)名:SetWriteCmd
- * 描述 :設(shè)置LCD為寫命令模式
- *
- * 輸入 :無
- * 輸出 :無
- * 說明 :
- */
- void SetWriteCmd(void)
- {
- LCD_RW=Write;
- LCD_RS=Cmd;
- }
- /*
- * 函數(shù)名:SetReadCmd
- * 描述 :設(shè)置LCD為讀命令模式
- *
- * 輸入 :無
- * 輸出 :無
- * 說明 :
- */
- void SetReadCmd(void)
- {
- LCD_RW=Read;
- LCD_RS=Cmd;
- }
- /*
- * 函數(shù)名:SetWriteData
- * 描述 :設(shè)置LCD為寫數(shù)據(jù)模式
- *
- * 輸入 :無
- * 輸出 :無
- * 說明 :
- */
- void SetWriteData(void)
- {
- LCD_RW=Write;
- LCD_RS=Data;
- }
- /*--------------------------------- LCD功能執(zhí)行函數(shù)--------------------------------------*\
-
- WriteCmd() 寫命令
- WriteData() 寫數(shù)據(jù)
- ExecuteCmd() 執(zhí)行命令
- SetXY() 顯示定位
- DisplaySingleChar() 顯示單個字符
- DisplayString() 顯示一串字符
- IsBusy() 忙標(biāo)志檢測
- \*----------------------------------------------------------------------------------------*/
- /*
- * 函數(shù)名:WriteCmd
- * 描述 :寫命令
- *
- * 輸入 :無
- * 輸出 :無
- * 說明 :
- */
- void WriteCmd(char cmd)
- {
- while(IsBusy());
- LCD_Data=cmd;
- SetWriteCmd();
- ExecuteCmd();
- }
- /*
- * 函數(shù)名:WriteData
- * 描述 :寫數(shù)據(jù)
- *
- * 輸入 :無
- * 輸出 :無
- * 說明 :
- */
- void WriteData(char ddata)
- {
- while(IsBusy());
- LCD_Data=ddata;
- SetWriteData();
- ExecuteCmd();
- }
- /*
- * 函數(shù)名:ExecuteCmd
- * 描述 :執(zhí)行命令
- *
- * 輸入 :無
- * 輸出 :無
- * 說明 :
- */
- void ExecuteCmd(void)
- {
- LCD_E=Enable;
- LCD_E=Disable;
- }
- /*
- * 函數(shù)名:SetXY
- * 描述 :顯示定位
- *
- * 輸入 :無
- * 輸出 :無
- * 說明 :
- */
- void SetXY(char x,char y)
- {
- if (y)
- x|=0x40;
- x|=0x80;
- Delay(5);
- WriteCmd(x);
- }
- /*
- * 函數(shù)名:DisplaySingleChar
- * 描述 :顯示單個字符
- *
- * 輸入 :無
- * 輸出 :無
- * 說明 :
- */
- void DisplaySingleChar(char x,char y,char cchar)
- {
- SetXY(x,y);
- WriteData(cchar);
- }
- /*
- * 函數(shù)名:DisplayString
- * 描述 :顯示字符串
- *
- * 輸入 :無
- * 輸出 :無
- * 說明 :
- */
- void DisplayString(char x,char y,char *str)
- {
- while(*str)
- {
- Delay(5);
- DisplaySingleChar(x++,y,*str);
- str++;
- }
- }
- /*
- * 函數(shù)名:IsBusy
- * 描述 :忙標(biāo)志檢測
- *
- * 輸入 :無
- * 輸出 :無
- * 說明 :
- */
- bit IsBusy(void)
- {
- LCD_Data=0xFF;
- SetReadCmd();
- ExecuteCmd();
- // return (bit)(P0 & 0x80);
- return (bit)(LCD_Data & 0x80);
- }
- #ifndef __INCLUDE_H
- #define __INCLUDE_H
- //#define uchar unsigned char
- //#define uint unsigned int
- #include <stdio.h>
- #include "math.h"
- #include "I2C.h"
- #include "PCF8591.h"
- #include "lcd.h"
- #endif /* __INCLUDE_H */
- extern bit ack;
- //起動總線函數(shù)
- extern void Start_I2c();
- //結(jié)束總線函數(shù)
- extern void Stop_I2c();
- //應(yīng)答子函數(shù)
- extern void Ack_I2c(bit a);
- //字節(jié)數(shù)據(jù)發(fā)送函數(shù)
- extern void SendByte(unsigned char c);
- //有子地址發(fā)送多字節(jié)數(shù)據(jù)函數(shù)
- extern bit ISendStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no) ;
- //無子地址發(fā)送多字節(jié)數(shù)據(jù)函數(shù)
- extern bit ISendStrExt(unsigned char sla,unsigned char *s,unsigned char no);
- //無子地址讀字節(jié)數(shù)據(jù)函數(shù)
- extern unsigned char RcvByte();
- #include "PCF8591.h"
- #include "I2C.h"
- /*******************************************************************
- DAC 變換, 轉(zhuǎn)化函數(shù)
- *******************************************************************/
- bit DACconversion(unsigned char sla,unsigned char c, unsigned char Val)
- {
- Start_I2c(); //啟動總線
- SendByte(sla); //發(fā)送器件地址
- if(ack==0)return(0);
- SendByte(c); //發(fā)送控制字節(jié)
- if(ack==0)return(0);
- SendByte(Val); //發(fā)送DAC的數(shù)值
- if(ack==0)return(0);
- Stop_I2c(); //結(jié)束總線
- return(1);
- }
- /*******************************************************************
- ADC發(fā)送字節(jié)[命令]數(shù)據(jù)函數(shù)
- *******************************************************************/
- bit ISendByte(unsigned char sla,unsigned char c)
- {
- Start_I2c(); //啟動總線
- SendByte(sla); //發(fā)送器件地址
- if(ack==0)return(0);
- SendByte(c); //發(fā)送數(shù)據(jù)
- if(ack==0)return(0);
- Stop_I2c(); //結(jié)束總線
- return(1);
- }
- /*******************************************************************
- ADC讀字節(jié)數(shù)據(jù)函數(shù)
- *******************************************************************/
- unsigned char IRcvByte(unsigned char sla)
- { unsigned char c;
- Start_I2c(); //啟動總線
- SendByte(sla+1); //發(fā)送器件地址
- if(ack==0)return(0);
- c=RcvByte(); //讀取數(shù)據(jù)0
- Ack_I2c(1); //發(fā)送非就答位
- Stop_I2c(); //結(jié)束總線
- return(c);
- }
- #ifndef _PCF8591_H_
- #define _PCF8591_H_
- #define PCF8591 0x90 //PCF8591 地址
- bit DACconversion(unsigned char sla,unsigned char c, unsigned char Val);
- bit ISendByte(unsigned char sla,unsigned char c);
- unsigned char IRcvByte(unsigned char sla);
- #endif
- /*************************此部分為I2C總線的驅(qū)動程序*************************************/
- #include <reg52.h>
- #include <intrins.h>
- #include <I2C.H>
- #define NOP() _nop_() /* 定義空指令 */
- #define _Nop() _nop_() /*定義空指令*/
- sbit SCL=P2^1; //I2C 時鐘
- sbit SDA=P2^0; //I2C 數(shù)據(jù)
- bit ack; /*應(yīng)答標(biāo)志位*/
- /*******************************************************************
- 起動總線函數(shù)
- 函數(shù)原型: void Start_I2c();
- 功能: 啟動I2C總線,即發(fā)送I2C起始條件.
- ********************************************************************/
- void Start_I2c()
- {
- SDA=1; /*發(fā)送起始條件的數(shù)據(jù)信號*/
- _Nop();
- SCL=1;
- _Nop(); /*起始條件建立時間大于4.7us,延時*/
- _Nop();
- _Nop();
- _Nop();
- _Nop();
- SDA=0; /*發(fā)送起始信號*/
- _Nop(); /* 起始條件鎖定時間大于4μs*/
- _Nop();
- _Nop();
- _Nop();
- _Nop();
- SCL=0; /*鉗住I2C總線,準(zhǔn)備發(fā)送或接收數(shù)據(jù) */
- _Nop();
- _Nop();
- }
- /*******************************************************************
- 結(jié)束總線函數(shù)
- 函數(shù)原型: void Stop_I2c();
- 功能: 結(jié)束I2C總線,即發(fā)送I2C結(jié)束條件.
- ********************************************************************/
- void Stop_I2c()
- {
- SDA=0; /*發(fā)送結(jié)束條件的數(shù)據(jù)信號*/
- _Nop(); /*發(fā)送結(jié)束條件的時鐘信號*/
- SCL=1; /*結(jié)束條件建立時間大于4μs*/
- _Nop();
- _Nop();
- _Nop();
- _Nop();
- _Nop();
- SDA=1; /*發(fā)送I2C總線結(jié)束信號*/
- _Nop();
- _Nop();
- _Nop();
- _Nop();
- }
- /*******************************************************************
- 字節(jié)數(shù)據(jù)發(fā)送函數(shù)
- 函數(shù)原型: void SendByte(UCHAR c);
- 功能: 將數(shù)據(jù)c發(fā)送出去,可以是地址,也可以是數(shù)據(jù),發(fā)完后等待應(yīng)答,并對
- 此狀態(tài)位進(jìn)行操作.(不應(yīng)答或非應(yīng)答都使ack=0)
- 發(fā)送數(shù)據(jù)正常,ack=1; ack=0表示被控器無應(yīng)答或損壞。
- ********************************************************************/
- void SendByte(unsigned char c)
- {
- unsigned char BitCnt;
- for(BitCnt=0;BitCnt<8;BitCnt++) /*要傳送的數(shù)據(jù)長度為8位*/
- {
- if((c<<BitCnt)&0x80)SDA=1; /*判斷發(fā)送位*/
- else SDA=0;
- _Nop();
- SCL=1; /*置時鐘線為高,通知被控器開始接收數(shù)據(jù)位*/
- _Nop();
- _Nop(); /*保證時鐘高電平周期大于4μs*/
- _Nop();
- _Nop();
- _Nop();
- SCL=0;
- }
- _Nop();
- _Nop();
- SDA=1; /*8位發(fā)送完后釋放數(shù)據(jù)線,準(zhǔn)備接收應(yīng)答位*/
- _Nop();
- _Nop();
- SCL=1;
- _Nop();
- _Nop();
- _Nop();
- if(SDA==1)ack=0;
- else ack=1; /*判斷是否接收到應(yīng)答信號*/
- SCL=0;
- _Nop();
- _Nop();
- }
- /*******************************************************************
- 字節(jié)數(shù)據(jù)接收函數(shù)
- 函數(shù)原型: UCHAR RcvByte();
- 功能: 用來接收從器件傳來的數(shù)據(jù),并判斷總線錯誤(不發(fā)應(yīng)答信號),
- 發(fā)完后請用應(yīng)答函數(shù)應(yīng)答從機(jī)。
- ********************************************************************/
- unsigned char RcvByte()
- {
- unsigned char retc;
- unsigned char BitCnt;
- retc=0;
- SDA=1; /*置數(shù)據(jù)線為輸入方式*/
- for(BitCnt=0;BitCnt<8;BitCnt++)
- {
- _Nop();
- SCL=0; /*置時鐘線為低,準(zhǔn)備接收數(shù)據(jù)位*/
- _Nop();
- _Nop(); /*時鐘低電平周期大于4.7μs*/
- _Nop();
- _Nop();
- _Nop();
- SCL=1; /*置時鐘線為高使數(shù)據(jù)線上數(shù)據(jù)有效*/
- _Nop();
- _Nop();
- retc=retc<<1;
- if(SDA==1)retc=retc+1; /*讀數(shù)據(jù)位,接收的數(shù)據(jù)位放入retc中 */
- _Nop();
- _Nop();
- }
- SCL=0;
- _Nop();
- _Nop();
- return(retc);
- }
- /********************************************************************
- 應(yīng)答子函數(shù)
- 函數(shù)原型: void Ack_I2c(bit a);
- 功能: 主控器進(jìn)行應(yīng)答信號(可以是應(yīng)答或非應(yīng)答信號,由位參數(shù)a決定)
- ********************************************************************/
- void Ack_I2c(bit a)
- {
- if(a==0)SDA=0; /*在此發(fā)出應(yīng)答或非應(yīng)答信號 */
- else SDA=1;
- _Nop();
- _Nop();
- _Nop();
- SCL=1;
- _Nop();
- _Nop(); /*時鐘低電平周期大于4μs*/
- _Nop();
- _Nop();
- _Nop();
- SCL=0; /*清時鐘線,鉗住I2C總線以便繼續(xù)接收*/
- _Nop();
- _Nop();
- }
- #ifndef _LCD_H
- #define _LCD_H
- /********************************************************************************\
- ** 宏定義區(qū) **
- \********************************************************************************/
- /*------------------------------- LCD模塊 ------------------------------------*/
- #define Busy 0x80 //忙信號
- #define LCD_Data P0 //數(shù)據(jù)口定義
- #define Write 0x00 //低電平寫入
- #define Read 0x01 //高電平讀出
- #define Data 0x01 //高電平選擇數(shù)據(jù)
- #define Cmd 0x00 //低電平選擇命令
- #define Enable 0x00 //躍變到低電平時執(zhí)行命令
- #define Disable 0x01
- #define True 0x01
- #define False 0x00
- #define LCD_Init 0x38 //初始化模式
- #define LCD_DispCtr 0x0C //開顯示及光標(biāo)設(shè)置
- #define LCD_CloseCtr 0x08 //關(guān)顯示
- #define LCD_CLS 0x01 //清屏幕
- #define LCD_EnterSet 0x06 //顯示光標(biāo)
- /********************************************************************************\
- ** 函數(shù)聲明 **
- \********************************************************************************/
- extern void LCDInit(void); //LCD初始化
- void SetWriteCmd(void); //設(shè)置寫命令模式
- void SetReadCmd(void); //設(shè)置讀命令模式
- void SetWriteData(void); //設(shè)置寫數(shù)據(jù)模式
- extern void WriteCmd(char cmd); //寫命令
- void WriteData(char ddata); //寫數(shù)據(jù)
- void ExecuteCmd(void); //執(zhí)行命令
- void SetXY(char x,char y); //定位顯示地址
- extern void DisplaySingleChar(char x,char y,char cchar); //顯示單個字符
- extern void DisplayString(char x,char y,char *str); //顯示一段字符串
- void Delay(unsigned int time); //延時主程序
- void DelayUs(unsigned int time); //延時子程序
- bit IsBusy(void); //判斷忙標(biāo)志函數(shù)
- extern void delay_1s();
- #endif
復(fù)制代碼
|
|