有些時(shí)候我們需要對(duì)高精度的ADC來(lái)處理一些要求較高的模擬量采集。在處理溫控器的過(guò)程中我們就使用到了LTC2400這款ADC。接下來(lái)我們就來(lái)設(shè)計(jì)并實(shí)現(xiàn)LTC2400的驅(qū)動(dòng)。
1 、功能概述
LTC2400是一個(gè)供電電壓2.7V到5.5V的微功率24位轉(zhuǎn)換器,集成了振蕩器、4ppm INL和0.3ppm RMS噪聲。所需外接基準(zhǔn)電壓源的電壓范圍為0.1V~VCC;模擬信號(hào)輸入VIN的輸入電壓范圍為-0.125VREF~1.125VREF。
1.1 、硬件結(jié)構(gòu)
LTC2400模數(shù)轉(zhuǎn)換器采用與SPI接口兼容的3線數(shù)字接口,可應(yīng)用于高分辨率和低頻應(yīng)用場(chǎng)合,如稱重、溫度測(cè)量、氣體分析、應(yīng)變儀,數(shù)據(jù)采集,工業(yè)控制等方面。它采用8腳SO-8封裝,其引腳排列如圖所示。
LTC2400內(nèi)部已集成了高精度的振蕩器,因此采用片內(nèi)振蕩器時(shí)不需要外接任何元件。通過(guò)一個(gè)引腳,LTC2400可以配置為在50Hz或60Hz±2%時(shí)優(yōu)于110dB的抑制,也可以由外部振蕩器驅(qū)動(dòng),用戶定義的抑制頻率在1Hz到120Hz之間。當(dāng)芯片的F0腳接VCC時(shí),使用內(nèi)部振蕩器可對(duì)輸入信號(hào)中的50Hz干擾進(jìn)行大于110dB的抑制,其AD轉(zhuǎn)換時(shí)間為160ms;F0腳接GND時(shí),使用內(nèi)部振蕩器可對(duì)輸入信號(hào)中的60Hz干擾進(jìn)行大于110dB的抑制,AD轉(zhuǎn)換時(shí)間為133ms;當(dāng)F0腳接外部振蕩器fEOSC時(shí),其抑制的頻率為f EOSC /2560,AD轉(zhuǎn)換時(shí)間為2048/f EOSC 。
LTC2400轉(zhuǎn)換器接受任何外部參考電壓從0.1V到VCC。LTC2400以其擴(kuò)展的輸入轉(zhuǎn)換范圍-12.5% VREF到112.5% VREF,平穩(wěn)地解決了先前傳感器或信號(hào)調(diào)理電路的偏移和超量程問(wèn)題。
1.2 、通訊接口
通過(guò)對(duì)CS和SCK的控制,LTC2400可以提供幾種靈活的接口模式(內(nèi)部或外部的SCK模式)。不同轉(zhuǎn)換模式的選擇無(wú)需對(duì)LTC2400的寄存器進(jìn)行設(shè)置,并且不影響數(shù)據(jù)轉(zhuǎn)換周期。使用時(shí)鐘信號(hào)SCK(PIN7)控制轉(zhuǎn)換數(shù)據(jù)的輸出時(shí),轉(zhuǎn)換結(jié)果將在時(shí)鐘CLK的下降沿由SDO腳輸出。在內(nèi)部時(shí)鐘模式,SCK信號(hào)由LTC2400產(chǎn)生輸出在外部SCK模式,SCK為L(zhǎng)TC2400外部輸入的時(shí)鐘信號(hào)。下面詳細(xì)介紹外部串行時(shí)鐘的三線接口方法。
當(dāng)LTC2400上電時(shí),如果SCK為低電平,轉(zhuǎn)換進(jìn)入外部串行模式;在CS信號(hào)的下降沿,SCK信號(hào)必須為低電平。
當(dāng)CS為高電平時(shí),SDO為高阻態(tài),此時(shí),SDO連接的接口線可以作為其它應(yīng)用。如果LTC2400在轉(zhuǎn)換和睡眠時(shí)CS為低電平,那么,SDO的輸出狀態(tài)將用于指示EOC。在AD轉(zhuǎn)換階段,SDO的輸出狀態(tài)EOC將變?yōu)楦唠娖剑坏┺D(zhuǎn)換完成,EOC又變?yōu)榈碗娖健T贚TC2400處于睡眠狀態(tài)時(shí),如果CS為低電平,系統(tǒng)會(huì)在SCK的上升沿將其喚醒。LTC2400的外部串行時(shí)鐘接口時(shí)序圖如下:
CS信號(hào)除用來(lái)檢測(cè)LTC2400的狀態(tài)和輸出AD轉(zhuǎn)換數(shù)據(jù)外,還可用來(lái)控制全部串行數(shù)據(jù)輸出之前進(jìn)行的新一次AD轉(zhuǎn)換。在LTC2400處于數(shù)據(jù)輸出狀態(tài)時(shí),CS由低變高以停止串行輸出,同時(shí)開始新的AD轉(zhuǎn)換。
由于在CS為高電平時(shí),數(shù)據(jù)輸出端SDO為高阻態(tài),因此,在LTC2400的轉(zhuǎn)換過(guò)程中,可通過(guò)將CS變?yōu)榈碗娖絹?lái)檢測(cè)轉(zhuǎn)換狀態(tài)。當(dāng)CS為低電平時(shí),SDO腳輸出的EOC信號(hào)為1,表示轉(zhuǎn)換正在進(jìn)行;EOC為0表示轉(zhuǎn)換完成,系統(tǒng)處于睡眠狀態(tài)。當(dāng)LTC2400處于睡眠狀態(tài)時(shí),其轉(zhuǎn)換結(jié)果將保存在內(nèi)部移位寄存器中。CS為低可在SCK的上升沿喚醒LTC2400,此時(shí)轉(zhuǎn)換數(shù)據(jù)將在SCK的下降沿串行輸出。EOC通常在SCK的第一個(gè)上升沿被鎖存,直到第32個(gè)上升沿鎖存結(jié)束,同時(shí),系統(tǒng)將在第32個(gè)下降沿開始的新一輪轉(zhuǎn)換。
一般情況下,在數(shù)據(jù)輸出過(guò)程中,如果CS為低電平,那么,系統(tǒng)將在SCK的第一個(gè)上升沿和第32個(gè)下降沿中間將CS變高以停止數(shù)據(jù)輸出。
1.3 、工作過(guò)程
LTC2400是一種低功耗、采用Δ-Σ技術(shù)且具有3線串行接口的AD轉(zhuǎn)換器,而且在AD轉(zhuǎn)換完成后將直接進(jìn)入睡眠狀態(tài)。LTC2400的三線接口線分別是數(shù)據(jù)輸出(SDO)、時(shí)鐘(SCK)和片選(CS)。其工作流程如圖所示:
LTC2400完成轉(zhuǎn)換就進(jìn)入睡眠狀態(tài)。睡眠狀態(tài)的供電電流僅為20μA。若CS一直為高電平,芯片將保持睡眠狀態(tài)。進(jìn)入睡眠狀態(tài)時(shí),數(shù)據(jù)最后的轉(zhuǎn)換結(jié)果將保存在芯片內(nèi)部的靜態(tài)移位寄存器中。
當(dāng)CS變?yōu)榈碗娖綍r(shí),LTC2400開始輸出轉(zhuǎn)換結(jié)果,此時(shí)數(shù)據(jù)轉(zhuǎn)換沒(méi)有等待時(shí)間,輸出數(shù)據(jù)即為剛進(jìn)行的轉(zhuǎn)換結(jié)果。該轉(zhuǎn)換結(jié)果是在串行時(shí)鐘SCK的控制下由SDO輸出的,并在SCK的下降沿更新,而在SCK的上升沿可靠讀取。當(dāng)32位數(shù)據(jù)從LTC2400讀出或當(dāng)CS被拉高時(shí),數(shù)據(jù)輸出結(jié)束。此后LTC2400將自動(dòng)開始新的數(shù)據(jù)轉(zhuǎn)換和重復(fù)周期。
2 、驅(qū)動(dòng)設(shè)計(jì)與實(shí)現(xiàn)
我們已經(jīng)了解了LTC2400模數(shù)轉(zhuǎn)換器的基本情況,接下來(lái)我們將設(shè)計(jì)并實(shí)現(xiàn)LTC2400模數(shù)轉(zhuǎn)換器的驅(qū)動(dòng)程序。
2.1 、對(duì)象定義
首先我們需要抽象出LTC2400模數(shù)轉(zhuǎn)換器的對(duì)象類型。作為一個(gè)對(duì)象最起碼包括量方面的內(nèi)容:屬性和操作。關(guān)于LTC2400模數(shù)轉(zhuǎn)換器的屬性我們簡(jiǎn)單分析一下。LTC2400模數(shù)轉(zhuǎn)換器是一個(gè)主動(dòng)發(fā)送數(shù)據(jù)的器件,并沒(méi)有需要配置的地方,僅有一個(gè)時(shí)鐘通過(guò)外部引腳設(shè)置,所以為了應(yīng)用更清楚我們將其時(shí)鐘引腳的配置作為其屬性記錄下來(lái)。另一個(gè)其返回的數(shù)據(jù)帶有狀態(tài)標(biāo)識(shí),我們將其作為另一個(gè)屬性以記錄當(dāng)前的狀態(tài)。
至于操作也很簡(jiǎn)單,首先我們要從LTC2400接收數(shù)據(jù),而這個(gè)與具體的平臺(tái)聯(lián)系緊密,所以我們將從LTC2400接收數(shù)據(jù)作為對(duì)象的一個(gè)操作。LTC2400模數(shù)轉(zhuǎn)換器采用SPI通訊接口,有時(shí)需要在軟件中對(duì)片選信號(hào)進(jìn)行操作,所以我們將片選型號(hào)的操作作為對(duì)象的另一個(gè)操作。在一些情況下,有些針對(duì)對(duì)象的活動(dòng)需要延時(shí)進(jìn)行,而在不同的平臺(tái)中采取的延時(shí)方式不盡相同,為了操作方便我們將延時(shí)操作作為對(duì)象的一個(gè)操作。于是我們可抽象的LTC2400的對(duì)象類型如下:
/* 定義LTC2400對(duì)象類型 */
typedef struct Ltc2400Object {
LTC2400ClockTypeclock; //使用的時(shí)鐘
uint32_tdataCode; //數(shù)據(jù)編碼
void(*Receive)(uint8_t *rData); //接收數(shù)據(jù)
void(*ChipSelect)(LTC2400CSType cs); //實(shí)現(xiàn)片選
void(*Delayms)(volatile uint32_t nTime); //實(shí)現(xiàn)ms延時(shí)操作
}Ltc2400ObjectType;
定義了LTC2400模數(shù)轉(zhuǎn)換器的對(duì)象類型,我們還需要設(shè)計(jì)對(duì)象的初始化函數(shù),因?yàn)閷?duì)象必須初始化后才能使用。初始化函數(shù)至少包含有2方面內(nèi)容:一是為對(duì)象變量賦必要的初值;二是檢查這些初值是否是有效的。特別是一些操作指針錯(cuò)誤的話可能產(chǎn)生嚴(yán)重的后果。基于這一原則,我們?cè)O(shè)計(jì)LTC2400模數(shù)轉(zhuǎn)換器的對(duì)象初始化函數(shù)如下:
/* LTC2400對(duì)象初始化函數(shù) */
void LTC2400Initialization(Ltc2400ObjectType*ltc,
LTC2400ClockType clock,
LTC2400Receive receive,
LTC2400ChipSelect cs,
LTC2400Delay msDelay)
{
if((ltc==NULL)||(receive==NULL)||(msDelay==NULL))
{
return;
}
ltc->dataCode=0;
ltc->clock=clock;
if(cs==NULL) //硬件電路實(shí)現(xiàn)片選
{
ltc->ChipSelect=DefaultChipSelect;
}
else
{
ltc->ChipSelect=cs;
}
ltc->Receive=receive;
ltc->Delayms=msDelay;
}
至此關(guān)于LTC2400模數(shù)轉(zhuǎn)換器的對(duì)象定義才算完成。在使用初始化函數(shù)時(shí),需要注意片選操作函數(shù),如果是采用硬件電路選中則可使用NULL作為參數(shù)。
2.2 、對(duì)象操作
我們獲取對(duì)象的目的就是希望通過(guò)對(duì)象來(lái)得到我們想要的數(shù)據(jù)。對(duì)于LTC2400模數(shù)轉(zhuǎn)器來(lái)說(shuō),就是從其接收ADC轉(zhuǎn)換數(shù)據(jù)。所以我們封裝LTC2400的操作函數(shù)如下:
/* 獲取LTC2400轉(zhuǎn)換數(shù)據(jù),返回量程數(shù)據(jù)的比例值 */
float GetLtc2400Data(Ltc2400ObjectType*ltc)
{
uint8_trData[4];
ltc->ChipSelect(LTC2400CS_Enable);
ltc->Delayms(1);
ltc->Receive(rData);
ltc->Delayms(1);
ltc->ChipSelect(LTC2400CS_Disable);
returnCompoundLTC2400Data(ltc,rData);
}
函數(shù)的返回值是轉(zhuǎn)換結(jié)果的比例值,是一個(gè)浮點(diǎn)數(shù),使用這一返回結(jié)果結(jié)合具體浮點(diǎn)數(shù)的量成范圍就可以得到物理量值。
3 、驅(qū)動(dòng)的使用
我們已經(jīng)開發(fā)了LTC2400模數(shù)轉(zhuǎn)換器的驅(qū)動(dòng)程序,接下來(lái)我們用一個(gè)簡(jiǎn)單的實(shí)例驗(yàn)證這一驅(qū)動(dòng)。
3.1 、聲明并初始化對(duì)象
使用基于對(duì)象的操作我們需要先得到這個(gè)對(duì)象,所以我們先要使用前面定義的LTC2400模數(shù)轉(zhuǎn)換器對(duì)象類型聲明一個(gè)LTC2400模數(shù)轉(zhuǎn)換器對(duì)象變量,具體操作格式如下:
Ltc2400ObjectTypeltc2400;
聲明了這個(gè)對(duì)象變量并不能立即使用,我們還需要使用驅(qū)動(dòng)中定義的初始化函數(shù)對(duì)這個(gè)變量進(jìn)行初始化。這個(gè)初始化函數(shù)所需要的輸入?yún)?shù)如下:
Ltc2400ObjectType*ltc,所要初始化的對(duì)象
LTC2400ClockTypeclock,采用時(shí)鐘方式
LTC2400Receivereceive,接收數(shù)據(jù)函數(shù)指針
LTC2400ChipSelectcs,片選操作函數(shù)指針
LTC2400DelaymsDelay,延時(shí)函數(shù)指針
對(duì)于這些參數(shù),對(duì)象變量我們已經(jīng)定義了。所使用的時(shí)鐘方式為枚舉,根據(jù)實(shí)際情況選擇就好了。主要的是我們需要定義幾個(gè)函數(shù),并將函數(shù)指針作為參數(shù)。這幾個(gè)函數(shù)的類型如下:
/*定義接收數(shù)據(jù)函數(shù)指針類型*/
typedef void(*LTC2400Receive)(uint8_t *rData);
/*定義片選信號(hào)函數(shù)指針類型*/
typedef void(*LTC2400ChipSelect)(LTC2400CSType cs);
/*定義延時(shí)操作函數(shù)指針類型*/
typedef void (*LTC2400Delay)(volatileuint32_t nTime);
對(duì)于這幾個(gè)函數(shù)我們根據(jù)樣式定義就可以了,具體的操作可能與使用的硬件平臺(tái)有關(guān)系。片選操作函數(shù)用于多設(shè)備需要軟件操作時(shí),如采用硬件片選可以傳入NULL即可。具體函數(shù)定義如下:
/*定義讀寫操作函數(shù)指針類型*/
voidLTC2400Recieve(uint8_t *rData)
{
HAL_SPI_Receive(<c2400hspi,rData,4,1000);
}
/*實(shí)現(xiàn)片選*/
void LTC2400ChipSelected(LTC2400CSTypecs)
{
if(LTC2400CS_Enable==cs)
{
HAL_GPIO_WritePin(GPIOF, GPIO_PIN_4, GPIO_PIN_RESET);
}
else
{
HAL_GPIO_WritePin(GPIOF, GPIO_PIN_4, GPIO_PIN_SET);
}
}
對(duì)于延時(shí)函數(shù)我們可以采用各種方法實(shí)現(xiàn)。我們采用的STM32平臺(tái)和HAL庫(kù)則可以直接使用HAL_Delay()函數(shù)。于是我們可以調(diào)用初始化函數(shù)如下:
LTC2400Initialization(<c2400,INTERNAL_CLOCK50Hz,LTC2400Recieve,LTC2400ChipSelected,HAL_Delay);
這里我們將其初始化為使用改了內(nèi)部時(shí)鐘,采用軟件控制片選信號(hào)。
3.2 、基于對(duì)象進(jìn)行操作
我們定義了對(duì)象變量并使用初始化函數(shù)給其作了初始化。接著我們就來(lái)考慮操作這一對(duì)象獲取我們想要的數(shù)據(jù)。我們?cè)隍?qū)動(dòng)中已經(jīng)將獲取數(shù)據(jù)并轉(zhuǎn)換為轉(zhuǎn)換值的比例值,接下來(lái)我們使用這一驅(qū)動(dòng)開發(fā)我們的應(yīng)用實(shí)例。
/* 獲取LTC2400測(cè)量的物理量值 */
void GetLTC2400Value(void)
{
float ratio;
float phyValue;
float range=100.0;
float zero=0.0;
ratio=GetLtc2400Data(<c2400);
phyValue=(range-zero)*ratio+zero;
}
在這一例中,我們計(jì)算了一個(gè)量程范圍為0到100的物理量的值,如果檢測(cè)的物理量不同,我們根據(jù)實(shí)際修改即可。
4 、應(yīng)用總結(jié)
這一篇中,我們?cè)O(shè)計(jì)并實(shí)現(xiàn)了LTC2400模數(shù)轉(zhuǎn)換器的驅(qū)動(dòng)程序,并使用這一驅(qū)動(dòng)開發(fā)了獲取一個(gè)量程范圍為0到100的溫度信號(hào)的簡(jiǎn)單應(yīng)用,得到的結(jié)果與我們預(yù)期一致,因此我們的驅(qū)動(dòng)符合要求。
在使用驅(qū)動(dòng)時(shí)需注意,采用SPI接口的器件需要考慮片選操作的問(wèn)題。如果片選信號(hào)是通過(guò)硬件電路來(lái)實(shí)現(xiàn)的,我們?cè)诔跏蓟瘯r(shí)給其傳遞NULL值。如果是軟件操作片選則傳遞我們編寫的片選操作函數(shù)。
完整的源代碼可在GitHub下載:https://github.com/foxclever/ExPeriphDriver
評(píng)論
查看更多