PIC12F1822の基本動作から応用プログラムまでを学びます。

ホーム
16F18313
16F18325
16F18346
16F1619
Curiosity
---
---
    
12F1822
16F1455
16F1459
18F14K50
18F26J50
dsPIC
その他
PIC12F1822のAD変換

12F1822 には、10ビットのADコンバータ(ADC)が組み込まれています。 4チャンネルの外部入力、IC内部の温度センサ、基準電圧(FVR)、DAコンバータ出力の計7チャンネルを切り替えてAD変換することができます。

AD変換チャンネル AN0 AN1 AN2 AN3
I/O Port RA0 RA1 RA2 RA4
Pin 番号 7 6 5 3
AD変換手順
  1. 使用するアナログ入力ピンの設定:
    • 該当するTRIS レジスタのビットを入力「1」に設定
    • 該当するANSEL レジスタのビットを「1」に設定
  2. ADC moduleの設定:
    • AD変換クロックを指定
    • 基準電圧を指定
    • ADC 入力チャネルを指定
    • 結果出力のフォーマットを指定
    • チャージ時間の指定
    • ADC moduleをON
  3. 必要とするチャージ時間を待つ
  4. GO/DONE bitをセットして変換を開始
  5. 変換の終了を以下の方法で待つ:
    • GO/DONE bitを常時監視
    • ADC からのinterrupt を待つ(interrupts使用時)
    • AD変換の結果を取得
    • ADC interrupt flagをクリア (interrupts使用時)
  6. AD変換の結果を取得

充電時間(Acquisition time)

AD変換は、CHS信号により入力電圧を選び、その電圧をモジュール内のコンデンサに充電したのちに開始されます。この充電時間(Acquisition time)を十分にとらないと正確な変換ができません。必要時間は、Vddと入力信号のインピーダンス(Rs)で決まります。
Vdd = 5v、Rs = 10KΩの場合、Acquisition time > 7.37uS の時間が必要です。

レジスタ bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
TRISA - - - TRISA4 TRISA3 TRISA2 TRISA1 TRISA0
ANSELA - - - ANSA4 - ANSA2 ANSA1 ANSA0
INTCON GIE PEIE TMR0IE INTE IOCIE TMR0IF INTF IOCIF
PIE1 TMR1GIE ADIE RCIE TXIE SSP1IE SSP1IE TMR2IE TMR1IE
PIR1 TMR1GIF ADIF RCIF TXIF SSP1IF SSP1IF TMR2IF TMR1IF
ADCON0 - CHS<4:0> GO/DONE ADON
ADCON1 ADFM AADCS<2:0> - - ADPREF<1:0>
FVRCON FVREN FVRRDY TSEN TSRNG CDAFVR<1:0> ADFVR<1:0>
ADRESH A/D Result Register High
ADRESL A/D Result Register Low
レジスタ BIT 内容 1 0
INTCON 7 GIE 全インタラプトの使用許可 許可
6 PEIE 周辺機能インタラプトの使用許可 許可
PIE1 6 ADIE AD変換のインタラプト許可 許可
PIR1 6 ADIF AD変換完了フラグ 完了 未完
ADCON0 6 CHS4 アナログ入力チャネルの指定: (規定値 0000)
00000=AN0,  
00001=AN1,  11101=TMP
00010=AN2,  11110=DAC
00011=AN3,  11111=FVR
1 0
5 CHS3 1 0
4 CHS2 1 0
3 CHS1 1 0
2 CHS0 1 0
1 GO/DONE 変換開始/終了 開始 終了
0 ADON ADモジュール On/Off ON OFF0
ADCON1 7 ADFM 変換結果の出力フォーマット 右詰 左詰
6 ADCS2 AD変換クロック指定: リセット直後は、<000>
000 =Fosc/2, 010 =Fosc/32, 101 =Fosc/16, 011 =FRC
001 =Fosc/8, 100 =Fosc/4, 110 =Fosc/64, 111 =FRC
1 0
5 ADCS1 1 0
4 ADCS0 1 0
1 ADPREF1 基準電圧指定: リセット直後は、<00>
00=Vdd, 10=外部Pin, 11=内部基準電圧(FVR)
1 0
0 ADPREF0 1 0
FVRCON 7 FVREN FVR制御 動作 無効
6 FVRRDY (Read Only) FVR状況 常時「1」 使用可 不可
1 ADFVR1 ADC用バッファ出力倍率
11 : x4(4.096V), 10 : x2(2.048v), 01 : x1(1.024v), 00 : OFF(初期値)
0 ADFVR0
FoscとAD変換クロック(TAD)の関連
変換クロック Fosc
ソース ADCS 1M 4M 16M 32M
Fosc/2 000 2.0 uS 500 nS 125 nS 63 nS
Fosc/4 100 4.0 uS 1.0 uS 250 nS 125 nS
Fosc/8 001 8.0 uS 2.0 uS 500 nS 250 nS
Fosc/16 101 16.0 uS 4.0 uS 1.0 uS 0.5 uS
Fosc/32 010 32.0 uS 8.0 uS 2.0 uS 1.0 uS
Fosc/64 110 64.0 uS 16.0 uS 4.0 uS 2.0 uS
FRC x11 1.0-6.0 uS 1.0-6.0 uS 1.0-6.0 uS 1.0-6.0 uS
  • FRCの中心値は、1.6uS
  • Foscが1MHzより遅い場合や、
    Sleep中は、FRCを使用する。
  • 枠内が赤いTADは、動作保障外

A/D変換のプログラム例

PortA - RA4 (AN3) に続されたボリュームで分圧された電圧をAD変換し、その値をシリアル送信するプログラムです。 得られた10ビットの値は10進数に変換しシリアル送信しています。 下の写真は、左のPICでAD変換し、左のシリアル信号LCD表示器に表示しています。

<回路図>

<プログラム>

/*********************************************************************
//  AD変換した値をUARTでデータ送信する。
//
//         4MHz (内部クロック)
//
 *      1 VDD         8 VSS
 *      2 RA5         7 RA0 TX
 *   IN 3 RA4         6 RA1
 *      4 MCLR        5 RA2
 *
 * PIC12F1822  MPLAB X IDE with XC8 Ver1.32
 * Copyright (c) 2012 iwamoto All Rights Reserved
 * *******************************************************************/

#define _XTAL_FREQ 4000000          // delay_ms(x) のための定義

#include <xc.h>
#include <stdio.h>
#include <stdlib.h>

//******************* コンフィグレーション ****************************
#pragma config FOSC = INTOSC, WDTE = OFF, PWRTE = OFF, MCLRE = OFF, CP = OFF
#pragma config CPD = OFF, BOREN = ON, CLKOUTEN = OFF, IESO = OFF, FCMEN = OFF
#pragma config WRT = OFF, PLLEN = OFF, STVREN = ON, BORV = LO, LVP = OFF
//

// ================= printf関数を使用するための定義 =================
void putch(unsigned char ch) {
    while (!TXIF);               // 送信終了待ち
        TXREG = ch;
}

// ******************* main ******************************************
void main() {

    OSCCON = 0b01101010;       // 内部クロック4Mhz
    PORTA  = 0x00;
    TRISA  = 0b11111111;       // Port すべて入力
    ANSELA = 0x00;             // すべてデジタル
    WPUA   = 0b00000000;       // RA3 弱プルアップ OFF
    nWPUEN = 1;

//------------ Initialize UART -------------------
    RCSTA   = 0b10000000;      // 非同期送信 9600baud
    TXSTA   = 0b00100100;
    BAUDCON = 0b00001000;
    SPBRGH  = 0;
    SPBRG   = 103;
    // --------- Initialize ADC -----------------
    ANSA4 = 1;                  // AN3はアナログ入力に設定
    ADCON1 = 0b11000000;        // 右詰め出力, AD変換クロックFosc/4
                                // 正基準電圧 VDD
    ADCON0 = 0b00001101;        // アナログ入力 AN3(RA4),ADC ON

    __delay_ms(500);            // LCD表示器安定待ち
    printf("¥x01");             // 画面クリア
    printf("A/D conv");         // 上段に表示

    // ----------- 繰返し ----------------------------------
    while(1){
        __delay_ms(100);        // LEDちらつき防止の遅延
        GO = 1;                 // AD変換開始
        while(GO);              // AD変換終了待ち
        printf("¥x03");         // 下段先頭にカーソル
        printf("%4d",ADRES);    // AD変換結果送信
    }
}

<プログラム 2>
  基準電圧に内部 FVR を使用し、ADC用バッファの倍率を x2(2.048v)に設定。AD変換した値を2倍することで、0-2vまで mV直読のデジボルとなる。

/*********************************************************************
 *  AD変換した値をUARTでデータ送信する。
 *  基準電圧に内部 FVRx2 を使用し、0-2vまでは直読とした
 *          4MHz (内部クロック)
 *
 *      1 VDD         8 VSS
 *      2 RA5         7 RA0 TX
 *   IN 3 RA4         6 RA1
 *      4 MCLR        5 RA2
 *
 * PIC12F1822  MPLAB X IDE with XC8 Ver1.32
 * Copyright (c) 2012 iwamoto All Rights Reserved
 * *******************************************************************/

#define _XTAL_FREQ 4000000          // delay_ms(x) のための定義

#include <xc.h>
#include <stdio.h>
#include <stdlib.h>

//******************* コンフィグレーション ****************************
#pragma config FOSC = INTOSC, WDTE = OFF, PWRTE = OFF, MCLRE = OFF, CP = OFF
#pragma config CPD = OFF, BOREN = ON, CLKOUTEN = OFF, IESO = OFF, FCMEN = OFF
#pragma config WRT = OFF, PLLEN = OFF, STVREN = ON, BORV = LO, LVP = OFF
//

// ================= printf関数を使用するための定義 =================
void putch(unsigned char ch) {
    while (!TXIF);               // 送信終了待ち
        TXREG = ch;
}

// ******************* main ******************************************
void main() {
    OSCCON = 0b01101010;       // 内部クロック4Mhz
    PORTA  = 0x00;
    TRISA  = 0b11111111;       // Port すべて入力
    ANSELA = 0x00;             // すべてデジタル
    WPUA   = 0b00000000;       // RA3 弱プルアップ OFF
    nWPUEN = 1;

//------------ Initialize UART -------------------
    RCSTA   = 0b10000000;      // 非同期送信 9600baud
    TXSTA   = 0b00100100;
    BAUDCON = 0b00001000;
    SPBRGH  = 0;
    SPBRG   = 103;
    // --------- Initialize ADC -----------------
    ANSA4 = 1;                  // AN3はアナログ入力に設定
    ADCON1 = 0b11000011;        // 右詰め出力, AD変換クロックFosc/4
                                // 正基準電圧 FVR
    ADCON0 = 0b00001101;        // アナログ入力 AN3(RA4),ADC ON
    // --------- Initialize FVR -----------------
    FVRCON = 0b10000010;        // ADC用出力 x2(2.048v)に設定

    __delay_ms(500);            // LCD表示器安定待ち
    printf("¥x01");             // 画面クリア
    printf("A/D conv");         // 上段に表示

    // ----------- 繰返し ----------------------------------
    while(1){
        __delay_ms(100);        // LEDちらつき防止の遅延
        GO = 1;                 // AD変換開始
        while(GO);              // AD変換終了待ち
        printf("¥x03");         // 下段先頭にカーソル
        printf("%4d",ADRES<<1); // AD変換結果送信
    }
}