MPLABX XC8でPIC16F88のアナログポート(A/Dコンバータ)を使うテストをします。
使い方は、「PICで遊ぶ電子工作」というサイトのこちらのページがたいへん参考になりました。
PIC16F88では、RA0~RA4とRB6,RB7をアナログポートとして使うことができます。
A/Dコンバータは、10bitで、アナログ値(電圧)を0~1023の数値で読み込むことができます。
今回は、RA0(AN0)を使い、ボリュームからの電圧を数値で読み取ってみます。数値はシリアル通信でTeraTermで表示します。
回路図です。
Image may be NSFW.
Clik here to view.
Clik here to view.

ブレッドボードです。
Image may be NSFW.
Clik here to view.
Clik here to view.

プログラムです。
まず、A/Dコンバータを使うための次のように初期設定をします。
TRISAレジスタで、RA0(AN0)を入力に設定します。
ANSELレジスタで、RA0(AN0)をアナログポートに設定します。
ADCON0,ADCON1,ADCON2レジスタで、A/D変換クロックの設定、基準電圧の設定、A/D変換結果の格納方法、A/D変換有効の設定をします。
今回は、内臓クロック8MHzを使いますので、A/D変換クロック1.6us~6.4usの範囲で計算すると16Toscで 2.0us
になります。
基準電圧はVdd=5Vとします。
格納方法は、右詰めとします。
A/D変換の方法はつぎのようにします。
A/D変換対象ポートの設定
A/D変換の準備完了を待ちます。(50us待ちます)
A/D変換開始
A/D変換完了を待ちます。
A/D変換結果を読み取ります。
シリアル通信のヘッダファイルserial.hとソースファイルserial.cは、シリアル通信テストと同じものを使います。
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include "serial.h"
#include <stdlib.h>
#include <xc.h>
#include "serial.h"
/* PIC16F88におけるA/D変換テスト
* pin17 AN0を使う
* Vrefは、Vdd=5V
*/
* pin17 AN0を使う
* Vrefは、Vdd=5V
*/
// CONFIG1
#pragma config FOSC = INTOSCIO //内臓発振器を使う
#pragma config WDTE = OFF
#pragma config PWRTE = ON
#pragma config MCLRE = OFF
#pragma config BOREN = OFF
#pragma config LVP = OFF
#pragma config CPD = OFF
#pragma config WRT = OFF
#pragma config CCPMX = RB0
#pragma config CP = OFF
#pragma config FOSC = INTOSCIO //内臓発振器を使う
#pragma config WDTE = OFF
#pragma config PWRTE = ON
#pragma config MCLRE = OFF
#pragma config BOREN = OFF
#pragma config LVP = OFF
#pragma config CPD = OFF
#pragma config WRT = OFF
#pragma config CCPMX = RB0
#pragma config CP = OFF
// CONFIG2
#pragma config FCMEN = OFF
#pragma config IESO = OFF
#pragma config FCMEN = OFF
#pragma config IESO = OFF
#define _XTAL_FREQ 8000000
void main() {
OSCCON = 0b01110000;//内部クロック8MHz
/* A/D変換設定 */
TRISA = 0b00100001; //RA0,RA5はinput 他はoutput
ANSEL = 0b00000001; //AN0を使う。他はデジタルポート
TRISB = 0b11001000; //RB3はinput 他はoutput
/* A/D変換クロックの設定 クロック8MHz 16Tosc 2.0us */
ADCON1bits.ADCS2 = 1;
ADCON0bits.ADCS1 = 0;
ADCON0bits.ADCS0 = 1;
/* 基準電圧の設定 Vref+ = Vdd,Vref- = Vss */
ADCON1bits.VCFG1 = 0;
ADCON1bits.VCFG0 = 0;
/* A/D変換結果の格納方法の設定 */
ADCON1bits.ADFM = 1;//右詰め
/* A/D変換を有効にする */
ADCON0bits.ADON = 1;
/* A/D変換対称ボートの選択 AN0を選択*/
ADCON0bits.CHS2 = 0;
ADCON0bits.CHS1 = 0;
ADCON0bits.CHS0 = 0;
PORTA = 0x00; //PORTA初期化
PORTB = 0x00; //PORTB初期化
serial_init(); //シリアル通信初期化
while(1){
/* A/D変換 */
__delay_us(50); //50us待つ
ADCON0bits.GO_nDONE = 1; //A/D変換開始
while(ADCON0bits.GO_nDONE); // A/D変換終了まで待つ
/* A/D変換結果を読み取る */
unsigned int val = ADRESH;
val = (val<<8)+ADRESL;
printf("%d\r\n",val);
__delay_ms(500);
}
}
OSCCON = 0b01110000;//内部クロック8MHz
/* A/D変換設定 */
TRISA = 0b00100001; //RA0,RA5はinput 他はoutput
ANSEL = 0b00000001; //AN0を使う。他はデジタルポート
TRISB = 0b11001000; //RB3はinput 他はoutput
/* A/D変換クロックの設定 クロック8MHz 16Tosc 2.0us */
ADCON1bits.ADCS2 = 1;
ADCON0bits.ADCS1 = 0;
ADCON0bits.ADCS0 = 1;
/* 基準電圧の設定 Vref+ = Vdd,Vref- = Vss */
ADCON1bits.VCFG1 = 0;
ADCON1bits.VCFG0 = 0;
/* A/D変換結果の格納方法の設定 */
ADCON1bits.ADFM = 1;//右詰め
/* A/D変換を有効にする */
ADCON0bits.ADON = 1;
/* A/D変換対称ボートの選択 AN0を選択*/
ADCON0bits.CHS2 = 0;
ADCON0bits.CHS1 = 0;
ADCON0bits.CHS0 = 0;
PORTA = 0x00; //PORTA初期化
PORTB = 0x00; //PORTB初期化
serial_init(); //シリアル通信初期化
while(1){
/* A/D変換 */
__delay_us(50); //50us待つ
ADCON0bits.GO_nDONE = 1; //A/D変換開始
while(ADCON0bits.GO_nDONE); // A/D変換終了まで待つ
/* A/D変換結果を読み取る */
unsigned int val = ADRESH;
val = (val<<8)+ADRESL;
printf("%d\r\n",val);
__delay_ms(500);
}
}
ボリュームを回して、0~5Vの電圧を数値で読みとっています。0~1023の数値で読み取れます。
Image may be NSFW.
Clik here to view.![イメージ 3]()
Clik here to view.
Image may be NSFW.
Clik here to view.![イメージ 4]()
Clik here to view.
数値に±1ビット程度のゆらぎがあります。外来ノイズによるものと思われます。