PICの内蔵DAC機能を動作させて見る
〔マイコン使用による電子部品の使い方に戻る〕
前の記事でマイコンによるPWMの話とDAC専用ICのMCP4922を使用した記事を書きました。
なのでPWM? DAC?と言う人はまずそちらの記事を一読して下さい。
マイコンでのアナログ出力は大体PWM出力ですが、最近のPICにはDAC(Digital-to-Analog Converter)
モジュールを内蔵している物が有り、アナログ電圧を出力可能となっています。
DACモジュールの出力は、外部ピン出力の他にコンパレータの正入力やADCの入力チャンネルにも
使用されます。
また、DACは入力電圧を32レベルの電圧レンジに切り替えて出力されます。
(16F1705は256レベルの電圧レンジとなります)
DACのレジスタ等の操作は、どのPICでもほとんど同じ様に操作できますが、
若干PICにより機能が有ったり無かったりします、その内容を下記一覧で纏めて見ました。
(一覧のPIC種類は私の手元に有る物だけですがぁ......)
|
正ソース電圧源 |
負ソース電圧源 |
出力 |
低電力電圧ステート |
VDD |
VREF+ |
FVR |
VSS |
VREF- |
DACOUT |
DACLPS |
12F1501 |
○ |
○ |
|
○ |
|
2個 |
|
12F1822 |
○ |
○ |
○ |
○ |
|
1個 |
○ |
16F1705 |
○ |
○ |
○ |
○ |
○ |
2個 |
|
16F1827 |
○ |
○ |
○ |
○ |
○ |
1個 |
○ |
16F18313 |
○ |
○ |
○ |
○ |
○ |
1個 |
|
16F1938 |
○ |
○ |
○ |
○ |
○ |
1個 |
|
18F25K22 |
○ |
○ |
○ |
○ |
○ |
1個 |
○ |
2個出力はDACOUT1とDACOUT2の2ピンから出力が出来ますが、同じ電圧値が出力されるだけです。
FVRとは
DACは出力電圧を32レベルで出力できますが、固定参照電圧(FVR)は出力レベルが
1.024V/2.048V/4.096V から選択でき、ADCの入力、コンパレータの正入力、DAC入力、
CPSモジュールの基準電圧として供給されます、尚、FVRは外部出力不可です。
《12F1822のDACピン構成》
DACの出力するピンは、DACOUTで7番(RA0)ピンを使用します。
正ソース電圧源の6番(RA1)ピン VREF+ は今回使用せず、正ソースはVDDとします。
また、負ソースはVSSです。
尚、PICの1番ピンに電源+5V、8番ピンに電源GND(-)を接続しています。
《サンプルプログラム》
DACOUTの7番(RA0)ピンから約2Vを出力するのみのプログラムです。
尚、PICのシステムクロック(Fosc)は内蔵8MHzで行っています。
@MPLAB X(v2.15)を起動させます。 *2)
A下記がプログラムソースです、
MPLAB(R) XC8 C Compiler Version 1.32コンパイラを使用しています。 *2)
プロジェクトを作成して新規ファイルにコピーペーストして貼り付けて下さい。
BコンパイルとPIC書き込みを実行して下さい。 *2)
---------------------------------------------------------------------
#include <xc.h>
// コンフィギュレーション1の設定
#pragma config FOSC = INTOSC // 内部クロック使用する(INTOSC)
#pragma config WDTE = OFF // ウオッチドッグタイマー無し(OFF)
#pragma config PWRTE = ON // 電源ONから64ms後にプログラムを開始する(ON)
#pragma config MCLRE = OFF // 外部リセット信号は使用せずにデジタル入力(RA3)ピンとする(OFF)
#pragma config CP = OFF // プログラムメモリーを保護しない(OFF)
#pragma config CPD = OFF // データメモリーを保護しない(OFF)
#pragma config BOREN = ON // 電源電圧降下常時監視機能ON(ON)
#pragma config CLKOUTEN = OFF // CLKOUTピンをRA4ピンで使用する(OFF)
#pragma config IESO = OFF // 外部・内部クロックの切替えでの起動はなし(OFF)
#pragma config FCMEN = OFF // 外部クロック監視しない(OFF)
// コンフィギュレーション2の設定
#pragma config WRT = OFF // Flashメモリーを保護しない(OFF)
#pragma config PLLEN = OFF // 動作クロックを32MHzでは動作させない(OFF)
#pragma config STVREN = ON // スタックがオーバフローやアンダーフローしたらリセットをする(ON)
#pragma config BORV = HI // 電源電圧降下常時監視電圧(2.5V)設定(HI)
#pragma config LVP = OFF // 低電圧プログラミング機能使用しない(OFF)
// メインの処理
void main()
{
OSCCON = 0b01110010 ; // 内部クロックは8MHzとする
ANSELA = 0b00000000 ; // アナログは使用しない(すべてデジタルI/Oに割当てる)
TRISA = 0b00000000 ; // ピンは全て出力に割当てる(RA3は入力専用)
PORTA = 0b00000000 ; // 出力ピンの初期化(全てLOWにする)
// DACの設定(約2.0VをRA0から出力する)
DACCON0 = 0b11100000 ; // VDD/VSSを使用、DACOUTピン(RA0)出力する
DACCON1 = 13 ; // 約2.0Vを出力( 5V*(13/2^5)=2.03125 )
while(1) {
}
}
---------------------------------------------------------------------
実行結果
このプログラム自体は設定のみなので、LED表示などの外部出力はないので何も変化は
無いですが、DACOUT(RA0)からは約2.0Vの電圧が出力されています。
尚、テスターで電圧を計測したら VDD=5.02V DACOUT=2.042V でした。
DAC参照電圧出力
データシートに、”DACOUT を外部接続する場合、電流駆動能力が限られているため、下記図の様に
DAC 参照電圧出力にバッファを使う必要があります”、と書いて有ります。
16F1705にはオペアンプを2個内蔵しているのでバッファとして使用出来ます。
その辺の記事は、セッピーナさんの「PIC/16F1705のオペアンプをDACのバッファとして使ってみた」を
参照下さい。
レジスタの設定
18F25K22は、DACCON0がVREFCON1へ、DACCON1がVREFCON2にレジスタ名が変わります。
が、コンパイルはDACCON0/DACCON1でも通る様です。
12F1501の時DACOUT1/DACOUT2と2個出力が有るので、
DACCON0のDACCOE1(bit5)・DACCOE2(bit4)とそれぞれに割り当てられています。
16F1705の時DAC1OUT1/DAC1OUT2と2個出力が有るので、
DAC1CON0のDAC1COE1(bit5)・DAC1COE2(bit4)とそれぞれに割り当てられています。
尚、DACCON0がDAC1CON0へ、DACCON1がDAC1CON1にレジスタ名が変わります。
DACCON0の構成
ビット |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
機能 |
DACEN |
DACLPS |
DACOE |
|
DACPSS |
|
DACNSS |
Bit 7:DACEN DACモジュールの有効無効指定ビット
1:モジュールを使用する
0:モジュールを使用しない
Bit 6:DACLPS DAC低電力電圧ステート選択ビット(PICによってはこのビットは有りません)
1:低電力状態時に+側のソース電圧を選択し、−側は切る
0:低電力状態時に−側のソース電圧を選択し、+側は切る
Bit 5:DACOE DAC電圧をピンに出力するのかを指定するビット
1:DAC電圧レベルをDACOUT ピンにも出力する
0:DAC電圧レベルをDACOUT ピンから切り離す
Bit 2-3:DACPSS +側のソース電圧選択ビット(VSOURCE+)
00:PIC接続の+電源(VDD)を選択する
01:VREF+ ピン
10:PIC内蔵の固定電圧 FVR(1.024V/2.048V/4.096V)を選択する
11:予約済み(使用不可)
Bit 0:DACNSS −側のソース電圧選択ビット(VSOURCE-)(12F1822にはこのビットは有りません)
0:PIC接続のGND(VSS)を選択する
1:VREF- ピン
※ 16F18313ではbit名称がDAC1となります、即ち"DACEN"なら"DAC1EN"と言った感じです。
但し、レジスタ名称は同じです。
DACCON1の構成
このレジスタで32レベル(5ビット)の電圧レンジに切り替えます、なので0〜31を設定する。
出力する電圧の計算は、
出力電圧 = ((VSOURCE+) - (VSOURCE-))*(DACCON1/(2^5)) + VSOURCE-
VSOURCE+ = 5V VSOURCE- = 0V DACCON1 = 13 ならば 5V*(13/2^5)=2.03125V
16F1705では、
このレジスタで256レベル(8ビット)の電圧レンジに切り替えます、なので0〜255を設定する。
出力する電圧の計算は、
出力電圧 = ((VSOURCE+) - (VSOURCE-))*(DACCON1/(2^8)) + VSOURCE-
VSOURCE+ = 5V VSOURCE- = 0V DACCON1 = 13 ならば 5V*(13/2^8)=0.25390V
おまけ
同じ電圧の一直線波形では面白くないので下記の様にプログラムを追加すると、
---------------------------------------------------------------------
#define _XTAL_FREQ 8000000 // delay用に必要(この行は#include行の下にでも入れる)
while(1) {
for (int i=0 ; i < 32 ; i++) {
DACCON1 = i ;
__delay_us(10) ;
}
}
}
---------------------------------------------------------------------
と、この様にのこぎり波形になっちゃいま〜す。
でもぉ、32レベルの電圧切り替えしかないので本当に
ギザギザのノコギリですけどね。
16F18313の記事追記(*3) 2016/11/22
MPLAB X用に記事変更(*2) 2015/10/30
16F1705の記事追記(*1) 2014/12/01
【きむ茶工房ガレージハウス】
Copyright (C) 2006-2016 Shigehiro Kimura All Rights Reserved.