2012-09-25 27 views
0

我試圖使用可編程波形發生器AD9833用ATmega32的-A的微控制器,用於產生正弦波AD9833波形發生器。(MCLK = 8MHz的時鐘頻率)。我使用USART通信,所以如果我改變超級終端的頻率,那麼波形頻率必須改變。 我寫了如下所示的小代碼。需要幫助與ATmega32的-A微控制器

但是從上面的代碼我產生正弦波,但如果我想改變信號頻率到125KHz那麼我必須在超級終端輸入499.9KHz。如果我輸入125KHz,那麼它顯示31.2KHz。我不知道爲什麼它會像這樣產生,我做了什麼錯誤?並且它正在改變波形直到500KHz的頻率假設如果我輸入1000KHz左右的波形頻率,但沒有信號頻率改變它只顯示125KHz。

最後我想生成具有不同頻率的波形。如果我改變超級終端或膩子的頻率,那麼我輸入它的頻率必須以那個頻率產生波形。

這是我的第一篇文章,所以如果任何語法錯誤都沒有,那麼請原諒我。

在此先感謝。

 void unicom(void){ 

     switch(Command){ 


       case(WGF): 
      if(Param < 500) 
       SetWGFreq(Param); 
       Command = 0; 
      break; 

       case.... 
       case.... 
       default: 
      } 

    void main(void){ 
    SetWGFreq(125); 
    ----------- 
    -------- 
    } 

嗨再次

這一次,我想通過SPI SM470R1B1M-HT單片機編程AD9833。我正在按照下面的「羅斯」所解釋的原則。 看來我無法改變正弦波頻率。 下面是我正在嘗試的代碼,我用以前的時鐘設置相同的配置。

void SetupSPI(void); 
unsigned char spi(unsigned char data); 
void SetWGFreq(unsigned int); 
void setFrequencyA(unsigned long fdata); 
void WG_CS_Status(int status); 

int main(void) 
{ 
GCR &= ~ZPLL_MULT4; 
GCR &= ~ZPLL_CLK_DIV_PRE1; 
GCR &= ~ZPLL_CLK_DIV_PRE2; 
GCR &= ~ZPLL_CLK_DIV_PRE3; 

PCR = CLKDIV_1;       // ICLK = SYSCLK 
PCR |= PENABLE;       // Enable peripherals 

GIODIRA |= X7; 

CLKCNTL |= CLKDIR | CLKSR_ICLK; 

SetupSPI(); 

for(;;) 
{ 
    //SetWGFreq(25); 
    setFrequencyA(1045200); 
}        // Wait in endless loop 
} 

void SetupSPI(void) 
{ 
int data = 0; 

SPI2CTRL1 = CHARLEN_8 + PRESCALE_4;    // 8 bits per xfer 
SPI2CTRL2 |= CLKMOD + MASTER + POLARITY;    // We are the master 
SPI2PC6 |= SOMI_FUN | SIMO_FUN | CLK_FUN; 
// SPI2PC6 |= 0x0E; 
// enable 
SPI2CTRL2 |= SPIEN; 

data = SPI2BUF; 
} 

unsigned char spi(unsigned char data) 
{ 
    SPI2DAT1 = data;    
    while(!(SPI2CTRL3 & 0x01)){}  // Wait for RxFlag to get set  
    return (SPI2BUF & 0x000000FF);  // Read SPIBUF 
} 

void setFrequencyA(unsigned long fdata) 
{ 
WG_CS_Status(0); 
while(GIODOUTA&X7); // Delay 
spi(0x20);  // Initiate loading of frequence register 0 by 28 bits. 
spi(0x00); 
spi((0x40 | (0x3F & (fdata >> 8)))); // load bit 8-13 + 0x40. 
spi(fdata);        // load bit 0-7 
spi((0x40 | (0x3F & (fdata >> 22)))); // load bit 22-27 + 0x40. 
spi(fdata >> 14);      // load bit 14-21 
spi(0); // dummy write 
WG_CS_Status(1); 
} 
void WG_CS_Status(int status) 
{  
if(status == 0) 
    { 
    // Make Chip Select low 
    GIODOUTA &= ~X7; 
    } 
else 
    { 
    // Make Chip select high 
    GIODOUTA |= X7; 
    } 
} 

我附上了SPI引導我休耕此控制器和AD9833編程不是。 SPI guideAD9833

回答

2

當您將頻率轉換爲AD9833所需的兩個14位數字塊時,您正在頻率寄存器的D14和D15中進行或運算。那裏有兩個問題。

第一個問題是,你正在失去你的FREG值的4位(的時間爲2位)。


LL000000 00000000 LL000000 00000000 //The L's are lost because they're overwritten by the addressing. 

的第二個問題是,你需要的位15和14是完全0x40的。現在,如果數據已經根據您的頻率存在,那麼結果可能爲0xC0。

作爲未成年人注意到我認爲沒有理由分配給fByte0-3時候,因爲你使用的分配使用口罩。

因此,結合這兩種修復和簡化了口罩給:

fByte0 = (char)freg; 
fByte1 = (char)(freg>>8); 
fByte1 = (fByte1 & 0x3F) | 0x40; //clears bits 15 and 14, then sets for FREQ0 
fByte2 = (char)(freg>>14); //byte1 only has 6 bits, so move over by 8+6 
fByte3 = (char)(freg>>22); //byte1 only has 6 bits, so move over by 8+8+6 
fByte3 = (fByte3 & 0x3F) | 0x40; //clears bits 15 and 14, then sets for FREQ0 

我想,你想成爲那給你拿。

+0

非常感謝,現在我明白我做了什麼錯誤。它運作良好。 – verendra

+0

抱歉再次提問。我有一點疑問。我在開關盒中調用這個函數,所以它的工作良好,但是問題出在主函數中,當沒有來自超級終端的輸入時,我已經將頻率設置爲125kHz,但是顯示小於50KHz的問題是什麼?你可以看看我編輯的代碼。 – verendra

+0

我看到了編輯,但我不確定問題出在哪裏。你還記得在main()中設置階段嗎?我會檢查是否有其他寄存器忘記配置...否則,我對unicom()函數有點困惑。在WGF的情況下,你爲什麼總是將命令設置爲0?那應該是隻有當價值低於500? – Ross

0

的根本問題,我跟你的代碼中看到的是,它不是分層。你正試圖在一個例程中做太多的數據操作。你在另一篇文章中讀取ADC值的代碼是分層的,這就是你應該爲這個設備做的事情。

AD9833波形發生器基本上是一個16位器件。它需要編程的三種寄存器都是16位。這只是8位數據傳輸(使用SPI)。因此,只有實際的輸出語句(使用spi())需要處理字節(就像您的ADC輸入例程立即將讀取的字節轉換爲短整數一樣)。爲發生器計算的值應該是16位值。那麼你應該能夠看到代碼如何實現生成器數據表中的數據需求。

void WG_out(unsigned short rval) 
{ 
    /* assume little-endian CPU but AD9833 wants high byte first */ 
    spi(*((unsigned char *)&rval + 1)); 
    spi(*(unsigned char *)&rval); 
} 

void SetWGFreq(int fsel, unsigned int freq) 
{ 
    unsigned short freg_addr; 
    unsigned short freq_reghi; 
    unsigned short freq_reglo; 
    unsigned short cntl_reg; 

    SPCR = 0x5A;   /* set SPI to mode 2 and Fosc/64 */ 
    WG_CS = 0; 

    freg_addr = (fsel > 0) ? 0x8000 : 0x4000; 
    /* split the f value into two 14-bit values */ 
    freq *= 33554.432; /* number based on a MCLK of 8 MHz */ 
    freq_reghi = freg_addr | ((freq >> 14) & 0x00003fff); 
    freq_reglo = freg_addr | (freq & 0x00003fff); 

    cntl_reg = (1 << 13) | (fsel > 0) ? (1 << 11) : 0; 
    while (WG_CS_PIN) /* wait for chip select to go low */ 
     /* DELAY */ ; 
    WG_out(cntl_reg); /* set B28 in Control */ 
    WG_out(freq_reglo); /* 14 LSB goes first */ 
    WG_out(freq_reghi); /* 14 MSB goes next */ 
    WG_CS = 1; 
} 

void SetWGPhase(int fsel, int psel, unsigned int phase) 
{ 
    unsigned short cntl_reg; 
    unsigned short phase_reg; 

    SPCR = 0x5A; 
    WG_CS = 0; 
    cntl_reg = (1 << 13) | (fsel > 0) ? (1 << 11) : 0 | (psel > 0) ? (1 << 10) : 0; 
    phase *= 1303;  /* 4096/2pi radians */ 
    phase_reg = 0xc000 | (psel > 0) ? (1 << 13) : 0 | (phase & 0x0fff); 
    while (WG_CS_PIN) /* wait for chip select to go low */ 
     /* DELAY */ ; 
    WG_out(cntl_reg); /* set B28 in Control */ 
    WG_out(phase_reg); 
    WG_CS = 1; 
} 

該代碼允許使用FREQ0FREQ1,要麼階段0PHASE1寄存器的規格。 * WG_out()*的源代碼看起來很複雜,但實際上它編譯成非常簡單的機器代碼。

代碼改進仍然需要

  • 幻數需要與#define s內更換。

  • 而不是重寫完整的控制寄存器,需要維護一個狀態變量,以便只根據需要修改控制位。然後可以消除SetWGPhase()中的參數。

+0

非常感謝。 – verendra