PIC18F46K22 PWM(Timer2+CCP3)によるLEDの明るさ変更(アセンブラ)

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

概要

PIC18F46K22 のtimer2とCCP3を使用してPWMをRB5端子に出力します。
デューティ比を約0~100%を約6.4秒で変化させます。
RC1端子にLEDが接続されていますので消灯から最大明るさまで変化させることができます。
回路図を以下に示します。LEDが5個接続されていますが本プログラムに必要なLEDはRB5に接続されているLEDのみです。
../pwm3a/pwm3a.svg
回路図(PDF)

PWMの動作について

../pwm3a/ccpx.svg ../pwm3a/ccpxtime.svg
TMRx(上位8bit)は8bitのカウントでFOSC/4をプリスケーラー(1:1,1:4,1:16)で分周したクロックで増加方向にカウントします。
PRxとTMRx(上位8bit)の値が一致した場合、TMRxカウンターを0クリアします。またCCPRxL,CCPxCONレジスタをCCPRxHレジスタに転送します。SがセットされるのでQはHiになります。
TMRx(上位8bit+下位2bit)とCCPRxHレジスタと一致したとき出力がRがセットされ、QはLowになります。
TMRx(下位2bit)はTMRx(上位8bit)に入力されたクロックの4倍の周波数でカウントされる2bitのカウンターです。
PRxを0xffに設定した場合、PWMのHiの幅は10bit(1024)の分解能が得られることになります。
PWMの周期がPRxレジスタ、パルス幅はCCPRxL,CCPxCONで設定することになります。
FOSC/4=16MHz,プリスケーラー1:4,PRx=0xff,CCPRxL=25 CCPxCON<5:4>=2 時の実測波形を以下に示します。
 
周期が15.62kHz、hiの幅が6.32μ秒です。
計算上の値は以下の通りです。概ね実測値と一致しています。
FOSC/4/4/256=15.625kHz
CCPRxH=25*4+2=102
102/(FOSC/4)=6.375μ秒

プログラムの説明

Timer2をソースとしてCCP3をシングルPWMで初期化します。
パルスステアリングモードによりPWMの出力をCCP3→P3A(RB5)に割り当てます。(PSTR3CONレジスタ)
プリスケーラー 1:4
PWM周波数 FOSC/4/4/256=15.625kHz
RC1をIOポートに設定し出力にします。
メモリ上の16bitカウンタcount16をクリアします。
PWMのパルス幅を設定するためにcount16の値を引数としてサブルーチンSetDCPWMxを呼び出します。
ソフトウェアディレイにより6.25m秒待機します。
count16に1を加算し、上記のPWMのパルス幅設定の処理へジャンプします。
メインプログラムでタイマー設定を行い、無限ループとする。
カウンタ値は下位10bitが有効となります。
6.25m秒×1024=6.4秒がLEDの明るさの変化の1周期となります。

SetDCPWMx

16bitの変数arg16に設定された値でパルス幅を設定します。
arg16の下位2bitの値をCCPxCONの5~4bitにコピーします。
arg16の9~2bitの値をCCPRxLにコピーします。

ソースファイル

以下のファイルで構成されている
pwm6a.asm ・・・ プログラム

ソースファイルのダウンロード pwm6a.zip

; timer2+CCP3(PWM P3A(RB5)よる明るさ連続変更サンプル
; 慈渓博瑞テクノロジー株式会社 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

bank0       UDATA_ACS   ; 変数の定義 アクセスバンク
Tcount2  RES     1
Tcount3  RES     1
Tcount4  RES     2  ;   6.25ms
arg16    RES     2
count16  RES     2

        CODE
        org 0
        goto   start

start
        BANKSEL CCPTMRS0
        clrf    CCPTMRS0,BANKED  ;   Timer2をソースとする
        movlw   0ffh
        movwf   PR2
        movlw   b'00001100'      ;   PWM
        movwf   CCP3CON,BANKED
        movlw   b'00000101'      ;   PS 1:4 Timer2 On
        movwf   T2CON
        movlw   b'00000001'      ;   CCP3->P3A(RB5)
        movwf   PSTR3CON,BANKED
        movlw   b'00011111'     ;   RB5をIO
        movwf   ANSELB,BANKED   ;   bank 0Fh
        movlw   b'00011111'     ;   RB5をOut
        movwf   TRISB

        clrf    count16
        clrf    count16+1
loop
        movff   count16,arg16
        movff   count16+1,arg16+1

        call    SetDCPWM3


LOOP_MAX EQU d'1'       
;       wait  6.25ms*513=3.21s
        movlw   LOW LOOP_MAX
        movwf   Tcount4
        movlw   HIGH LOOP_MAX
        movwf   Tcount4+1
loop_start
        call    wait6_25ms
        clrf    WREG
        decf    Tcount4
        subwfb  Tcount4+1
        bc      loop_start

        incf    count16
        clrf    WREG
        addwfc  count16+1
        goto    loop

;        PWM設定 arg16:パルス幅
SetDCPWM3
        movlw   b'11001111'
        andwf   CCP3CON,BANKED 
        movf    arg16,W
        andlw   b'00000011'
        swapf   WREG
        iorwf   CCP3CON,BANKED 
        bcf     STATUS,C
        rrcf    arg16+1
        rrcf    arg16
        bcf     STATUS,C
        rrcf    arg16+1
        rrcf    arg16
        movf    arg16,W
        movwf   CCPR3L,BANKED 
        return

;       wait 6.25ms
wait6_25ms
        movlw   d'130'  ; 48μs*130=6.25ms
        movwf   Tcount2
dloop2                   ; t=(12+12*count3)/64MHz 48μs
        movlw   d'0'
        movwf   Tcount3
        nop
dloop3
        decfsz  Tcount3
        goto    dloop3
        decfsz  Tcount2
        goto    dloop2
        return

        END