模擬信號(hào)輸出是經(jīng)常會(huì)遇到的應(yīng)用需求,解決的辦法應(yīng)多種,但我們使用最多的還是數(shù)模轉(zhuǎn)換。對(duì)于不同的數(shù)模轉(zhuǎn)換器我們需要為其編寫(xiě)適用的驅(qū)動(dòng)程序,在這一篇中我們就來(lái)考慮如何實(shí)現(xiàn)DAC8552高精度模數(shù)轉(zhuǎn)換器的驅(qū)動(dòng)程序。
1、功能概述
??該DAC8552是一個(gè)16位,雙通道,電壓輸出數(shù)模轉(zhuǎn)換器(DAC)提供低功率操作和靈活的串行主機(jī)接口。每個(gè)芯片上的精確輸出放大器允許軌到軌輸出擺動(dòng),以實(shí)現(xiàn)在2.7V到5.5V的供應(yīng)范圍。該設(shè)備支持標(biāo)準(zhǔn)三線串行接口,能夠操作與輸入數(shù)據(jù)時(shí)鐘頻率高達(dá)30MHz的VDD = 5V。
1.1、功能結(jié)構(gòu)
??DAC8552這種設(shè)備在正常情況下的低功耗使得它非常適合便攜式、電池驅(qū)動(dòng)設(shè)備和其他低功耗應(yīng)用。采用SOIC-8的封裝形式,引腳定義如下:
??DAC8552需要一個(gè)外部參考電壓來(lái)設(shè)置每個(gè)DAC通道的輸出范圍。DAC8552還包括一個(gè)電源上電復(fù)位電路,以確保DAC輸出功率能夠輸出到零,并保持在那里,直到獲取一個(gè)有效的寫(xiě)入值。DAC8552擁有一個(gè)SPI串行接口,該接口提供了靈活的功能。
??從上述結(jié)構(gòu)圖可知,DAC8552每次僅能操作一路輸出,因?yàn)槿康牟僮鞫际峭ㄟ^(guò)同一個(gè)移位寄存器來(lái)實(shí)現(xiàn)的。
1.2、移位寄存器
??DAC8552有一個(gè)24位的輸入移位寄存器,前面8位用來(lái)作控制位,后面16位用作數(shù)據(jù)位。具體如下圖所示:
??在前面的8位控制位中,DB23和DB22是保留位必須為“0”,DB21(LDB)位和DB20(LDA)用于控制后面的16位數(shù)據(jù)適用于加載哪一個(gè)輸出通道還是Power_Down命令。DB19沒(méi)有定義,DAC8552不關(guān)心該位的具體數(shù)值。DB18為緩沖器選擇位,用于控制數(shù)據(jù)的目標(biāo)通道是DAC A還是DAC B。后續(xù)的DB17(PD1)和DB16(PD0)用于選擇Power_Down的模式。具體的命令如下表中描述:
??至于Power_Down的模式有幾種選擇,如下表所示:
2、驅(qū)動(dòng)設(shè)計(jì)與實(shí)現(xiàn)
??我們已經(jīng)了解了DAC8552的基本結(jié)構(gòu)及寄存器命令,接下來(lái)我們將根據(jù)這些認(rèn)知設(shè)計(jì)DAC8552的驅(qū)動(dòng)程序。
2.1、對(duì)象定義
??在設(shè)計(jì)DAC8552的驅(qū)動(dòng)程序之前,我們先來(lái)考慮一下DAC8552的對(duì)象定義問(wèn)題。我們作為一個(gè)對(duì)象一般會(huì)包括屬性和操作兩個(gè)方面的內(nèi)容。我們先來(lái)分析DAC8552對(duì)象應(yīng)該包含有哪些屬性。屬性用于標(biāo)識(shí)對(duì)象的某些特性,DAC8552通過(guò)SPI總線下發(fā)數(shù)據(jù)和命令,我們沒(méi)有發(fā)現(xiàn)什么需要特別標(biāo)記的特性,所以我們不需要為DAC8552對(duì)象設(shè)計(jì)屬性。
??我們?cè)賮?lái)看一看,DAC8552對(duì)象需要實(shí)現(xiàn)哪些操作。首先DAC8552使用SPI總線進(jìn)行通訊,而SPI總線采用片選信號(hào)來(lái)區(qū)分不同的節(jié)點(diǎn),所以我們需要操作DAC8552的片選信號(hào),而片選型號(hào)的操作顯然依賴于特定的操作平臺(tái),所以我們將控制其片選信號(hào)作為DAC8552對(duì)象的一個(gè)操作。另外,DAC8552作為模擬量輸出對(duì)象,我們需要向其發(fā)送命令和數(shù)據(jù),而向其發(fā)送數(shù)據(jù)和命令也依賴于具體的操作平臺(tái),所以應(yīng)將其作為對(duì)象的一個(gè)操作來(lái)實(shí)現(xiàn)。據(jù)此我們可以定義DAC8552的對(duì)象類型如下:
/* 定義DAC8552對(duì)象類型 */
typedef struct DAC8552Object {
void (*WriteDataToDAC)(uint8_t *tData,uint16_t tSize); //向DAC發(fā)送數(shù)據(jù)
void (*ChipSelcet)(DAC8552CSType cs); //片選信號(hào)
}DAC8552xObjectType;
??我們定義了DAC8552的對(duì)象類型,但當(dāng)我們使用其聲明一個(gè)對(duì)象時(shí),并不能直接使用,我們需要對(duì)對(duì)象進(jìn)行初始化,這就需要我們?cè)O(shè)計(jì)一個(gè)對(duì)象初始化的函數(shù)。對(duì)象初始化函數(shù)處理對(duì)象相關(guān)的屬性和操作的配置,具體實(shí)現(xiàn)如下:
/*初始化DAC8552對(duì)象*/
void DAC8552Initialization(DAC8552xObjectType *dac, //DAC8552對(duì)象變量
DAC8552WriteType write, //寫(xiě)數(shù)據(jù)函數(shù)指針
DAC8552ChipSelectType cs //片選操作函數(shù)指針
)
{
if((dac==NULL)||(write==NULL))
{
return;
}
if(cs!=NULL)
{
dac->ChipSelcet=cs;
}
else
{
dac->ChipSelcet=DefaultChipSelect;
}
}
2.2、對(duì)象操作
??我們已經(jīng)定義了DAC8552的對(duì)象類型并為DAC8552對(duì)象設(shè)計(jì)了初始化函數(shù),接下來(lái)我們看一看DAC8552所要實(shí)現(xiàn)的操作。對(duì)于DAC8552對(duì)象來(lái)說(shuō),我們對(duì)其操作無(wú)非就是寫(xiě)其移位寄存器以實(shí)現(xiàn)命令和數(shù)據(jù)的下發(fā)。從其數(shù)據(jù)表中我們可以看到操作移位寄存器的時(shí)序如下所示:
??根據(jù)我們前面對(duì)DAC8552相關(guān)數(shù)據(jù)的了解以及上述時(shí)序圖,我們可以封裝對(duì)其移位寄存器的操作函數(shù)如下:
/*操作DAC8552輸出通道*/
void SetDAC8552ChannelValue(DAC8552xObjectType *dac,DAC8552LDType ld,DAC8552BSType bs,DAC8552PDType pd,uint16_t data)
{
uint32_t inputShiftData=0;
uint8_t sData[3];
inputShiftData=data;
inputShiftData=inputShiftData|(ld<<20);
inputShiftData=inputShiftData|(bs<<18);
inputShiftData=inputShiftData|(pd<<16);
sData[0]=(uint8_t)(inputShiftData>>16);
sData[1]=(uint8_t)(inputShiftData>>8);
sData[2]=(uint8_t)inputShiftData;
dac->ChipSelcet(DAC8552CS_Enable);
dac->WriteDataToDAC(sData,3);
dac->ChipSelcet(DAC8552CS_Disable);
}
3、驅(qū)動(dòng)的使用
??我們?cè)O(shè)計(jì)了DAC8552的對(duì)象驅(qū)動(dòng),但這個(gè)驅(qū)動(dòng)是否正確我們需要驗(yàn)證一下。所以接下來(lái)我們?cè)O(shè)計(jì)一個(gè)簡(jiǎn)單的例子來(lái)實(shí)現(xiàn)對(duì)驅(qū)動(dòng)程序的驗(yàn)證。
3.1、聲明并初始化對(duì)象
??我們使用設(shè)計(jì)的驅(qū)動(dòng)程序操作DAC8552時(shí),首先需要使用我們定義的對(duì)象類型聲明一個(gè)DAC8552對(duì)象。
DAC8552xObjectType dac8552;
??聲明了這個(gè)對(duì)象變量之后,我們還需要使用初始化函數(shù)對(duì)其進(jìn)行初始化方可使用。這一初始化函數(shù)擁有3個(gè)參數(shù):
DAC8552xObjectType *dac, //DAC8552對(duì)象變量
DAC8552WriteType write, //寫(xiě)數(shù)據(jù)函數(shù)指針
DAC8552ChipSelectType cs //片選操作函數(shù)指針
??第一個(gè)參數(shù)正是我們要初始化的對(duì)象變量;第二個(gè)參數(shù)為向DAC8552寫(xiě)命令和數(shù)據(jù)的函數(shù)指針;第三個(gè)參數(shù)是片選信號(hào)操作函數(shù)指針。這兩個(gè)函數(shù)指針需要我們實(shí)現(xiàn)。它們的原型如下:
/* 向DAC發(fā)送數(shù)據(jù)函數(shù)指針類型 */
typedef void (*DAC8552WriteType)(uint8_t *tData,uint16_t tSize);
/* 片選操作函數(shù)指針類型 */
typedef void (*DAC8552ChipSelectType)(DAC8552CSType cs);
??我們根據(jù)函數(shù)原型定義,在具體的實(shí)現(xiàn)平臺(tái)上實(shí)現(xiàn)它們,如我們?cè)?a href="http://www.socialnewsupdate.com/v/tag/751/" target="_blank">STM32平臺(tái)上實(shí)現(xiàn)如下:
/*定義片選信號(hào)函數(shù)*/
void DAC8552CS(DAC8552CSType en)
{
if(DAC8552CS_Enable==en)
{
HAL_GPIO_WritePin(GPIOF, GPIO_PIN_4, GPIO_PIN_RESET);
}
else
{
HAL_GPIO_WritePin(GPIOF, GPIO_PIN_4, GPIO_PIN_SET);
}
}
/*定義發(fā)送數(shù)據(jù)函數(shù)*/
void DAC8552TransmitData(uint8_t *wData,uint16_t wSize)
{
HAL_SPI_Transmit (&dac8552hspi, wData, wSize, 1000);
}
??我們將對(duì)象變量以及上面實(shí)現(xiàn)的2個(gè)函數(shù)的函數(shù)指針作為參數(shù)傳遞給DAC8552對(duì)象初始化函數(shù)來(lái)實(shí)現(xiàn)對(duì)象變量的初始化。具體如下:
DAC8552Initialization(&dac8552, //DAC8552對(duì)象變量
DAC8552TransmitData, //寫(xiě)數(shù)據(jù)函數(shù)指針
DAC8552CS //片選操作函數(shù)指針
);
3.2、基于對(duì)象進(jìn)行操作
??初始化對(duì)象變量后,我們就可以基于該對(duì)象變量實(shí)現(xiàn)我們對(duì)DAC8552的操作了。我們已經(jīng)封裝了對(duì)其移位寄存器操作的函數(shù),直接調(diào)用該函數(shù)來(lái)說(shuō)實(shí)現(xiàn)我們的操作。一個(gè)簡(jiǎn)單的實(shí)現(xiàn)函數(shù)如下:
/* 修改DAC8552的通道輸出 */
void DAC8552Operation(void)
{
uint16_t wData=0;
wData=(uint16_t)(65535*tValueA/100);
SetDAC8552ChannelValue(&dac8552, //所操作的DAC對(duì)象
DAC8552_LoadA, //加載的通道
DAC8552BS_BufferA, //選擇的緩存
DAC8552PD_Normal, //Power-Down設(shè)置
wData //所寫(xiě)的數(shù)據(jù)
);
wData=(uint16_t)(65535*tValueB/100);
SetDAC8552ChannelValue(&dac8552, //所操作的DAC對(duì)象
DAC8552_LoadB, //加載的通道
DAC8552BS_BufferB, //選擇的緩存
DAC8552PD_Normal, //Power-Down設(shè)置
wData //所寫(xiě)的數(shù)據(jù)
);
}
??在這個(gè)例子中我們分別通過(guò)百分比設(shè)定值調(diào)整了A、B通道的輸出,實(shí)現(xiàn)在正常模式下操作A或者B通道,并更新指定的緩存。
4、應(yīng)用總結(jié)
??我們?cè)O(shè)計(jì)并實(shí)現(xiàn)了DAC8552模數(shù)轉(zhuǎn)換器的驅(qū)動(dòng)程序,并且設(shè)計(jì)了一個(gè)簡(jiǎn)單的應(yīng)用來(lái)驗(yàn)證這一驅(qū)動(dòng)程序的正確性。所得到的結(jié)果證明驅(qū)動(dòng)的設(shè)計(jì)是沒(méi)有問(wèn)題的,實(shí)際上我們已經(jīng)將其運(yùn)用到實(shí)際的項(xiàng)目中,效果良好。
??在使用驅(qū)動(dòng)程序時(shí)需要注意,片選信號(hào)并非必須實(shí)現(xiàn)。因?yàn)橛行r(shí)候我們可能需要在硬件上直接將其選中,此時(shí)添加片選操作函數(shù)是沒(méi)有什么意義的,我們可以在初始化時(shí)傳入NULL來(lái)完成。
評(píng)論