PIC18F4550を使ってA/Dコンバーターの実験
2017/05/18


部品箱をひっくりかえしていたら、2軸の小型ジョイスティックが出てきた。

これは、10KΩの可変抵抗を二つ直角に付けて一つのレバーで操作するものである。

ちょうどLCDが基板に乗っているので、アナログ/デジタル変換の実験をやってみることにした。



test_pgm027
回路としては以前のLCDの試験と同じようなものだが、別の試験をしようとしており、LEDがRD0〜RD7に8個付いている状態である。

アナログ入力はRA0とRA1を使っている。




例のごとく、A/D変換用のルーチンを別に作っておく。

ADC.hという名でヘッダーファイル

#define _XTAL_FREQ 48000000     // 使用するPIC等により動作周波数値を設定する
                                // 水晶は20MHzでPLLで48MHz動作

void ADC_Init(void);
unsigned int ADC_In(unsigned char CH);



ADC.cという名でサブルーチンを作る。

#include < xc.h >
#include "ADC.h"

void ADC_Init() {
    ADCON0 = 0b00000000;    // 
    ADCON1 = 0b00001101;    // Referenceは電源 
                            // AN0 AN1 Analog input
    ADCON2 = 0b10111100;    // 20TAD Fosc/4
}

unsigned int ADC_In(unsigned char CH) {
    
    unsigned int val;
        
//    ADCON0bits.ADON = 0;
    ADCON0 = 0b00000000;    // A/Dコンバーター停止
    if (CH == 1) ADCON0bits.CHS0 = 1;  // チャンネル決定
    ADCON0bits.ADON = 1;    // チャージ開始
//        __delay_ms(1) ;        // ms
    __delay_us(5) ;        // μs
    ADCON0bits.GO = 1;  // A/D変換開始
    while(ADCON0bits.NOT_DONE);       //AD変換終了フラグがたつ(0になるまで)
    val = ADRESH;
    val = val * 256 + ADRESL;
    
    return val;
}



あと、以前作ったLCDとI2Cのヘッダーファイルとサブルーチンをそっくりコピーして持ってくるだけである。

こういうところがソフトウェアの強みで、一回十分なテストをしてあれば、だいたいそのまま使える場合が多いのである。
と言いながら、なかなかそうはいかないのだが・・・・


最後にメインのプログラム。

/* 
 * File:   main.c
 * Author: y.asaka
 *
 * Created on 2017/05/14, 13:50
 */

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

#include "LCD.h"
#include "ADC.h"

#define _XTAL_FREQ 48000000     // 使用するPIC等により動作周波数値を設定する
                                // 水晶は20MHzでPLLで48MHz動作

/*
 * 
 */
// コンフィギュレーション pic18f4550  c18
#pragma config PLLDIV = 5, CPUDIV = OSC1_PLL2, USBDIV = 2
#pragma config FOSC = HSPLL_HS, FCMEN = OFF, IESO = OFF
#pragma config PWRT = ON, BOR = OFF, BORV = 0
#pragma config VREGEN = ON, WDT = OFF, WDTPS = 1
#pragma config CCP2MX = OFF, PBADEN = OFF, LPT1OSC = OFF
#pragma config MCLRE = OFF, STVREN = OFF, LVP = OFF
#pragma config ICPRT = OFF, XINST = OFF, DEBUG = OFF
#pragma config CP0 = OFF, CP1 = OFF, CP2 = OFF, CP3 = OFF
#pragma config CPB = OFF, CPD = OFF
#pragma config WRT0 = OFF, WRT1 = OFF, WRT2 = OFF, WRT3 = OFF
#pragma config WRTC = OFF, WRTB = OFF, WRTD = OFF
#pragma config EBTR0 = OFF, EBTR1 = OFF, EBTR2 = OFF, EBTR3 = OFF, EBTRB = OFF

int main(int argc, char** argv) {
    
    unsigned int AdcValue;
    char str[17];
    int len;

    TRISA = 0b11111111;			//PORTA=0-7 input   
    TRISD = 0b00000000;			//PORTD=0-7 output   
    TRISB = 0b11111111;			//PORTB=0-7 input   
    LATD = 0;
    
    lcd_init();
    ADC_Init();

    AdcValue = 0;
    
   while(1){
        LATDbits.LD0 = 1;

        AdcValue = ADC_In(0);
        len = sprintf(str,"L/R=%04d",AdcValue);
        lcd_loc(0,0);
        lcd_str(str);

        AdcValue = ADC_In(1);
        len = sprintf(str,"U/D=%04d",AdcValue);
        lcd_loc(0,1);
        lcd_str(str);
        
        LATDbits.LD0 = 0;
        __delay_ms(5) ;        // ms
//        AdcValue++;
    }
    
    return (EXIT_SUCCESS);
}

test_pgm028
ちょっと光っていて見にくいのだが、LCDは以下のような表示になっている。

L/R=0512
U/D=1023

指でジョイスティックを動かすと、値が変わる。
最低値が0、最高値が1023である。

A/D変換自体はかなり高速で、ほとんどの時間はLCDへの表示のためのI2Cの通信の時間である。
この程度の表示で12ミリ秒程度かかっている。



HOME