目次
前
次
D/A converter
8ピンのPIC12F1501には、D/A変換器が含まれてます。
PICではD/A変換器を内蔵しているチップは少ないので
これを機会に使い方をマスターしようと考えました。
D/A変換器は、VCO(Voltage Controlled Oscillator)で
利用する、バリキャップの逆電圧を制御してみます。
D/A変換器の出力を安定させるため、OPアンプを
使った電圧フォロワを入れておきます。
D/A変換器に関する情報を、データシートから抜出して
みると、次のようになっています。
D/A変換器を使うためには、レジスタDACCON0のDACENビットを
1に設定します。さらに、D/A変換器の出力をどこにするかを
指定します。また、リファレンス電圧を電源電圧にするのか
Vref入力を使うのかをブロック図を見て指定します。
今回は、DACOUT1を使います。
D/A変換器の出力は、次の3角波とします。
D/A変換器の設定値は0から31なので、カウンタで
0から31、31から0を生成し、レジスタに書込みます。
0から31、31から0を生成するのは、タイマー割込みで
ステートマシンを動かし、ステートをインクリメントして
いきます。
ステートは0から63とし、このステート値をデコーダに
いれて、0から31、31から0を生成します。
D/A変換器の制御は、2関数に担当させます。
初期化
リファレンス電圧、D/A変換値出力を指定後、D/A変換
モジュールを使うと宣言します。
void dac_init(void)
{
/* reference Vdd */
DACCON0.DACPSS = OFF ;
/* enable DAC output #1 */
DACCON0.DACOE1 = ON ;
/* use DAC */
DACCON0.DACEN = ON ;
}
値出力
D/A変換器の設定値は0から31なので、その範囲になるよう
レンジチェックして出力します。
void dac_write(UBYTE x)
{
DACCON1 = (0x1f & x);
}
タイマー割込みを使うので、タイマー0のオーパーフロー割込み
を使います。割込みハンドラは、次のように定義します。
void interrupt(void)
{
/* generate 500Hz(2ms) */
if ( INTCON.T0IF == ON ) {
/* clear flag */
INTCON.T0IF = OFF ;
/* initialize */
TMR0 = CNTBEGIN ;
/* increment */
timcnt++ ;
/* judge */
if ( timcnt == CNTMAX ) {
/* clear */
timcnt = 0 ;
/* set flag */
eflag = ON ;
}
}
}
2ms周期で、D/A変換器の出力値を更新します。
MikroCを利用したソースコードは、以下。
typedef unsigned char UBYTE ;
typedef unsigned short UWORD ;
#define OFF 0
#define ON OFF+1
#define CNTBEGIN 6
#define CNTMAX 32
volatile UWORD timcnt ;
volatile UBYTE eflag ;
volatile UBYTE state ;
volatile UBYTE tmp ;
/* function prototype */
void init_usr(void);
void dac_write(UBYTE x);
void dac_init(void);
/* interrupt handler */
void interrupt(void)
{
/* generate 500Hz(2ms) */
if ( INTCON.T0IF == ON ) {
/* clear flag */
INTCON.T0IF = OFF ;
/* initialize */
TMR0 = CNTBEGIN ;
/* increment */
timcnt++ ;
/* judge */
if ( timcnt == CNTMAX ) {
/* clear */
timcnt = 0 ;
/* set flag */
eflag = ON ;
}
}
}
void main(void)
{
/* initialize */
init_usr() ;
/* endless loop */
while ( ON ) {
/* event handling */
if ( eflag == ON ) {
/* clear flag */
eflag = OFF ;
/* impress */
tmp = state ;
if ( state > 31 ) { tmp = 31 - state ; }
dac_write( tmp ) ;
/* increment */
state++ ;
/* judge */
if ( state & 0x40 ) {
state = 0 ;
}
}
}
}
/* define function body */
void init_usr(void)
{
/* select 4MHz */
OSCCON = (0x0d << 3) | 0x03 ;
/* disable A/D converter */
ADCON0.ADON = OFF ;
ADCON2 = 0 ;
/* initialize D/A converter */
dac_init();
/* disable compare module */
CM1CON0.C1ON = OFF ;
CM1CON0.C1OE = OFF ;
/* I/O state */
LATA = 0 ;
/* I/O directions */
TRISA = 0xf8 ; /* bit0,1,2 as output , others as input */
/* pull-up */
WPUA = 0x30 ;
/* initialize Timer 0 */
{
/*
4MHz/4 = 1MHz -> 1MHz/8 = 125kHz prescaler = 1:8
*/
OPTION_REG = 0x02 ;
/* 256 - 6 = 250 */
TMR0 = CNTBEGIN ;
/* enable timer0 overflow interrupt */
INTCON.TMR0IE = ON ;
}
/* enable general interrupt */
INTCON.GIE = ON ;
/* clear flag */
eflag = OFF ;
/* initialize variables */
timcnt = 0 ;
state = 0 ;
}
void dac_write(UBYTE x)
{
DACCON1 = (0x1f & x);
}
void dac_init(void)
{
/* reference Vdd */
DACCON0.DACPSS = OFF ;
/* enable DAC output #1 */
DACCON0.DACOE1 = ON ;
/* use DAC */
DACCON0.DACEN = ON ;
}
D/A変換器の出力には、OPアンプによるバッファを入れるよう
データシートに記載があるので、次の回路をバッファで入れ
ます。
テストに利用した基板は、以下。
目次
前
次