DAC在我們的項目中經常使用到,而使用最多的就是AD56xx系列,包括有單通道的AD5662、雙通道的AD5623和AD5663、以及四通道的AD5624和AD5664等。出于方便復用的原因,我們設計并實現AD56xx系列DAC的驅動。
1 、功能概述
AD56xx系列DAC屬于nanoDAC系列,是低功耗,12位、14位或者16位緩沖電壓輸出數模轉換器(DAC),采用2.7V至5.5V單電源供電。AD56xx采用多功能三線式串行接口,能夠以最高50 MHz的時鐘速率工作,并與標準SPI、QSPI、MICROWIRE、DSP接口標準兼容。它內置片內精密輸出放大器,能夠實現軌到軌輸出擺幅。其功能框圖如下所示:
AD56xx系列DAC都有一個24位的移位寄存器,所有的操作都是通過寫移位寄存器來實現的。對于不同的型號其移位寄存器的各位略有差異。具體如下圖所示:
單通道沒有通道選擇位,命令位只有2位,所以我們的軟件實際上就是針對不同的功能需求配置移位寄存器。
2 、驅動設計與實現
前面已經說過,對AD56xx的操作,實際就是根據需要配置移位寄存器。接下來我們將在此基礎上分析并實現AD56xx系列DAC的驅動。
2.1 、對象定義
在使用對象之前,我們需要抽象對象的定義。對于AD56xx系列DAC我們需要定義類型枚舉,因為該系列包含有多種DAC模塊。此外我們還要定義AD56xx系列DAC的對象類型。
/*定義DAC器件的類型*/
typedef enum AD56xx{
AD5662=0,
AD5623=1,
AD5643=2,
AD5663=3,
AD5624=4,
AD5644=5,
AD5664=6,
TypeNumber,
}AD56xxType;
/* 定義AD56XX對象類型 */
typedef struct AD56xxObject {
AD56xxType objectType; //DAC的類型
void(*WriteDataToDAC)(uint8_t *tData,uint16_t tSize); //向DAC發(fā)送數據
void(*ChipSelcet)(AD56xxCSType cs); //片選信號
}AD56xxObjectType;
我們抽象了對象,在我們使用這個對象定義聲明了一個具體的對象時,它只是一個代表對象的變量,我們需要對它進行初始化才可使用。于是我們定義初始化對象函數。
/* 初始化AD56xx對象 */
void AD56xxInitialization(AD56xxObjectType *dacObj,AD56xxTypeobjectType,AD56xxWritewrite,AD56xxChipSelcetcs)
{
if((dacObj==NULL)||(write==NULL)||(cs==NULL))
{
return;
}
if(objectTypeobjectType=objectType;
}
dacObj->WriteDataToDAC=write;
dacObj->ChipSelcet=cs;
}
2.2 、對象操作
我們已經將AD56xx抽象為對象,那么對AD56xx的操作都轉化為對某一個對象的操作。接下來我們來實現對象的操作函數。
2.2.1 、軟件復位
軟件復位也是通過操作輸入移位寄存器來實現的。命令位的定義沒有變化,數據段的最后一位作為軟件復位的模式設定,其它位無效。最后一位為0時,會清除DAC寄存器和輸入寄存器,而最后一位為1時清除掉全部寄存器。最后一位為1時,實際就是上電復位模式。輸入移位寄存器的數據格式如下:
其軟件實現如下:
/* 對AD56xx進行軟件復位 */
void Ad56xxSoftwareReset(AD56xxObjectType *dacObj,AD56xxResetTyperesetMode)
{
uint32_t inputShiftData=0;
if(resetMode==ResetSoftware)
{
inputShiftData=RESET|Register_Reset_Software;
}
if(resetMode==ResetPoweron)
{
inputShiftData=RESET|Register_Reset_Poweron;
}
uint8_t txData[3];
txData[0]=inputShiftData>>16;
txData[1]=inputShiftData>>8;
txData[2]=inputShiftData;
dacObj->ChipSelcet(AD56xxCS_Enable);
dacObj->WriteDataToDAC(txData,3);
dacObj->ChipSelcet(AD56xxCS_Disable);
}
2.2.2 、上電復位
上電復位也是通過操作輸入移位寄存器來實現的。命令位的定義沒有變化,數據段的DB5和DB4定義掉電的模式,而DB1和DB0定義操作的通道。輸入移位寄存器的數據格式如下:
其軟件實現如下:
/* 設置AD56xx上電/掉電工作模式 */
void Ad56xxPowerUpDownMode(AD56xxObjectType *dacObj,AD56xxChannelTypechannel,AD56xxPowerdownTypepowerdownType)
{
uint32_t inputShiftData=0;
uint32_t pdc=0;
uint32_t pdm=0;
uint32_t cmd=Power_Down;
uint32_t pdChannel[]={DAC_A,DAC_B,DAC_C,DAC_D,DAC_ALL,DAC_None};
pdc=pdChannel[channel];
uint32_t pdMode[]={Normal_Operation,_1K_GND,_100K_GND,Three_State};
pdm=pdMode[powerdownType];
if(dacObj->objectType==AD5662)
{
pdc=DAC_None;
pdm=(pdm<<12);
cmd=Write_to_Input_Register;
}
inputShiftData=cmd|pdc|pdm;
uint8_t txData[3];
txData[0]=inputShiftData>>16;
txData[1]=inputShiftData>>8;
txData[2]=inputShiftData;
dacObj->ChipSelcet(AD56xxCS_Enable);
dacObj->WriteDataToDAC(txData,3);
dacObj->ChipSelcet(AD56xxCS_Disable);
}
2.2.3 、 LDAC****功能
除去單通道的設備外,其他的AD56xx設備都具有LDAC操作功能。而對LDAC操作的寄存器設置如下圖所示:
其軟件實現如下:
/* 設置AD56xx及同類器件LDAC功能 */
void SetAd56xxLdacFunction(AD56xxObjectType *dacObj,AD56xxChannelTypechannel)
{
uint32_t inputShiftData=0;
uint32_t pdChannel[]={DAC_A,DAC_B,DAC_C,DAC_D,DAC_ALL,DAC_None};
inputShiftData=pdChannel[channel];
inputShiftData=inputShiftData|LDAC_Register_Setup;
uint8_t txData[3];
txData[0]=(uint8_t)(inputShiftData>>16);
txData[1]=(uint8_t)(inputShiftData>>8);
txData[2]=(uint8_t)inputShiftData;
dacObj->ChipSelcet(AD56xxCS_Enable);
dacObj->WriteDataToDAC(txData,3);
dacObj->ChipSelcet(AD56xxCS_Disable);
}
2.2.4 、內部基準電壓源設置
有一些型號以R結尾的AD56xx器件是包含有內部參考電源的。片內基準電壓源在上電時默認關閉。通過設置控制寄存器中的軟件可編程位DB0,可以開啟或關閉此基準電壓源。具體的寄存器設置如下圖所示:
其軟件實現如下:
/* 開啟或關閉內部參考電壓源 */
void SetInternalReference(AD56xxObjectType*dacObj,AD56xxRefTyperef)
{
uint32_t inputShiftData=0;
inputShiftData=Reference_Set;
if(ref==AD56xxRef_ON)
{
inputShiftData=inputShiftData|Reference_ON;
}
uint8_t txData[3];
txData[0]=(uint8_t)(inputShiftData>>16);
txData[1]=(uint8_t)(inputShiftData>>8);
txData[2]=(uint8_t)inputShiftData;
dacObj->ChipSelcet(AD56xxCS_Enable);
dacObj->WriteDataToDAC(txData,3);
dacObj->ChipSelcet(AD56xxCS_Disable);
}
2.3.5 、輸出操作
對各輸出通道值的操作也是通過輸入移位寄存器來完成。其數據格式如前面輸入移位寄存器的介紹。后16位是數據(0-65535),然后是3位地址和3位命令。通訊的時序圖如下所示:
其軟件實現如下:
/* 設置DA通道的值 */
void SetAD56xxChannelValue(AD56xxObjectType *dacObj,AD56xxChannelTypechannel,uint16_t data)
{
uint32_t inputShiftData=0;
uint32_t dac=0;
uint32_t cmd=WriteTo_Update_DAC_Channel;
uint32_t dacChannel[]={DAC_Channel_A,DAC_Channel_B,DAC_Channel_C,DAC_Channel_D,DAC_Channel_ALL};
uint32_t shiftV[]={0,4,2,0,4,0};
if(channel>=ChannelNone)
{
return;
}
dac=dacChannel[channel];
if(dacObj->objectType==AD5662)
{
dac=DAC_Channel_A;
cmd=Write_to_Input_Register;
}
inputShiftData=dac|cmd|(data<objectType]);
uint8_t txData[3];
txData[0]=(uint8_t)(inputShiftData>>16);
txData[1]=(uint8_t)(inputShiftData>>8);
txData[2]=(uint8_t)inputShiftData;
dacObj->ChipSelcet(AD56xxCS_Enable);
dacObj->WriteDataToDAC(txData,3);
dacObj->ChipSelcet(AD56xxCS_Disable);
}
3 、驅動的使用
我們已經實現了AD56xx系列DAC的驅動,接下來我們就可以使用我們的這個驅動實現我們的應用了。
3.1 、聲明并初始化對象
首先需要使用AD56xx對象類型AD56xxObjectType聲明一個對象變量。具體聲明形式如下:AD56xxObjectType ad56xx;
對象變量需要使用AD56xxInitialization函數進行初始化。這個函數的參數除了對象變量外還有對象類型以及寫數據操作和片選操作2個函數指針。在調用初始化函數之前必須準備好這些參數。所以我們需要按如下類型定義相關函數。
/* 向DAC發(fā)送數據函數指針類型 */
typedef void(*AD56xxWrite)(uint8_t *tData,uint16_t tSize);
/* 片選操作函數指針類型 */
typedef void(*AD56xxChipSelcet)(AD56xxCSType cs);
我們實現這幾個函數并將函數指針作為參數傳遞給初始化函數。初始化函數的調用樣式如下:
AD56xxInitialization(&ad56xx,objectType,write,cs);
后兩個參數即是上面定義的2個函數的函數指針。這兩個函數根據具體的硬件電路來實現。第二個參數為對象類型,為AD56xxType枚舉類型。
3.2 、基于對象進行操作
初始化完成后就可以操作對象了。對AD56xx系列DAC對象的操作包括:軟件復位操作,上下電模式控制,LDAC控制,參考電壓操作以及輸出控制。下面將調用驅動函數實現相應的應用。
AD56xx系列DAC擁有1到4個通道,所以我們需要為操作制定通道。還有向該通道設定的數據,由于AD56xx系列DAC為12到16位,所以我們要發(fā)送一個不超過16位的無符號整數。有了這兩個參數我們就可以調用SetAD56xxChannelValue函數為AD56xx系列DAC設定輸出了。
SetAD56xxChannelValue(&ad56xx,channel,data);
第二個參數為設定的通道,是一個AD56xxChannelType類型的枚舉,以此決定我們當前操作的是哪一個通道。而其它的函數:
/*設置AD56xx上電/掉電工作模式*/
void Ad56xxPowerUpDownMode(AD56xxObjectType *dacObj,AD56xxChannelTypechannel,AD56xxPowerdownType powerdownType);
/*對AD56xx進行軟件復位*/
void Ad56xxSoftwareReset(AD56xxObjectType *dacObj,AD56xxResetTyperesetMode);
/* 開啟或關閉內部參考電壓源 */
void SetInternalReference(AD56xxObjectType *dacObj,AD56xxRefTyperef);
/*設置AD56xx及同類器件LDAC功能*/
void SetAd56xxLdacFunction(AD56xxObjectType*dacObj,AD56xxChannelType channel);
其調用方式是類似的。需要指出的是SetInternalReference函數,只有具有內部參考電源的器件調用這個函數才有作用。
4 、應用總結
我們使用AD56xx系列DAC實現過多種應用,都是基于我們的驅動開發(fā)的。使用的結果基本都與我們的預期一樣。
需要注意對象的類型,特別是AD5662的移位寄存器有很大區(qū)別。雖然驅動在這一方面作了處理,但是基于初始化時配置的類型執(zhí)行的。所以在調用初始化函數初始化對象時一定要傳遞正確的類型。
**源碼公布到GitHUB:**https://github.com/foxclever/ExPeriphDriver
評論
查看更多