PIC18F4550を使ってA/Dコンバーターの実験
2017/05/18
部品箱をひっくりかえしていたら、2軸の小型ジョイスティックが出てきた。
これは、10KΩの可変抵抗を二つ直角に付けて一つのレバーで操作するものである。
ちょうどLCDが基板に乗っているので、アナログ/デジタル変換の実験をやってみることにした。
回路としては以前の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);
}
ちょっと光っていて見にくいのだが、LCDは以下のような表示になっている。
L/R=0512
U/D=1023
指でジョイスティックを動かすと、値が変わる。
最低値が0、最高値が1023である。
A/D変換自体はかなり高速で、ほとんどの時間はLCDへの表示のためのI2Cの通信の時間である。
この程度の表示で12ミリ秒程度かかっている。
HOME