【A/D変換】PIC12F683のA/D変換機能を使ってみよう
A/D変換とは
一般にA/D変換というと、Analog/Digital Conversion つまりアナログ信号からディジタル信号への変換を意味します。逆は「D/A変換」と呼びます。
コンピュータの世界は、現在はほぼすべてがディジタルの世界で動いています。(昔にはアナログコンピュータと呼ばれるものがありました。)しかし、自然界はすべてがアナログの世界です。したがって、我々が普段接している世界に、コンピュータをつなごうとする時には、必ずA/D変換とD/A変換が必要になります。
A/D変換の原理
2ビットのA/Dコンバータで説明します。アナログ電圧として0~3Vまでの電圧をコンバータに加えると、2ビット分である「00」「01」「10」「11」の4段階で分けられます。例えば、1.5Vだった場合は、「01」へ変換されるということです。つまり、変換するビット数が多ければそれだけ細かくアナログ電圧をデジタル変換可能になるということになります。
AD変換の設定
AD変換を行うチャンネル設定が書かれています。このビットでチャンネル設定します。今回のサンプルプログラムでは「AN3」固定で実施していますが、AD変換する前にチャンネル設定すれば、複数のピンで実行することが可能です。ただし、一回の実行である程度時間を待つ必要があるため、シビアな時間設定を要求されるICとして活用に向いていないと思います。
この「ADCON0」の2ビット目「GO/DONE」を1にするとスタートします。私が作成したサンプルプログラムを参考に見てください。
回路図
12F683についての詳細は下記のリンク先よりみてください。さて、12F683には、アナログピンが4つ(AN0からAN3)あります。今回の回路は、AN3をアナログとして活用して、GP0からGP2をLED出力として利用することにしました。回路作成の注意点は、可変抵抗とアナログを接続する信号線に保護抵抗を入れるのを忘れないようにしてください。可変抵抗のため、場合によって0Ωになってしまい過大な電流を流す可能性が出てくるためです。
動作の動画
よろしければ、チャンネル登録お願いいたします。
プログラム
関数
途中で切り替えるためにPattern1とPattern2を作りました。
〇Pattern1
LEDの2つが常時点灯しており、可変抵抗を変えていくと、消灯→点滅→点灯と変化します。
〇Pattern2
可変抵抗の位置によってLEDの点灯場所が変わっていきます。 ●〇〇 → 〇●〇 → 〇〇●
void Pattern1(int ad_data){
GP1 = 1;
GP2 = 1;
if(ad_data <200){
GP0=0;
}
if(ad_data > 200 && ad_data < 800){
GP0=~GP0;
__delay_ms(500);
}
if(ad_data > 800 && ad_data<1000){
GP0=1;
}
}
void Pattern2(int ad_data){
if(ad_data <200){
GP0 = 1;
GP1 = 0;
GP2 = 0;
}
if(ad_data > 200 && ad_data < 800){
GP0 = 0;
GP1 = 1;
GP2 = 0;
}
if(ad_data > 800 && ad_data<1000){
GP0 = 0;
GP1 = 0;
GP2 = 1;
}
}
AD変換のサンプルプログラム
少しプログラムが長いですがコピー&ペーストで対応可能です。
/*
* File: AD.c
* Author: TM-kit
*
* Created on 2022/02/12, 21:59
*/
#include <xc.h>
// CONFIG
#pragma config FOSC = INTOSCIO // Oscillator Selection bits (INTOSCIO oscillator: I/O function on RA4/OSC2/CLKOUT pin, I/O function on RA5/OSC1/CLKIN)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON // Power-up Timer Enable bit (PWRT enabled)
#pragma config MCLRE = OFF // MCLR Pin Function Select bit (MCLR pin function is digital input, MCLR internally tied to VDD)
#pragma config CP = OFF // Code Protection bit (Program memory code protection is disabled)
#pragma config CPD = OFF // Data Code Protection bit (Data memory code protection is disabled)
#pragma config BOREN = OFF // Brown Out Detect (BOR disabled)
#pragma config IESO = OFF // Internal External Switchover bit (Internal External Switchover mode is disabled)
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is disabled)
#define _XTAL_FREQ 4000000
//スイッチを定義して今後SW1とする
#define SW1 GP5
#define Led_ON 1
#define Led_OFF 0
static void interrupt time0int (void)
{
if(INTCONbits.T0IF == 1){
/*タイマーフラグをリセット*/
INTCONbits.T0IF = 0;
TMR0=252;/*10m秒ごと*/
}
}
void Pattern1(int ad_data){
GP1 = 1;
GP2 = 1;
if(ad_data <200){
GP0=0;
}
if(ad_data > 200 && ad_data < 800){
GP0=~GP0;
__delay_ms(500);
}
if(ad_data > 800 && ad_data<1000){
GP0=1;
}
}
void Pattern2(int ad_data){
if(ad_data <200){
GP0 = 1;
GP1 = 0;
GP2 = 0;
}
if(ad_data > 200 && ad_data < 800){
GP0 = 0;
GP1 = 1;
GP2 = 0;
}
if(ad_data > 800 && ad_data<1000){
GP0 = 0;
GP1 = 0;
GP2 = 1;
}
}
void main(void) {
/*AD変換で利用する変数*/
char ad_temp=0;
int ad_data=0;
/*手順1:内部クロックの設定:4MHz*/
/*データシート:P19,P20*/
OSCCON=0b01101000;
/*ポートプルアップを使いたい場合は、このオプションレジスタを0で有効にしておく*/
/*プリスケーラ:256 */
OPTION_REG=0b00000111;
/*手順2:ポートデジタルに設定*/
/*P33(P35)*/
/*ANS3をON & Fosc/64*/
ANSEL=0b01101000;
/*手順3:ポートの入出力の設定 1;入力 0:出力*/
/*今回の設定:GP3は入力のみなので1を立てておく。また、今回は、反省を活かし入力をGP5とします*/
/*データシート:P36*/
TRISIO=0b00011000;
/*手順4 A/D変換の設定 使用しているピン*/
/* 設定:左寄せ Vdd AN3使用 A/D使用 */
ADCON0=0b00001101;
/*ポートのデータは何が入っているかわからないので、消灯できるように0をポートに入れておく*/
GPIO=0b00000000;
/*念のためにコンパレータを無効にしておく*/
CMCON0 = 0b00000111;
TMR0 = 252;
/*割り込みOK設定*/
INTCONbits.T0IE = 1;
INTCONbits.GIE = 1;
while(1){
__delay_us(200);//AD変換を利用する場合は、このくらいの時間を毎回待たせたほうが良いかと思います。無くても動作すると思います
ADCON0bits.GO_DONE = 1;
while(ADCON0bits.GO_DONE){}
ad_temp = ADRESH;
ad_data = ad_temp;
ad_data = ad_data << 2;
ad_data = ad_data | (ADRESL >> 6);
//ここのコメントアウトで出力方法を変更する。
//スイッチ入力で変更すると面白いかも
//Pattern1(ad_data);
Pattern2(ad_data);
}
return;
}
まとめ
12F683は、10ビットのAD変換機能を3つ持っています。8ピンマイコン最強と呼ばれるだけありますね。AD変換を使う場面はわりとあります。今回の活用方法は、ピンが少ないマイコンの入力を補う活用方法として考えられますね。
他の人の記事のパクリですよね?
コメントアウトの内容とプログラムが一致してないですよ、、、
ご指摘ありがとうございます。
ソースコードについては、過去に作成したプログラムをそのまま使っているところもあり、コメントが間違っているところもあるかもしれません。
また、確認してみたいと思います。
ちなみに、今回のマイコンは、過去に電子工作実験室から勉強して作成したものです。