PIC18F46K22でAN11の入力電圧をAD変換しSPIで7セグLEDを4桁で表示

icon 項目のみ表示/展開表示の切り替え

概要

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
image1.svg

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変換値を読み込みます。

プログラムの説明

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