PIC16F1705は、8チャンネルのADコンバータを使うことができます。内部のADコンバータは1つなのですが、下の図のようにADCON0レジスタのCHS<4:0>によってチャンネルを選択します。
PIC16F1705の説明書から転載
今回のテストでは、AN0とAN1を使い、VREF+はFVR×2=2.048Vとして、AD変換値をI2C LCD AQM0802Aに2つの値を表示してみます。
ブレッドボードです。電源は乾電池2本(3V)です。
プログラムです。
AD変換の手順については、PIC12F1822と同じなので、私のホームページ「JH7UBCホームページ」のこの記事を見てください。
ADコンバータの変換結果(0~1023)は、AQM0802Aの1行目にAN0(CH0)を2行目にAN1(CH1)を0.5秒ごとに表示します。
AN0とAN1の選択は、ADCON0レジスタのbit2 CHS0で行います。CHS0=0でAN0、CHS0=1でAN1が選択されます。
-----------------------------------------------------------
/*
* File: main.c
* Author: JH7UBC Keiji Hata
* PIC16F1705 ADC test
* Created on 2019/04/23
*/
* File: main.c
* Author: JH7UBC Keiji Hata
* PIC16F1705 ADC test
* Created on 2019/04/23
*/
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include <stdlib.h>
#include <xc.h>
// CONFIG1
#pragma config FOSC = INTOSC //内部クロックを使う
#pragma config WDTE = OFF //ウォッチドックタイマー無効
#pragma config PWRTE = ON //パワーアップタイマーを有効にする
#pragma config MCLRE = OFF //MCLRピンをRA3として使用する
#pragma config CP = OFF //プログラムメモリを保護しない
#pragma config BOREN = ON //ブラウンアウトリセットを有効にする
#pragma config CLKOUTEN = OFF //クロック出力を無効とし、RA4ピンとして使用する
#pragma config IESO = OFF //内部・外部クロックの切り替えでの起動を行わない
#pragma config FCMEN = OFF //外部クロックを監視しない
#pragma config FOSC = INTOSC //内部クロックを使う
#pragma config WDTE = OFF //ウォッチドックタイマー無効
#pragma config PWRTE = ON //パワーアップタイマーを有効にする
#pragma config MCLRE = OFF //MCLRピンをRA3として使用する
#pragma config CP = OFF //プログラムメモリを保護しない
#pragma config BOREN = ON //ブラウンアウトリセットを有効にする
#pragma config CLKOUTEN = OFF //クロック出力を無効とし、RA4ピンとして使用する
#pragma config IESO = OFF //内部・外部クロックの切り替えでの起動を行わない
#pragma config FCMEN = OFF //外部クロックを監視しない
// CONFIG2
#pragma config WRT = OFF //フラッシュメモリを保護しない
#pragma config PPS1WAY = OFF //ロック解除シーケンスで何度でもPPSLOCKをセット/クリアできる
#pragma config ZCDDIS = ON //ゼロクロス検出回路無効
#pragma config PLLEN = ON //×4PLLを動作させる
#pragma config STVREN = ON //スタックオーバーフローリセットを行う
#pragma config BORV = HI //ブラウンアウトリセット電圧を高(2.7V)に設定
#pragma config LPBOR = OFF //低消費電力ブラウンアウトリセット無効
#pragma config LVP = OFF //低電圧プログラミングを行わない
#pragma config WRT = OFF //フラッシュメモリを保護しない
#pragma config PPS1WAY = OFF //ロック解除シーケンスで何度でもPPSLOCKをセット/クリアできる
#pragma config ZCDDIS = ON //ゼロクロス検出回路無効
#pragma config PLLEN = ON //×4PLLを動作させる
#pragma config STVREN = ON //スタックオーバーフローリセットを行う
#pragma config BORV = HI //ブラウンアウトリセット電圧を高(2.7V)に設定
#pragma config LPBOR = OFF //低消費電力ブラウンアウトリセット無効
#pragma config LVP = OFF //低電圧プログラミングを行わない
#define _XTAL_FREQ 32000000 //クロック32MHz
/* LCD関係定義 */
#define LCD_addr 0x7C //3E+0
#define LCD_LINE1 0x80
#define LCD_LINE2 0xC0
#define LCD_addr 0x7C //3E+0
#define LCD_LINE1 0x80
#define LCD_LINE2 0xC0
/* I2C 初期化*/
void I2C_init(){
SSP1CON1 = 0x28; //SSPEN = 1,I2C Master Mode
SSP1STATbits.SMP = 1; //標準速度モード(100KHz)
SSP1ADD = 0x4F; //Fosc/(4*Clock)-1 Clock=100kHz,Fosc=32MHz
}
void I2C_init(){
SSP1CON1 = 0x28; //SSPEN = 1,I2C Master Mode
SSP1STATbits.SMP = 1; //標準速度モード(100KHz)
SSP1ADD = 0x4F; //Fosc/(4*Clock)-1 Clock=100kHz,Fosc=32MHz
}
/* スタートコンディション */
void I2C_start(){
SSP1CON2bits.SEN = 1;
while(SSP1CON2bits.SEN);
}
void I2C_start(){
SSP1CON2bits.SEN = 1;
while(SSP1CON2bits.SEN);
}
/* ストップコンディション */
void I2C_stop(){
SSP1IF = 0;
SSP1CON2bits.PEN = 1;
while(SSP1CON2bits.PEN);
SSP1IF = 0;
}
void I2C_stop(){
SSP1IF = 0;
SSP1CON2bits.PEN = 1;
while(SSP1CON2bits.PEN);
SSP1IF = 0;
}
/* I2Cに1byte送信 */
void I2C_write(unsigned char dat){
SSP1IF = 0;
SSP1BUF = dat;
while(!SSP1IF);
}
void I2C_write(unsigned char dat){
SSP1IF = 0;
SSP1BUF = dat;
while(!SSP1IF);
}
/* write command */
void LCD_cmd(unsigned char cmd){
I2C_start(); //start condition
I2C_write(LCD_addr); //send slave address
I2C_write(0x00); //send control byte
I2C_write(cmd); //send command
I2C_stop(); //stop condition
}
void LCD_cmd(unsigned char cmd){
I2C_start(); //start condition
I2C_write(LCD_addr); //send slave address
I2C_write(0x00); //send control byte
I2C_write(cmd); //send command
I2C_stop(); //stop condition
}
/* write charactor */
void LCD_char(unsigned char dat){
I2C_start(); //start condition
I2C_write(LCD_addr); //send slave address
I2C_write(0x40); //send control byte
I2C_write(dat); //send data
I2C_stop(); //stop condition
}
void LCD_char(unsigned char dat){
I2C_start(); //start condition
I2C_write(LCD_addr); //send slave address
I2C_write(0x40); //send control byte
I2C_write(dat); //send data
I2C_stop(); //stop condition
}
/* LCD initialize */
void LCD_init(){
__delay_ms(40); //40ms wait
LCD_cmd(0x38); //8bit,2line
LCD_cmd(0x39); //IS=1 : extention mode set
LCD_cmd(0x14); //Internal OSC Frequency
LCD_cmd(0x70); //Contrast set
LCD_cmd(0x56); //Power/ICON/Contrast Control
LCD_cmd(0x6C); //Follower control
__delay_ms(200);//200ms wait
LCD_cmd(0x38); //IS=0 : extention mode cancel
LCD_cmd(0x0C); //Display ON
LCD_cmd(0x01); //Clear Display
__delay_ms(2); //wait more than 1.08ms
}
void LCD_init(){
__delay_ms(40); //40ms wait
LCD_cmd(0x38); //8bit,2line
LCD_cmd(0x39); //IS=1 : extention mode set
LCD_cmd(0x14); //Internal OSC Frequency
LCD_cmd(0x70); //Contrast set
LCD_cmd(0x56); //Power/ICON/Contrast Control
LCD_cmd(0x6C); //Follower control
__delay_ms(200);//200ms wait
LCD_cmd(0x38); //IS=0 : extention mode cancel
LCD_cmd(0x0C); //Display ON
LCD_cmd(0x01); //Clear Display
__delay_ms(2); //wait more than 1.08ms
}
/* Clear Display */
void LCD_clear(){
LCD_cmd(0x01);
__delay_ms(1);
__delay_us(80);
}
void LCD_clear(){
LCD_cmd(0x01);
__delay_ms(1);
__delay_us(80);
}
/* Return Home `*/
void LCD_home(){
LCD_cmd(0x02);
__delay_ms(1);
__delay_us(80);
}
void LCD_home(){
LCD_cmd(0x02);
__delay_ms(1);
__delay_us(80);
}
/* Locate cursor x,y */
void LCD_cursor(unsigned char x,unsigned char y){
if (y == 0){
LCD_cmd(LCD_LINE1+x);
}
if (y == 1){
LCD_cmd(LCD_LINE2+x);
}
}
void LCD_cursor(unsigned char x,unsigned char y){
if (y == 0){
LCD_cmd(LCD_LINE1+x);
}
if (y == 1){
LCD_cmd(LCD_LINE2+x);
}
}
/* write 1 charactor to LCD */
void putch(unsigned char ch){
LCD_char(ch);
}
void putch(unsigned char ch){
LCD_char(ch);
}
/* ADconvert & display*/
void AD_convert(unsigned char channel){
ADCON0bits.CHS0 = channel; //ADC チャンネルセレクト
__delay_us(20); // 20us待つ
GO = 1; // ADC スタート
while(GO); // AD変換終了まで待つ
unsigned int val = (ADRESH << 8)| ADRESL; //AD変換結果をvalに入れる
LCD_cursor(3,channel);
printf("%5d",val); // AD変換結果を表示
}
void AD_convert(unsigned char channel){
ADCON0bits.CHS0 = channel; //ADC チャンネルセレクト
__delay_us(20); // 20us待つ
GO = 1; // ADC スタート
while(GO); // AD変換終了まで待つ
unsigned int val = (ADRESH << 8)| ADRESL; //AD変換結果をvalに入れる
LCD_cursor(3,channel);
printf("%5d",val); // AD変換結果を表示
}
void main() {
OSCCON = 0b01110000; // 内部クロック8MHz ×4=32MHz
ANSELA = 0b00000011; // AN0-AN1を使う。他はデジタル
ANSELC = 0b00000000; // AN4-AN6を使わない
TRISA = 0b00000011; // RA0,RA1は入力、他は出力
TRISC = 0b00000011; // RC0,RC1は入力、他は出力
PORTA = 0b00000000; // PORTAクリア
PORTC = 0b00000000; // PORTCクリア
/* ADコンバータ設定*/
ADCON0 = 0b00000001; // bit0=1 ADCを有効にする
ADCON1 = 0b10100011; // bit7(ADFM)=1(右詰め),bit<6:4>=010 Fosc/32=1.0us
// bit<1:0>=00 VREF+=FVR
FVRCON = 0b10000010; // bit7(FVRON)=1,bit<1:0>=10 ADFVR×2=2.048V
/* I2Cピン設定 */
RC0PPS = 0x10; //RC0をSCLに割り当てる(出力)
SSPDATPPS = 0x11;//SSPDATにRC1を割り当てる(入力)
RC1PPS = 0x11; //RC1をSDAに割り当てる(出力)
I2C_init(); // I2C初期化
LCD_init(); // LCD初期化
/* 表示初期設定*/
LCD_home();
printf("CH0");
LCD_cursor(0,1);
printf("CH1");
while(1){
AD_convert(0); //channel0をAD変換・表示
AD_convert(1); //channel1をAD変換・表示
__delay_ms(500);
}
}
OSCCON = 0b01110000; // 内部クロック8MHz ×4=32MHz
ANSELA = 0b00000011; // AN0-AN1を使う。他はデジタル
ANSELC = 0b00000000; // AN4-AN6を使わない
TRISA = 0b00000011; // RA0,RA1は入力、他は出力
TRISC = 0b00000011; // RC0,RC1は入力、他は出力
PORTA = 0b00000000; // PORTAクリア
PORTC = 0b00000000; // PORTCクリア
/* ADコンバータ設定*/
ADCON0 = 0b00000001; // bit0=1 ADCを有効にする
ADCON1 = 0b10100011; // bit7(ADFM)=1(右詰め),bit<6:4>=010 Fosc/32=1.0us
// bit<1:0>=00 VREF+=FVR
FVRCON = 0b10000010; // bit7(FVRON)=1,bit<1:0>=10 ADFVR×2=2.048V
/* I2Cピン設定 */
RC0PPS = 0x10; //RC0をSCLに割り当てる(出力)
SSPDATPPS = 0x11;//SSPDATにRC1を割り当てる(入力)
RC1PPS = 0x11; //RC1をSDAに割り当てる(出力)
I2C_init(); // I2C初期化
LCD_init(); // LCD初期化
/* 表示初期設定*/
LCD_home();
printf("CH0");
LCD_cursor(0,1);
printf("CH1");
while(1){
AD_convert(0); //channel0をAD変換・表示
AD_convert(1); //channel1をAD変換・表示
__delay_ms(500);
}
}
※コメント投稿者のブログIDはブログ作成者のみに通知されます