天天看點

外設驅動庫開發筆記7:LTC2400系列ADC驅動

  有些時候我們需要對高精度的ADC來處理一些要求較高的模拟量采集。在處理溫控器的過程中我們就使用到了LTC2400這款ADC。接下來我們就來設計并實作LTC2400的驅動。

1、功能概述

  LTC2400是一個供電電壓2.7V到5.5V的微功率24位轉換器,內建了振蕩器、4ppm INL和0.3ppm RMS噪聲。所需外接基準電壓源的電壓範圍為0.1V~VCC;模拟信号輸入VIN的輸入電壓範圍為-0.125VREF~1.125VREF。

1.1、硬體結構

  LTC2400模數轉換器采用與SPI接口相容的3線數字接口,可應用于高分辨率和低頻應用場合,如稱重、溫度測量、氣體分析、應變儀,資料采集,工業控制等方面。它采用8腳SO-8封裝,其引腳排列如圖所示。

外設驅動庫開發筆記7:LTC2400系列ADC驅動

  LTC2400内部已內建了高精度的振蕩器,是以采用片内振蕩器時不需要外接任何元件。通過一個引腳,LTC2400可以配置為在50Hz或60Hz±2%時優于110dB的抑制,也可以由外部振蕩器驅動,使用者定義的抑制頻率在1Hz到120Hz之間。當晶片的F0腳接VCC時,使用内部振蕩器可對輸入信号中的50Hz幹擾進行大于110dB的抑制,其AD轉換時間為160ms;F0腳接GND時,使用内部振蕩器可對輸入信号中的60Hz幹擾進行大于110dB的抑制,AD轉換時間為133ms;當F0腳接外部振蕩器fEOSC時,其抑制的頻率為fEOSC/2560,AD轉換時間為2048/fEOSC。

  LTC2400轉換器接受任何外部參考電壓從0.1V到VCC。LTC2400以其擴充的輸入轉換範圍-12.5% VREF到112.5% VREF,平穩地解決了先前傳感器或信号調理電路的偏移和超量程問題。

1.2、通訊接口

  通過對CS和SCK的控制,LTC2400可以提供幾種靈活的接口模式(内部或外部的SCK模式)。不同轉換模式的選擇無需對LTC2400的寄存器進行設定,并且不影響資料轉換周期。使用時鐘信号SCK(PIN7)控制轉換資料的輸出時,轉換結果将在時鐘CLK的下降沿由SDO腳輸出。在内部時鐘模式,SCK信号由LTC2400産生輸出在外部SCK模式,SCK為LTC2400外部輸入的時鐘信号。下面詳細介紹外部串行時鐘的三線接口方法。

  當LTC2400上電時,如果SCK為低電平,轉換進入外部串行模式;在CS信号的下降沿,SCK信号必須為低電平。

  當CS為高電平時,SDO為高阻态,此時,SDO連接配接的接口線可以作為其它應用。如果LTC2400在轉換和睡眠時CS為低電平,那麼,SDO的輸出狀态将用于訓示EOC。在AD轉換階段,SDO的輸出狀态EOC将變為高電平,而一旦轉換完成,EOC又變為低電平。在LTC2400處于睡眠狀态時,如果CS為低電平,系統會在SCK的上升沿将其喚醒。LTC2400的外部串行時鐘接口時序圖如下:

外設驅動庫開發筆記7:LTC2400系列ADC驅動

  CS信号除用來檢測LTC2400的狀态和輸出AD轉換資料外,還可用來控制全部串行資料輸出之前進行的新一次AD轉換。在LTC2400處于資料輸出狀态時,CS由低變高以停止串行輸出,同時開始新的AD轉換。

  由于在CS為高電平時,資料輸出端SDO為高阻态,是以,在LTC2400的轉換過程中,可通過将CS變為低電平來檢測轉換狀态。當CS為低電平時,SDO腳輸出的EOC信号為1,表示轉換正在進行;EOC為0表示轉換完成,系統處于睡眠狀态。當LTC2400處于睡眠狀态時,其轉換結果将儲存在内部移位寄存器中。CS為低可在SCK的上升沿喚醒LTC2400,此時轉換資料将在SCK的下降沿串行輸出。EOC通常在SCK的第一個上升沿被鎖存,直到第32個上升沿鎖存結束,同時,系統将在第32個下降沿開始的新一輪轉換。

  一般情況下,在資料輸出過程中,如果CS為低電平,那麼,系統将在SCK的第一個上升沿和第32個下降沿中間将CS變高以停止資料輸出。

1.3、工作過程

  LTC2400是一種低功耗、采用Δ-Σ技術且具有3線串行接口的AD轉換器,而且在AD轉換完成後将直接進入睡眠狀态。LTC2400的三線接口線分别是資料輸出(SDO)、時鐘(SCK)和片選(CS)。其工作流程如圖所示:

外設驅動庫開發筆記7:LTC2400系列ADC驅動

  LTC2400完成轉換就進入睡眠狀态。睡眠狀态的供電電流僅為20μA。若CS一直為高電平,晶片将保持睡眠狀态。進入睡眠狀态時,資料最後的轉換結果将儲存在晶片内部的靜态移位寄存器中。

  當CS變為低電平時,LTC2400開始輸出轉換結果,此時資料轉換沒有等待時間,輸出資料即為剛進行的轉換結果。該轉換結果是在串行時鐘SCK的控制下由SDO輸出的,并在SCK的下降沿更新,而在SCK的上升沿可靠讀取。當32位資料從LTC2400讀出或當CS被拉高時,資料輸出結束。此後LTC2400将自動開始新的資料轉換和重複周期。

2、驅動設計與實作

  我們已經了解了LTC2400模數轉換器的基本情況,接下來我們将設計并實作LTC2400模數轉換器的驅動程式。

2.1、對象定義

  首先我們需要抽象出LTC2400模數轉換器的對象類型。作為一個對象最起碼包括量方面的内容:屬性和操作。關于LTC2400模數轉換器的屬性我們簡單分析一下。LTC2400模數轉換器是一個主動發送資料的器件,并沒有需要配置的地方,僅有一個時鐘通過外部引腳設定,是以為了應用更清楚我們将其時鐘引腳的配置作為其屬性記錄下來。另一個其傳回的資料帶有狀态辨別,我們将其作為另一個屬性以記錄目前的狀态。

  至于操作也很簡單,首先我們要從LTC2400接收資料,而這個與具體的平台聯系緊密,是以我們将從LTC2400接收資料作為對象的一個操作。LTC2400模數轉換器采用SPI通訊接口,有時需要在軟體中對片選信号進行操作,是以我們将片選型号的操作作為對象的另一個操作。在一些情況下,有些針對對象的活動需要延時進行,而在不同的平台中采取的延時方式不盡相同,為了操作友善我們将延時操作作為對象的一個操作。于是我們可抽象的LTC2400的對象類型如下:

1 /* 定義LTC2400對象類型 */
2 typedef struct Ltc2400Object {
3        LTC2400ClockType clock;                                      //使用的時鐘
4        uint32_t dataCode;                                              //資料編碼
5        void (*Receive)(uint8_t *rData);                          //接收資料
6        void (*ChipSelect)(LTC2400CSType cs);                //實作片選
7        void (*Delayms)(volatile uint32_t nTime);            //實作ms延時操作
8 }Ltc2400ObjectType;      

  定義了LTC2400模數轉換器的對象類型,我們還需要設計對象的初始化函數,因為對象必須初始化後才能使用。初始化函數至少包含有2方面内容:一是為對象變量賦必要的初值;二是檢查這些初值是否是有效的。特别是一些操作指針錯誤的話可能産生嚴重的後果。基于這一原則,我們設計LTC2400模數轉換器的對象初始化函數如下:

1 /* LTC2400對象初始化函數 */
 2 void LTC2400Initialization(Ltc2400ObjectType *ltc,
 3                                       LTC2400ClockType clock,
 4                                       LTC2400Receive receive,
 5                                       LTC2400ChipSelect cs,
 6                                       LTC2400Delay msDelay)
 7 
 8 {
 9        if((ltc==NULL)||(receive==NULL)||(msDelay==NULL))
10        {
11               return;
12        }
13       
14        ltc->dataCode=0;
15        ltc->clock=clock;
16       
17        if(cs==NULL)     //硬體電路實作片選
18        {
19               ltc->ChipSelect=DefaultChipSelect;
20        }
21        else
22        {
23               ltc->ChipSelect=cs;
24        }
25       
26        ltc->Receive=receive;
27        ltc->Delayms=msDelay;
28 }      

  至此關于LTC2400模數轉換器的對象定義才算完成。在使用初始化函數時,需要注意片選操作函數,如果是采用硬體電路選中則可使用NULL作為參數。

2.2、對象操作

  我們擷取對象的目的就是希望通過對象來得到我們想要的資料。對于LTC2400模數轉器來說,就是從其接收ADC轉換資料。是以我們封裝LTC2400的操作函數如下:

1 /* 擷取LTC2400轉換資料,傳回量程資料的比例值 */
 2 float GetLtc2400Data(Ltc2400ObjectType *ltc)
 3 {
 4        uint8_t rData[4];
 5       
 6        ltc->ChipSelect(LTC2400CS_Enable);
 7        ltc->Delayms(1);
 8       
 9        ltc->Receive(rData);
10       
11        ltc->Delayms(1);
12        ltc->ChipSelect(LTC2400CS_Disable);
13       
14        return CompoundLTC2400Data(ltc,rData);
15 }      

  函數的傳回值是轉換結果的比例值,是一個浮點數,使用這一傳回結果結合具體浮點數的量成範圍就可以得到實體量值。

3、驅動的使用

  我們已經開發了LTC2400模數轉換器的驅動程式,接下來我們用一個簡單的執行個體驗證這一驅動。

3.1、聲明并初始化對象

  使用基于對象的操作我們需要先得到這個對象,是以我們先要使用前面定義的LTC2400模數轉換器對象類型聲明一個LTC2400模數轉換器對象變量,具體操作格式如下:

  Ltc2400ObjectType ltc2400;

       聲明了這個對象變量并不能立即使用,我們還需要使用驅動中定義的初始化函數對這個變量進行初始化。這個初始化函數所需要的輸入參數如下:

  Ltc2400ObjectType *ltc,所要初始化的對象

  LTC2400ClockType clock,采用時鐘方式

  LTC2400Receive receive,接收資料函數指針

  LTC2400ChipSelect cs,片選操作函數指針

  LTC2400Delay msDelay,延時函數指針

  對于這些參數,對象變量我們已經定義了。所使用的時鐘方式為枚舉,根據實際情況選擇就好了。主要的是我們需要定義幾個函數,并将函數指針作為參數。這幾個函數的類型如下:

1 /*定義接收資料函數指針類型*/
2 typedef void (*LTC2400Receive)(uint8_t *rData);
3 
4 /*定義片選信号函數指針類型*/
5 typedef void (*LTC2400ChipSelect)(LTC2400CSType cs);
6 
7 /*定義延時操作函數指針類型*/
8 typedef void (*LTC2400Delay)(volatile uint32_t nTime);      

  對于這幾個函數我們根據樣式定義就可以了,具體的操作可能與使用的硬體平台有關系。片選操作函數用于多裝置需要軟體操作時,如采用硬體片選可以傳入NULL即可。具體函數定義如下:

1 /*定義讀寫操作函數指針類型*/
 2 void LTC2400Recieve(uint8_t *rData)
 3 {
 4        HAL_SPI_Receive(&ltc2400hspi,rData,4,1000);
 5 }
 6  
 7 /*實作片選*/
 8 void LTC2400ChipSelected(LTC2400CSType cs)
 9 {
10        if(LTC2400CS_Enable==cs)
11        {
12               HAL_GPIO_WritePin(GPIOF, GPIO_PIN_4, GPIO_PIN_RESET);
13        }
14        else
15        {
16               HAL_GPIO_WritePin(GPIOF, GPIO_PIN_4, GPIO_PIN_SET);
17        }
18 }      

  對于延時函數我們可以采用各種方法實作。我們采用的STM32平台和HAL庫則可以直接使用HAL_Delay()函數。于是我們可以調用初始化函數如下:

  LTC2400Initialization(&ltc2400,INTERNAL_CLOCK50Hz,LTC2400Recieve,LTC2400ChipSelected,HAL_Delay);

  這裡我們将其初始化為使用改了内部時鐘,采用軟體控制片選信号。

3.2、基于對象進行操作

  我們定義了對象變量并使用初始化函數給其作了初始化。接着我們就來考慮操作這一對象擷取我們想要的資料。我們在驅動中已經将擷取資料并轉換為轉換值的比例值,接下來我們使用這一驅動開發我們的應用執行個體。

1 /* 擷取LTC2400測量的實體量值 */
 2 void GetLTC2400Value(void)
 3 {
 4        float ratio;
 5        float phyValue;
 6        float range=100.0;
 7        float zero=0.0;
 8       
 9        ratio=GetLtc2400Data(&ltc2400);
10       
11        phyValue=(range-zero)*ratio+zero;
12 }      

  在這一例中,我們計算了一個量程範圍為0到100的實體量的值,如果檢測的實體量不同,我們根據實際修改即可。

4、應用總結

  這一篇中,我們設計并實作了LTC2400模數轉換器的驅動程式,并使用這一驅動開發了擷取一個量程範圍為0到100的溫度信号的簡單應用,得到的結果與我們預期一緻,是以我們的驅動符合要求。

  在使用驅動時需注意,采用SPI接口的器件需要考慮片選操作的問題。如果片選信号是通過硬體電路來實作的,我們在初始化時給其傳遞NULL值。如果是軟體操作片選則傳遞我們編寫的片選操作函數。

  完整的源代碼可在GitHub下載下傳:https://github.com/foxclever/ExPeriphDriver

歡迎關注:

  

如果您希望更友善且及時的閱讀相關文章,關注我的微信公衆号【木南創智】