-1

最初に 125 kHz で正弦波を生成する際に小さな問題があります。これは非常に単純に思えますが、私には多くの時間がかかりましたが、何が問題なのかわかりませんでした。CodeVisionAVR コンパイラを使用しています。

ATmega32-A マイクロ コントローラー、AD9833 プログラマブル波形発生器を使用して正弦波を生成しています。以下のコードを書きました。

#include <MEGA32.h>
#include <main.h>
#include <interface.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <delay.h>
#include <sleep.h>

 // GLOBAL VARIABLES
 unsigned int i;

 //Status
 unsigned char state = 0;
 unsigned char debug = 0;
 unsigned int status = 0x0010;

 //External variables
 unsigned char Command;
 unsigned int  Param;
 extern unsigned char rx_counter0; 


 //Initialize registers
 void init(void){

    #asm("cli");        //Disable global interrupt

    // Input/Output Ports initialization
    // Port B initialization 
    PORTB=0x00;
    DDRB=0xBF;

    // Port C initialization
    PORTC=0x00;
    DDRC=0xC3;

    // Port D initialization
    PORTD=0x00;
    DDRD=0xFC;

    // USART initialization
    // Communication Parameters: 8 Data, 1 Stop, No Parity
    // USART Receiver: On
    // USART Transmitter: On
    // USART0 Mode: Asynchronous
    // USART Baud Rate: 9600
    UCSRC=0x86;
    UBRRH=0x00;
    UBRRL=0x67;
    UCSRA=0x00;
    UCSRB=0xD8;
   //UCSRC=0x86;

   // SPI initialisation
   // SPI clock rate fck/16
   // SPI master
   // SPI MSB first
   // SPI CPOL = 1, CPHA = 1
   SPCR=0x5D;
   //PORTB.1 = 1;    //Flash CS high
   PORTB.3 = 1;    //ADC CS high

  //Global enable interrupts
  #asm("sei")
 }

 void runCom(void){

         switch(Command){

                        case(NO_COM):
                            Command = 0;
                            break;

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

                        case(PHASE):
                            if(Param < 4095)
                                SetWGPhase(Param);
                            Command = 0;
                            break;          
                        default:
                            Command = 0;
                            break;   
                    }
             }

  void main(void){
        status = 0x0010;
        init();                                     //Initialize controller

        SetWGFreq(125);     //Initialize waveformgenerator 125 kH     

        debug = 0;              //Controls output during motor running      
   while (1){

         if(rx_counter0) getCom();                     
         if(Command)     runCom();

          }
       }
   }
   #asm("WDR");        //Reset WD timer 
 }  // EOF "while(1)"
} // EOF "main(void)"


unsigned char spi(unsigned char data) 
{ 
//Start transmision 
SPDR = data; 
//Wait for transmision complete 
while (!(SPSR & 0x80)); 
return SPDR; 
}        



//Sets the waveform generator output to given kHz
void SetWGFreq(unsigned int freq)
{
unsigned long freg;
char fByte0;
char fByte1;
char fByte2;
char fByte3;

freg = (unsigned long)freq*33554.432;   //Number based on a MCLK of 8 MHz
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

SPCR = 0x5A;        //Set SPI to mode 2 and Fosc/64
WG_CS = 0;
while(WG_CS_PIN);   //Wait for chip select pin to go low
spi(0x20);          //Load control register with B28 high
spi(0x00);
spi(fByte1);
spi(fByte0);
spi(fByte3);
spi(fByte2);
WG_CS = 1;
}

ATmega32-A と AD9833 の間で SPI 通信を使用しています。信号の周波数を設定する関数と、信号の位相を変更する関数をもう 1 つ作成しました。

「FREQ」と入力した周波数値を入力すると、スイッチケースにコマンドを書きました。「PHASE」と同じように、入力した周波数で信号を生成します。信号の位相を変更できます。したがって、コマンドを使用して信号の周波数と位相を正常に設定できます。

今私の問題は、

コードを実行するときに、波形発生器を 125 kHz に初期化したいです。電源のオフ/オン時でも 125KHz である必要があります。ユーザーが周波数を 125 から他の値に変更したい場合は、「FREQ」機能を使用する必要があります。
そのために、while ループに入る前に、メイン プログラムで「 SetWGFreq」関数を呼び出しました。

SetWGFreq(125); //波形発生器を初期化 125 kH

なぜ機能しなかったのかわかりません。

ただし、この関数を while ループに配置すると機能しますが (最初は 125KHz で信号が生成されます)、「FREQ」は機能しません。その後、「FREQ」機能を使用して信号の周波数を変更したい場合、機能していませんでした。

これで私を助けてください、私がしている間違いが何であったかわかりませんでした。

4

1 に答える 1

0

これを見ると、問題は SetWGFreq() の呼び出しが機能しないことではないと思います。問題は、初めて機能しないことです。

関数呼び出しは CS ピンを Low に駆動し、コマンド WG_CS = 0 の終了時に High に戻します。... WG_CS = 1;

しかし、最初の時点では、WG_CS はおそらく既に 0 でした。最初の呼び出しは、既存の不完全な SPI 状態をフラッシュするためだけに機能しています。

SetWGFreq() への 2 番目の呼び出しを追加するだけで、すばやくテストできます。それが解決する場合は、解決策を知っています。

一般に、初期化中に電源投入時のガベージをフラッシュする何かが必要です。少なくとも CS サイクルは SPI 状態をクリアする必要があります。ステータスコマンドを送信するか、リセットして既知の状態を確立することをお勧めします

おそらくこれで解決しましたが、何が問題でしたか?

于 2012-12-31T10:56:15.427 に答える