昨天有人反應(yīng)我寫的錯(cuò)別字太多,那我恭喜你看明白了我想表達(dá)的意思,只要是我偏科偏得厲害。
言歸正傳啊! 最近做的這個(gè)基于衛(wèi)星定位的便攜式污染源監(jiān)測系統(tǒng),對溫濕度要有高了些,對價(jià)格也比較敏感,所以對溫濕度的選擇比較慎重了些。順便我有分析了下,AD的精度和分辨率的問題:
很多人對于精度和分辨率的概念不清楚,這里我做一下總結(jié),希望大家不要混淆。
像我們搞電子的,經(jīng)常跟“精度”與“分辨率”打交道。簡單點(diǎn)說,“精度”是用來描述物理量的準(zhǔn)確程度的,而“分辨率”是用來描述刻度劃分的。從定義上看,這兩個(gè)量應(yīng)該是風(fēng)馬牛不相及的。我是這么理解的,“精度”就是描述物理量 的精確程度的,也就是我們常說的準(zhǔn)不準(zhǔn)的問題,或者說與真實(shí)值差多少的問題;“分辨率”是用來表述分辨能力的,分辨能力強(qiáng)的未必測試的準(zhǔn)確,比如說溫度變化多少時(shí)它能分辨出來。 在簡單做個(gè)比喻:有這么一把常見的塑料尺(中學(xué)生用的那種),它的量程是10厘米,上面有100個(gè)刻度,最小能讀出1毫米的有效值。那么我們就說這把尺子的分辨率是1毫米,或者量程的1%;而它的實(shí)際精度就不得而知了(算是0.1毫米吧)。當(dāng)我們用火來烤一下它,并且把它拉長一段,然后再考察一下它。我們不難發(fā)現(xiàn),它還有有100個(gè)刻度,它的“分辨率”還是1毫米,跟原來一樣!然而,您還會認(rèn)為它的精度還是原來的0.1毫米么?(這個(gè)例子是引用網(wǎng)上的,個(gè)人覺得比喻的很形象!)
回到電子技術(shù)上, 所以很多朋友一談到精度,馬上就和分辨率聯(lián)系起來了,包括有些項(xiàng)目負(fù)責(zé)人,只會在那里說:這個(gè)系統(tǒng)精度要求很高啊,你們AD的位數(shù)至少要多少多少啊
其實(shí),仔細(xì)瀏覽一下AD的數(shù)據(jù)手冊,會發(fā)現(xiàn)跟精度有關(guān)的有兩個(gè)很重要的指標(biāo):DNL和INL。似乎知道這兩個(gè)指標(biāo)的朋友并不多,所以在這里很有必要解釋一下。
DNL:Differencial NonLiner——微分非線性度
INL:Interger NonLiner——積分非線性度(精度主要用這個(gè)值來表示)
他表示了ADC器件在所有的數(shù)值點(diǎn)上對應(yīng)的模擬值,和真實(shí)值之間誤差最大的那一點(diǎn)的誤差值。也就是,輸出數(shù)值偏離線性最大的距離。單位是LSB(即最低位所表示的量)。當(dāng)然,像有的AD如△—∑系列的AD,也用Linearity error來表示精度。
分辨率的計(jì)算:測量電壓范圍/(2^AD位數(shù)-1)
就HTU20D溫濕度傳感器來說: 溫度部分:

由上圖不難看出,在14bit時(shí),HTU20D傳感器的溫度部分的分辨率是0.01°C,在12bit時(shí),溫度的分辨率是0.04°C。這里的14bit與12bit就是設(shè)定的AD轉(zhuǎn)換的位數(shù)啊。但是大家看看表中給出的溫度的“精度(Temperature Accuracy@25°C)”是±0.3°C,不管你在設(shè)置AD轉(zhuǎn)換位數(shù)是14位還是12位時(shí),傳感器本身的精度數(shù)不變的,0.3就是0.3°C。所以精度和分辨率是兩個(gè)完全不同的我概念。
下面再看看濕度吧

HTU20D濕度的的“分辨率”是,在12bits時(shí)為0.04%RH; 在8bits時(shí) 0.7%RH, 那么他的“精度”總是±3%RH, 如此看來分辨率和精度真的是不同了,呵呵 大家再想想,同是在一個(gè)傳感器中的溫度和濕度兩個(gè)物理量的溫度的精度是±0.3,而濕度的精度是±3 。對吧 你在看看上面的兩個(gè)表格,如果吧溫度和濕度都設(shè)置是12bit時(shí),他們的分辨率是相同的,都是0.04,不是嗎?你在仔細(xì)看看 至于0.04這個(gè)數(shù)是如何來的呢! 你知道嗎? 考慮考慮吧,
下面我給出我的讀寫HTU20D/HTU21D的程序僅供參考,不過我在項(xiàng)目中應(yīng)用過了,還沒發(fā)現(xiàn)有什么問題呢 /*================================================================
【名 稱】void I2CDelay (unsigned char t)
【功 能】模擬IIC用的短延時(shí)
【備 注】
【作 者】
【時(shí) 間】2015年10月18日
================================================================*/
void I2CDelay (unsigned char t)
{
while(t--);
} /*================================================================
【名 稱】void I2CInit(void)
【功 能】I2C初始化,空閑狀態(tài)
【備 注】
【作 者】
【時(shí) 間】2015年10月18日
================================================================*/
void I2CInit(void)
{
SDA = 1;
SCL = 1;
}
/*================================================================
【名 稱】void I2CStart(void)
【功 能】I2C起始信號
【備 注】SCL、SDA同為高,SDA跳變成低之后,SCL跳變成低
【作 者】
【時(shí) 間】2015年10月18日
================================================================*/
void I2CStart(void)
{
SDA = 1;
SCL = 1;
I2CDelay(10);
SDA = 0;
I2CDelay(20);
SCL = 0;
I2CDelay(20);
} /*================================================================
【名 稱】void I2CStop(void)
【功 能】I2C停止信號
【備 注】SCL、SDA同為低,SCL跳變成高之后,SDA跳變成高
【作 者】
【時(shí) 間】2015年10月18日
================================================================*/
void I2CStop(void)
{
SDA = 0;
SCL = 0;
I2CDelay(10);
SCL = 1;
I2CDelay(10);
SDA = 1;
I2CDelay(10);
}
/*================================================================
【名 稱】unsigned char I2CWRByte(unsigned char WRByte)
【功 能】I2C寫一個(gè)字節(jié)數(shù)據(jù),返回ACK或者NACK
【備 注】從高到低,依次發(fā)送
【作 者】
【時(shí) 間】2015年10月18日
================================================================*/
unsigned char I2CWRByte(unsigned char WRByte)
{
unsigned char i;
SCL = 0;
for(i=0;i<8;i++)
{
if(WRByte&0x80)
{
SDA = 1;
}
else
{
SDA = 0;
}
I2CDelay(10);
SCL=1; //輸出SDA穩(wěn)定后,拉高SCL給出上升沿,從機(jī)檢測到后進(jìn)行數(shù)據(jù)采樣
I2CDelay(50);
SCL=0;
I2CDelay(10);
WRByte <<= 1;
}
SDA = 1;
SCL = 1;
I2CDelay(20);
if(SDA==1) //SDA為高,收到NACK
{
SCL=0;
I2CDelay(50);
return NACK;
}
else //SDA為低,收到NACK
{
SCL=0;
I2CDelay(50);
return ACK;
}
}
/*================================================================
【名 稱】unsigned char I2CRDByte(unsigned char AckValue)
【功 能】I2C讀一個(gè)字節(jié)數(shù)據(jù),入口參數(shù)用于控制應(yīng)答狀態(tài),ACK或者NACK
【備 注】從高到低,依次接收
【作 者】
【時(shí) 間】2015年10月18日
================================================================*/
unsigned char I2CRDByte(unsigned char AckValue)
{
unsigned char i,RDByte=0;
SCL = 0;
SDA = 1; //釋放總線
for (i=0;i<8;i++)
{
RDByte <<= 1; //移位
SCL = 1; //給出上升沿
I2CDelay(30); //延時(shí)等待信號穩(wěn)定
if(SDA==1) //采樣獲取數(shù)據(jù)
{
RDByte |= 0x01;
}
else
{
RDByte &= 0xfe;
}
SCL = 0; //下降沿,從機(jī)給出下一位值
I2CDelay(10);
}
SDA = AckValue; //應(yīng)答狀態(tài)
I2CDelay(10);
SCL = 1;
I2CDelay(50);
SCL = 0;
SDA = 1;
I2CDelay(1);
return RDByte;
} /*================================================================
【名 稱】void HTU21Init(void)
【功 能】HTU21初始化函數(shù),主函數(shù)中調(diào)用
【備 注】從高到低,依次接收
【作 者】
【時(shí) 間】2015年10月18日
================================================================*/
void HTU21Init(void)
{
I2CInit();//I2C初始化
I2CStart();//啟動I2C
I2CWRByte(HTU21ADDR&0xfe);//寫HTU21I2C地址
I2CWRByte(0xfe);
I2CStop();//停I2C
Delay(600);//短延時(shí)
}
/*================================================================
【名 稱】long ReadHtu21(char whatdo)
【功 能】讀取函數(shù)函數(shù)
【備 注】
【作 者】
【時(shí) 間】2015年10月18日
================================================================*/
long ReadHtu21(char whatdo)
{
unsigned long temp;
unsigned char Humidity,HumidityH,HumidityL;
unsigned long wendu; I2CStart();
if(I2CWRByte(HTU21ADDR&0xfe)==ACK)
{
if(I2CWRByte(whatdo)==ACK)
{
do
{
Delay(30);
I2CStart();
}while(I2CWRByte(HTU21ADDR|0x01)==NACK); HumidityH = I2CRDByte(ACK);
HumidityL = I2CRDByte(ACK);
I2CRDByte(NACK);
I2CStop();
HumidityL &= 0xfc;
temp = HumidityH*256+HumidityL;
if (whatdo==((char)0xf5))
{
Humidity = (unsigned char)((temp*125)/65536-6)%0xff;
return Humidity;
}
else
{
temp=((long)17572)*temp;
temp=temp/((long)65536);
wendu =temp-((long)4685);
return wendu; //輸出
}
}
}
return 0;
} 你如果感覺有收獲就分享給更多的朋友吧,或者你把你的心得體會也分享給我和他。
|