PWMを使用した正弦信号生成


16

MC68HC908GP32マイクロコントローラーを使用してサイン信号を適切に生成することはできません。PWMの説明は349ページから始まります。クロック周波数は2.4MHzですが、プリスケーラを使用し、タイマーを次のようにモジュロを350に設定して7 kHz PWMを使用しました。

T1SC = 0x60;    // Prescaler: Div entre 64
//Counter modulo = 0x015E = 350
T1MODH = 0x01;   // High
T1MODL = 0x5E;   // Low

PWM出力は、次のRLCフィルターによってフィルターされ、その後、1uFの直列コンデンサを使用してDCが除去されます。カットオフ周波数は、PWMの7kHzをかなり下回っています。

ここに画像の説明を入力してください

まず、このサイトを使用して生成されたサンプル(100サンプル、振幅= 250)を使用してみました。これは単一の期間で構成されます。

 int seno[100]={ 125, 133, 141, 148, 156, 164, 171, 178, 185, 192, 198, 205, 211, 216, 221, 226, 231, 235, 238, 241, 244, 246, 248, 249, 250, 250, 250, 249, 248, 246, 244, 241, 238, 235, 231, 226, 221, 216, 211, 205, 198, 192, 185, 178, 171, 164, 156, 148, 141, 133, 125, 117, 109, 102, 94, 86, 79, 72, 65, 58, 52, 45, 39, 34, 29, 24, 19, 15, 12, 9, 6, 4, 2, 1, 0, 0, 0, 1, 2, 4, 6, 9, 12, 15, 19, 24, 29, 34, 39, 45, 52, 58, 65, 72, 79, 86, 94, 102, 109, 117}; 

次のパルスの幅は、PWMサイクルごとに計算されます。

interrupt 4 void rsi_t1ch0 (void)
{
    //-- disable interruption flag
    T1SC0&=(~0x80);
    //-- pwm to '0' 
    PTB&=0xFD;

    //some sensor measures are done here.... 100 out of the 350 cycles are left for this                
}
/************************************************************/
/* TIM1 overflow rutine                                     */
/************************************************************/
interrupt 6 void rsi_ov1 (void)
{

    T1SC&=(~0x80);
    //-- set PWM to 1
    PTB|=0x02;
    T1CH0H = ((seno[fase])>>8);   // high bits
    T1CH0L = (seno[fase])&0xFF;   // low bits
    fase+=1;
    if (fase >= 99)
      fase=0;
}

void main(void)
{
float temp;
    int i;

    CONFIG1|=0x01;  
    DDRB=0xFF;      //-- Port B is set as output
    PTB=0x00;       
    //Timer setup
    T1SC = 0x60;    // Prescaler: Div by 64  
    T1MODH = 0x01;   //Counter modulo
    T1MODL = 0x5E;  
    T1SC0 = 0x50;  //Comparator setup
    //-- Initial width
    T1CH0H = 0x00;
    T1CH0L = 0x53;

    EnableInterrupts;
    T1SC&=~(0x20); //Run timer forever
    for(;;);   
}

スコープにプラグインすると、次のシグナルを受け取ります。最小値に近いその奇妙なピークを避けることはできません。

ここに画像の説明を入力してください

そのピークをズームすると、PWM出力(上)が実際に正しくないことがわかります。

ここに画像の説明を入力してください

そのため、しばらくいじってそれを取り除くことができなかった後、各サンプルの値をハードコーディングする代わりに、MCUでサイン信号を計算しようとしました。すべてのカウンター設定の直前に、メイン関数に次のコードを追加しました。

 for(i=0;i<99;i++) {
     temp=100*(sin(2*3.14159*i/100)+1);
     seno[i]=(int)temp;
 }

しかし、結果は正弦波のようには見えません。

ここに画像の説明を入力してください

何時間も苦労した後、私たちは間違いを見つけることができませんでした。アドバイスをいただければ幸いです。


PWM値のリスト全体を投稿できますか?
pjc50

@ pjc50ここにある:pastebin.com/sNyA0Hki。どうもありがとうございました。
サージ

中央のすべての「0」値を「1」に置き換えてみてください。0は、希望する低信号ではなく、その高信号を与えると思われます。
pjc50

@Serge-データをインライン化してください。ペーストは消える可能性があり、質問の一部を失うのは悪いことです。ただし、それほど多くのスペースを使用しないようにフォーマットしてください。ありがとう。
トリグヴェLaugstøl

それは明らかにフィルタではありません-幸運-あなたのテーブルが壊れているか、それへのポインタを失っているように見えます。
アンディ別名

回答:


16

マイクロコントローラデータシートのページ350の下部では、オーバーフロー割り込み中にタイマー値レジスタに小さな値を書き込むと、次のpwmの繰り返しでのみ次の割り込みがトリガーされる可能性があると記載されています。割り込みルーチンが実行されています。

パルス幅の値を変更するためのTIMチャネルレジスタへの非同期書き込みは、最大2つのPWM周期で誤動作を引き起こす可能性があります。たとえば、カウンターが古い値に達する前に新しい値を書き込むが、カウンターが新しい値に達すると、そのPWM期間中の比較ができなくなります。また、TIMオーバーフロー割り込みルーチンを使用して、新しいより小さなパルス幅値を書き込むと、比較が失敗する場合があります。TIMは、書き込まれる前に新しい値を渡す場合があります。

これは、pwm値が1つのpwmクロック期間全体+タイマーの長さ(周囲の長さに基づく)のように見える間、高く保持されるという事実によって確認されます。タイマーの長さレジスタに書き込まれている値は、エラー時におそらく0に近いため、カウンターが割り込み中に小さい値を渡し、次のサイクルでのみトリガーされる可能性が非常に高くなります。

これは、正弦波の最小レベルをISRの実行にかかる時間よりも高いレベルに上げるか、新しいレベルを設定するメカニズムを変更することで修正できます。ページ351の上部に、これを行う方法の詳細があります。


1
データシートを読むときにどうすればスキップできるかわかりません。ありがとうございました!
サージ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.