PIC 10F322によるVCO

投稿日 2013/05/07

6ピン 超小型PIC(実験で用いたのは8ピンDIP) 10F322でVCOの実験を行いました。
これは、マイクロチップ社のアプリケーションノート TB3071(NCOを使用したVCO)の再現実験です。ただし、開発ボードAC103011は使用せずに、独自に実装しています。回路はほとんど同じです。

PIC_10F322_4.jpg
PIC_10F322_3.jpg

回路図


JPはAC103011と同じになるようにSWがMCLR、VRがRA2につながるように配線します。


 

10F322にはCPUコアとは独立に動作する周辺機能である、CLC、CWG/COG、NCO、HRPWMが搭載されています。

 

アプリケーションノートTB3071は、NCOとCLC、ADコンバータの使用例となっています。

 

NCO(Numerically Controlled Oscillator)は16bit分解能の数値制御の矩形波オシレータです。

 

CLC(Configrable Logic Cell))はある範囲内で自由にロジックが組めるもので、用途は限定されていません。

 

NCOもCLCも、クロックさえ動いていればCPUとは独立に動作可能です。

 

ADコンバータは8nitで、4chあります。

 

ADコンバータから入力した電圧値によってNCOの周波数を制御するとVCO(Voltage Controlled Oscillator)となります。

 

アプリケーションノートTB3071に記載のサンプルプログラムは、開発ボードAC103011をベースにしているため、そのピン配置の都合でCLCを使用していますが、目的はNCOの出力ピンの変換だけで、とくに機能的な用途に使っているわけではありません。RA2がNCOの本来の出力ピンですが、AC103011はボリュームのADコンバータのピンとなっているので、NCOの出力をCLCを使ってRA1に変換しているだけです。それでもCLCをどのように設定するかの勉強にはなります。

 

CLCの設定は少しややっこしいので、コンフィグレーション・ツールが提供されています。windowsで動くプログラムです。

 

NCOは16bit分解能ですが、10F322のADコンバータは8bitですので最高500KHzまでを256ステップで周波数可変することになります。可変ステップは約1.953KHzとなります。

 

最低周波数約7.6Hzと最高周波数約500KHzの出力波形を見てみました。

PIC_10F322_5.gif

スイープ画像

 

このようにNCOを使えば簡単に可変周波数発信器が作れます。


 

ソースコード(スイーパー)
mian.c
#include <pic.h>

 

__CONFIG (FOSC_INTOSC & BOREN_OFF & WDTE_OFF & PWRTE_OFF & MCLRE_OFF & CP_OFF & WRT_OFF & LVP_OFF);

 

#define LED_RED PORTA1

 

unsigned int TimerCount;
unsigned int inc_val;

 

//Timer0 Interrupt handller
void interrupt Timer0_ISR(void)
{
if(TMR0IF && TMR0IE)
{

TMR0IF = 0;
TimerCount++;

}
}

 

//mS delayer
void Delay_ms(unsigned int delay)
{

TimerCount = 0;
TMR0 = 0;               // x256
OPTION_REGbits.PS = 0x3;    // x16 -> Fosc/4(0.25uS) x 256 x 16 = 1.024ms
OPTION_REGbits.T0CS = 0;
OPTION_REGbits.PSA = 0;

GIE = 1;             //Interrupt Enable
TMR0IE = 1;           //Timer0 Enable

while(TimerCount < delay){};

TMR0IE = 0;           //Timer0 Disable

}

 

void main(void)
{
OSCCON = 0x70; // Fosc = 16 MHz(T=63nS)
LATA1 = 0;
TRISA = 0;

N1CKS1 = 0; //Clock source is Fosc
N1CKS0 = 1;
N1OE = 1;            //NCO1 Output Enable
N1EN = 1;            //NCO1 Enable

while(1)
{
for(inc_val = 0; inc_val < 65535; inc_val++)
{
if(inc_val == 0)
{

NCO1INCH = 0;
NCO1INCL = 1;

}
else
{

NCO1INCH = inc_val;
NCO1INCL = 0;

}
Delay_ms(30); //adjust sweep speed
}
}
}


 

(JF1VRR)