1. 程式人生 > >有關DSP2812與SPI介面DA晶片的通訊(AD5640,AD5682)

有關DSP2812與SPI介面DA晶片的通訊(AD5640,AD5682)

使用DSP2812控制SPI介面DA晶片總結:

本文只針對SPI介面的DA晶片,通常用到的DA晶片有精度位16位/14位/12位的。我在這次過程中用到的都是14位的,剛開始使用的是AD5640的DA晶片,其精度為14位,移位暫存器為16位,前2位是工作模式位(一般選正常工作模式就行),後14位是資料,剛剛好,DSP2812的資料輸出暫存器(SPITXBUF)也是16位,只需要設定SPICCR暫存器資料位為16位即可,由於AD5640是要求下降沿資料輸入,因此DSP2812配置為上升沿輸出,具體看SPI介面時序圖。在配置完資料輸出字元長度和極性(DSP資料上升沿輸出,下降沿輸入),接下來再配置DSP為主模式,設定時鐘相位(選正常的SPI時鐘),配置波特率(根據DSP低速外設時鐘設定,AD5640可達30MHz),復位SPI模組,設定為自由執行模式,這樣,DSP2812與AD5640的SPI介面已配置完畢,接下來對AD5640的操作就很簡單了,只需要通過SPITXBUF傳送資料就可以,相關原始碼如下:

#include "DSP281x_Device.h"
#include "DSP281x_Examples.h"   
#include "math.h"

void InitSpii(void); //SPI初始化

extern Uint16 RamfuncsLoadStart;
extern Uint16 RamfuncsLoadEnd;
extern Uint16 RamfuncsRunStart;

int main(void) {

InitSysCtrl();  //初始化系統控制暫存器、Pll、看門狗和時鐘

 MemCopy(&RamfuncsLoadStart, &RamfuncsLoadEnd, &RamfuncsRunStart);
 InitFlash();

 InitGpio();        //GPIO初始化

 DINT; //禁止和清除所有CPU中斷向量表
 InitPieCtrl();//初始化PIE控制暫存器
 IER = 0x0000;//禁止CPU中斷
 IFR = 0x0000;//清除CPU中斷標誌
 InitPieVectTable();//初始化中斷向量表

 InitPeripherals();         //模組初始化

EINT;          // Enable Global interrupt INTM   //使能所有CPU中斷向量表
//ERTM;          // Enable Global realtime interrupt DBGM   使能DEBUG中斷
while(1)
{
SpiaRegs.SPITXBUF=6000;  
}

void InitSpii(void)
{
//AD5640

// Initialize SPIA:
SpiaRegs.SPICCR.all=0x004F;//復位、下降沿有效、16位資料
SpiaRegs.SPICTL.all=0x0006;//主模式、使能傳送、禁止中斷
SpiaRegs.SPIBRR=0x007E;         //SPICLK
SpiaRegs.SPICCR.all=0x008F;     //退出復位、SPI CHAR 16bit
SpiaRegs.SPIPRI.bit.FREE=1;     //設定為自由執行模式

// Initialize SPIA-FIFO:
SpiaRegs.SPIFFTX.all=0xE040;
SpiaRegs.SPIFFRX.all=0x205F;
SpiaRegs.SPIFFCT.all=0x0000;

SpiaRegs.SPITXBUF=4800;        


//////////////////////////////////////////////////////////////////////////////
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

在我實現了DSP與AD5640的通訊以後,一切使用都很正常,可是在生產過程中,硬體工程師這邊總是反饋到這個晶片不正常工作,後來注意到這個晶片的焊接溫度不是很高,小批量生產都是生產人員焊接的,沒有注意到這一點,硬體工程師提出更換DA晶片,在供應商的推薦下,選擇了後面要說到的AD5682R這款晶片,說是封裝一樣,精度一樣,可以替換。後來就換了,後來發現通訊不對,我查看了資料手冊,原來它的移位暫存器是24位,分控制命令和資料輸入命令。


上面這張表就是介紹它的命令:

命令一:無任何操作;

命令二:將資料寫入輸入暫存器;

命令三:將輸入暫存器中的資料跟新到DAC暫存器,也就是讓其生效,實現數模轉換;

命令四:將資料寫入到輸入暫存器的同時跟新到DAC暫存器,同時完成命令二和命令三的操作;

命令五:寫控制暫存器,配置暫存器的相關引數;

命令六:讀回輸入暫存器的值;

一般操作,只使用命令四和命令五,在SPI介面初始化完成後,在進入大迴圈之前,使用命令五完成DA5682R的相關引數的配置,在大迴圈裡只需要用到命令四實現DA轉換。命令二,命令三,命令四中,高四位是命令位,接著的14位是資料位,後面的低六位是無效位。命令五的高四位是命令位,接著六位是配置控制暫存器位,後面的低14位全為0。使用過程嚴格按照資料格式使用。


上面這張表就是命令五,即配置控制暫存器的配置位,需要根據自己的實際使用情況來配置。下面介紹這些位的配置:

Reset:

這個復位位在使用傳送資料前,復位一次,置1復位DA,復位後自動清0;


工作模式選擇:

一般選擇正常工作模式,後面幾種都是設定為掉電模式,一般在考慮到功耗的時候會用到。


REF設定:

即參考電壓設定,置0,是預設的,選擇為內部參考;

置1,設定外部參考電壓;


Gain:

gain的設定,是選擇輸出電壓的範圍,置0,是預設的,輸出電壓是以參考電壓為準,(0V—VREF);

置1,輸出電壓是0V-2*VREF;


DCEN:

設定此位為0,就是在輸入的資料寫滿移位暫存器,即24位就進行處理;

置該位為1,就可以輸入任意長度的資料,但是隻去最後的24位,丟掉高位;


經過以上的配置,即完成了控制暫存器的配置,傳送資料使用命令四即可。

由於AD5682R的移位暫存器是24位,而2812可以設定傳送的資料位為1-16位;(1)因此可以設定為16位資料位,但是要將DCEN設定為1。連續輸入兩次,要將有效位放在低24位。(2)可以將設定位12位資料位,連續輸入二次,也不需要DCEN置1,;(3)可以將資料位設為8位,連續輸入三次;怎麼方便怎麼來;

我使用的命令如下:

控制命令:0x480000;//命令五,配置控制暫存器,復位,其他全置0;

資料命令:0x312c00;//命令四,4位命令位後的14位為資料,低6位無效;

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

那麼問題來了,在我將資料位設定為8位,連續發三次,或者資料位設定為12位,連續發兩次,通訊都不正常,很鬱悶,又看了手冊,SPI介面的極性,相位,波特率都沒問題,還是不行。

我在程式裡是這麼寫的:

配置為12位:

控制:SpiaRegs.SPITXBUF = 0x480;

 SpiaRegs.SPITXBUF = 0x000;

資料輸入:假設資料為12c0

SpiaRegs.SPITXBUF = 0x312;

SpiaRegs.SPITXBUF = 0xc00;

配置為8位:

控制:SpiaRegs.SPITXBUF = 0x48;

 SpiaRegs.SPITXBUF = 0x00;

SpiaRegs.SPITXBUF = 0x00;

資料輸入:假設資料為12c0

SpiaRegs.SPITXBUF = 0x31;

SpiaRegs.SPITXBUF = 0x2c;

SpiaRegs.SPITXBUF = 0x00;

拿過示波器,四個通道分別檢測片選,時鐘,輸入,輸出;

片選正常,時鐘正常,輸入的資料好像不太對,沒有輸出;

最後通過示波器發現一個問題,一直忘了,只顧著傳送的資料位,忘了SPITXBUF是16位,很關鍵,SPITXBUF是16位,SPITXBUF是16位,SPITXBUF是16位,重要的事說三遍;

比如:設定為8位資料位:SpiaRegs.SPITXBUF = 0x48;就相當於是SpiaRegs.SPITXBUF = 0x0048;,發過去的是高8位;

設定為12位資料位:SpiaRegs.SPITXBUF = 0x480;就相當於是SpiaRegs.SPITXBUF = 0x0480;,發過去的是高12位;

發過去的和我想要發過去的完全不一樣;

這樣就很清楚了,設定SPI通訊的資料位跟SPITXBUF是兩回事,設定資料位為16位,那麼SPITXBUF所有位有效;設定資料位為12位,那麼SPITXBUF高12位有效;

設定資料位為8位,那麼SPITXBUF高8位有效;這樣,就找到問題的根源了。

不使用24位移位暫存器發現不了這樣的問題。

DSP2812與AD5682R的SPI通訊程式碼如下:



#include "DSP281x_Device.h"
#include "DSP281x_Examples.h"   
#include "math.h"

void InitSpii(void); //SPI初始化
unsigned int Spi_TxReady(void);//SPI傳送資料判別
void spiakz(void);//  AD5683R --SPI傳送控制指令
void spia_xmit(Uint16 a);//AD5683R -- SPI資料傳送

extern Uint16 RamfuncsLoadStart;
extern Uint16 RamfuncsLoadEnd;
extern Uint16 RamfuncsRunStart;

int main(void) {

InitSysCtrl();  //初始化系統控制暫存器、Pll、看門狗和時鐘

MemCopy(&RamfuncsLoadStart, &RamfuncsLoadEnd, &RamfuncsRunStart);
InitFlash();

InitGpio();       //GPIO初始化

DINT;//禁止和清除所有CPU中斷向量表
InitPieCtrl();//初始化PIE控制暫存器
IER = 0x0000;//禁止CPU中斷
IFR = 0x0000;//清除CPU中斷標誌
InitPieVectTable();//初始化中斷向量表

InitPeripherals();         //模組初始化

EINT;          // Enable Global interrupt INTM   //使能所有CPU中斷向量表
//ERTM;          // Enable Global realtime interrupt DBGM   使能DEBUG中斷
spiakz();
spia_xmit(4800);
while(1)
{
spia_xmit(6000);
}

void InitSpii(void)
{

//AD5682R

// Initialize SPIA:
SpiaRegs.SPICCR.all=0x000b;//復位、下降沿有效、8位資料
SpiaRegs.SPICTL.all=0x0006;//主模式、使能傳送、禁止中斷
SpiaRegs.SPIBRR=0x007E;         //SPICLK
SpiaRegs.SPICCR.all=0x008b;     //退出復位、SPI CHAR 8bit
SpiaRegs.SPIPRI.bit.FREE=1;     //設定為自由執行模式

SpiaRegs.SPIFFTX.all=0xE040;
SpiaRegs.SPIFFRX.all=0x205F;
SpiaRegs.SPIFFCT.all=0x0000;

}
void spiakz(void)
{
SpiaRegs.SPITXBUF = 0x4800;
while(Spi_TxReady() != 1){}
SpiaRegs.SPITXBUF = 0x0000;
DELAY_US(100);
}

unsigned int Spi_TxReady(void)
{
unsigned int i;
if(SpiaRegs.SPISTS.bit.BUFFULL_FLAG == 1)
{
i = 0;
}
else
{
i = 1;
}
return i;
}

void spia_xmit(Uint16 a)
{

SpiaRegs.SPITXBUF = (0x3000 | (a >> 2));
while(Spi_TxReady() != 1){}
SpiaRegs.SPITXBUF = (a << 10);
DELAY_US(100);
}

總結:通過對這兩個DA晶片的使用,認識到了移位暫存器和傳送資料暫存器位數不一致如何使用。