山本ワールド
PIC18F46K22でAN11の入力電圧をAD変換しSPIで7セグLEDを4桁で表示
概要
AD変換
AN11のアナログ電圧をAD変換して7segLED 4桁に表示します。アナログ電圧の発生に半固定抵抗を用いました。PIC18F46K22には10bitの逐次型のAD変換器が内臓されています。入力の切り替えにより最大29チャンネルのアナログ信号を扱えます。
AD変換器の基準電圧はPIC18F46K22の内臓FVRの1.024,2.048,4.096Vを使用することができます。
例えば4.096Vを選択すると1bitの分解能は4.096/1024=4mVとなります。
ここではFVRを4.096Vに設定することによりAD変換値を4倍にすることによりmV単位で直読することができます。
使用メモリは以下のとおりです。
プログラムメモリ 263byte
アクセスバンク 31byte(スタック16byte)
全回路図は以下の通りです。
PDFデーターAD11_7SEG4A1.PDF
7SEG LED
7SEG LEDの回路及びソフトは以下の通りです。PIC18F46K22 のSPIに74HC595経由で7セグメントLED4桁をドライブする。
回路はSPIで7セグLEDを4桁ドライブする回路のとおりである。
本プログラムはダイナミック点灯のタイミングはtimer0を使用する。
ソフトの概要
timer0を使用して1ms置きに割り込みを掛けAD変換値を読み取り4倍にして桁を切り替えながら表示します。AD変換を1桁表示するごとに実行していますのでその間にアナログ値が変化していると表示にちらつきが生じます。
実用的には1ms*4の倍数の時間ごとにAD変換をかける必要があります。
AD変換の設定
AD変換を使用するには、基準電圧4.096Vを設定します。(VREFCON0)
アナログ入力する端子はアナログ入力を選択します。(ANSELB)
どの端子を対象にAD変換するかを選択するにはADCON0を設定します。
本プログラムではシフト演算子を使用してチャンネルをd'11'とソースに直接記述できるようにしてみました。
例えばAN9を選択する場合はd'9'に置き換えれば可能となります。
AD変換の基準電圧をFVRから得るように設定します。(ADCON1)
AD変換は変換開始をセットしてからサンプルホールドを開始し指定時間後にサンプルホールドを終了します。その後1bitずつ比較し最後にサンプルホールド用のコンデンサを放電します。
変換開始から実際に変換を開始するまでの時間をアクイジションタイムと呼びます。AD変換のアクイジションタイム及び1bitずつ比較するタイミングはTADと呼び、TADはクロックの分周比を設定することにより決まります。
サンプルホールドには時間がかかります。データーシートによると7.45μs以上とありますので、アクイジションタイムはそれ以上の時間を設定する必要があります。
本プログラムでは1ms置きに表示しますので、一番変換タイミングが遅いFOSC/64を選択していますので1MHz(TAD=1μs)となります。アクイジションタイムは20TADですので20μsとなります。逐次比較及び放電は11サイクルですので11μsとなります。
これらを合計すると20μs+11μs=31μsとなり、1ms以内に十分AD変換値を得ることができます。これらの設定は、ADCON2で設定します。
あとはAD変換開始を設定すれば変換終了を示すADCON0の1ビット目のGO/DONEフラグがセットされているのを確認してAD変換値を読み込みます。
アナログ入力する端子はアナログ入力を選択します。(ANSELB)
どの端子を対象にAD変換するかを選択するにはADCON0を設定します。
本プログラムではシフト演算子を使用してチャンネルをd'11'とソースに直接記述できるようにしてみました。
例えばAN9を選択する場合はd'9'に置き換えれば可能となります。
AD変換の基準電圧をFVRから得るように設定します。(ADCON1)
AD変換は変換開始をセットしてからサンプルホールドを開始し指定時間後にサンプルホールドを終了します。その後1bitずつ比較し最後にサンプルホールド用のコンデンサを放電します。
変換開始から実際に変換を開始するまでの時間をアクイジションタイムと呼びます。AD変換のアクイジションタイム及び1bitずつ比較するタイミングはTADと呼び、TADはクロックの分周比を設定することにより決まります。
サンプルホールドには時間がかかります。データーシートによると7.45μs以上とありますので、アクイジションタイムはそれ以上の時間を設定する必要があります。
本プログラムでは1ms置きに表示しますので、一番変換タイミングが遅いFOSC/64を選択していますので1MHz(TAD=1μs)となります。アクイジションタイムは20TADですので20μsとなります。逐次比較及び放電は11サイクルですので11μsとなります。
これらを合計すると20μs+11μs=31μsとなり、1ms以内に十分AD変換値を得ることができます。これらの設定は、ADCON2で設定します。
あとはAD変換開始を設定すれば変換終了を示すADCON0の1ビット目のGO/DONEフラグがセットされているのを確認してAD変換値を読み込みます。
プログラムの説明
seg7dispサブルーチン
引数ARGH:ARGLを4桁LEDに10進数として表示するデータを作成しdisp7segdataに保存します。word2deg
2byte整数ARGH:ARGLをBCD4桁に変換しアドレスFSR1に保存します。div16_8
16bit/8bitを計算します。spi2rw
WREGの値をSPIへ出力します。inth
Timer0の割り込みにより起動します。AD変換値を読み取り4倍します。読み取り後、AD変換開始を設定します。
桁データをLEDに転送します。
ソースファイル
以下のファイルで構成されているad11_7seg4a1.asm
ソースファイルのダウンロード ad11_7seg4a1.zip
; 7SEG LED4桁 ハードウェアSPIダイナミックスキャン+AN11サンプル(timer0使用) Version 1.00 2017/01/03
; AD変換値をmV単位でLEDに表示
; 慈渓博瑞テクノロジー株式会社 PIC18F46K22 マイコンキット Ver2013.12.08用
; http://akizukidenshi.com/catalog/g/gK-07231/
; 水晶は16MHzに交換してPICを64MHzで駆動
; MPLAB X IDE v3.45 Microchip MPASM(v5.70)
; PicKit 3
#INCLUDE <p18f46k22.inc>
; 水晶発振(16MHz) クロック分周無 PLL有効(*4) プライマリクロック有効 ウォッチドッグタイマ無効 低電圧プログラム書き込みモード無効
CONFIG FOSC = HSHP,PLLCFG=ON,PRICLKEN=ON,WDTEN=OFF,LVP=OFF
TMR0SET EQU d'131' ; 1/(64MHz/4)*128*(256-131)=0.001m秒
STACK_MAX EQU d'16' ; スタックサイズ
acs_bank UDATA_ACS ; 変数の定義 アクセスバンク
ARGL RES 1
ARGH RES 1
DIV_A RES 1 ; 除算の被除数を指定 サブルーチンコール後答えが返る
DIV_MOD RES 1 ; サブルーチンコール後余りが返る
DIV_B RES 1 ; 除算の除数を指定
DIV_AL RES 1
DIV_AH RES 1
DIV_MODL RES 1
DIV_MODH RES 1
DIV_COUNT RES 1
disp7segdata RES 4 ; 表示データ4桁分
disp7segcount RES 1 ; 表示桁位置
stack1 RES STACK_MAX ; スタックエリアFSR2
CODE
ORG 0
goto start ; リセット時
org 08h
goto inth ; 割り込み
start
lfsr 2,stack1+(STACK_MAX-1)
BANKSEL ANSELB
movlw b'10110000'
movwf VREFCON0,BANKED ; FVR 4.096V
movlw (d'11'<<2) ; AN11 Select
movwf ADCON0
movlw b'10001000' ; VREF+内臓FVR 0V
movwf ADCON1
movlw b'10111110' ; 右詰 20TAD FOSC/64=1MHz
movwf ADCON2
movlw b'00111111' ; AN11(RB4) Analog Select
movwf ANSELB,BANKED
bsf ADCON0,ADON ; AD変換イネブル
movlw b'11100110' ; SCK2 SS2 SDO2をデジタル入出力に設定
movwf ANSELD,BANKED
andwf PORTD
andwf TRISD
; i2c2モジュール設定
movlw b'00110001' ; FOSC/16
movwf SSP2CON1
movlw b'11000000' ; SCKの立下りでデーター更新
movwf SSP2STAT
; LEDの表示桁カウンタを初期化する
clrf disp7segcount
; LEDの表示を初期化する
setf WREG
call spi2rw
; Timer0を設定する
movlw b'11000110' ; 8bit FOSC/4 1:128
movwf T0CON
movlw TMR0SET
movwf TMR0L
; Timer0割り込み許可
bsf INTCON,TMR0IE
bsf INTCON,GIE
bra $
; 引数Wを10進数とみなして7SEG表示データを設定
seg7disp
lfsr 1,disp7segdata ; BCDデータ格納場所
; BCDデーターに変換
call word2deg
; 桁データ追加
movlw b'11100000'
addwf disp7segdata
movlw b'11010000'
addwf disp7segdata+1
movlw b'10110000'
addwf disp7segdata+2
movlw b'01110000'
addwf disp7segdata+3
return
; SPI2入出力
spi2rw
bcf PORTD,SS2
movwf SSP2BUF
btfss SSP2STAT,BF
goto $-2
movf SSP2BUF,w
bsf PORTD,SS2
return
inth ; 高位割り込み
bcf INTCON,TMR0IF ; 割り込みフラグクリア
; AD変換値読み込み
btfsc ADCON0,1 ; 1の場合AD変換中 GO/DONE
bra inth_adend
movff ADRESL,ARGL
movff ADRESH,ARGH
bsf ADCON0,1 ; AD変換開始 GO/DONE
; AD変換値を4倍にする
bcf STATUS,C
rlcf ARGL
rlcf ARGH
bcf STATUS,C
rlcf ARGL
rlcf ARGH
; ARGH:ARGLをLED表示用データーに変換
call seg7disp
inth_adend
lfsr 0,disp7segdata
movf disp7segcount,w
movf PLUSW0,w ; fsr0+wreg -> w
call spi2rw ; 74HC595へデータを転送
incf disp7segcount,w
andlw b'00000011'
movwf disp7segcount
movlw TMR0SET
movwf TMR0L
retfie FAST
word2deg ; 2byteの整数を4桁BCDに変換する 引数ARGH:ARGL FSR1:BCD保存先
movf ARGL,W
movwf DIV_AL
movf ARGH,W
movwf DIV_AH
movlw d'10'
movwf DIV_B
rcall div16_8
movf DIV_MODL,W
movwf POSTINC1
rcall div16_8
movf DIV_MODL,W
movwf POSTINC1
rcall div16_8
movf DIV_MODL,W
movwf POSTINC1
rcall div16_8
movf DIV_MODL,W
movwf POSTINC1
movf DIV_AL,W
return
; 除算 DIV_AH:DIV_AL / DIV_B 商はDIV_AH:DIV_AL 余りはDIV_MODL:DIV_MODLに返される
; 2016/12/17 FSR2で示されるスタックを1byte使用
div16_8 ; 16bit/8bit=16bit
clrf DIV_MODL
clrf DIV_MODH
movlw d'16'
div16_8_loop
movwf POSTDEC2
bcf STATUS,C
rlcf DIV_AL
rlcf DIV_AH
rlcf DIV_MODL
rlcf DIV_MODH
movf DIV_B,W
subwf DIV_MODL
btfsc STATUS,C
decf DIV_MODH
bnc div16_8_non_sub
bsf DIV_AL,0
bra div16_8_shift
div16_8_non_sub
movf DIV_B,W
addwf DIV_MODL
btfsc STATUS,C
incf DIV_MODH
div16_8_shift
movf PREINC2,W
decfsz WREG
bra div16_8_loop
return
END
Copyright (C) 2012 山本ワールド All Rights Reserved.