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

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

概要

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

PWMの動作について

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

SetDCPWM2

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

ソースファイル

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

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

; timer2+CCP2(PWM P2A(RC1)出力)よる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

bank0       UDATA   ; 変数の定義 バンク0
Tcount2  RES     1
Tcount3  RES     1
arg16    RES     2
count16  RES     2

        CODE
        org 0
        goto   start
start
        movlb   0fh
        clrf    CCPTMRS0,BANKED  ;   Timer2をソースとする
        movlw   0ffh
        movwf   PR2
        movlw   b'00001100'      ;   PWM
        movwf   CCP2CON
        movlw   b'00000101'      ;   PS 1:4 Timer2 On
        movwf   T2CON

        movlw   b'00000001'      ;   CCP2->P2A(RC1)
        movwf   PSTR2CON,BANKED

        movlw   b'11111101'      ;   RC1をIO
        movwf   ANSELC,BANKED
        movlw   b'11111101'      ;   RC1をOUT
        movwf   TRISC

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

        call    SetDCPWM2
        call    wait6_25ms

        incf    count16
        clrf    WREG
        addwfc  count16+1
        goto    loop

;        PWM設定 arg16:パルス幅
SetDCPWM2
        movlw   b'11001111'
        andwf   CCP2CON
        movf    arg16,W
        andlw   b'00000011'
        swapf   WREG
        iorwf   CCP2CON
        bcf     STATUS,C
        rrcf    arg16+1
        rrcf    arg16
        bcf     STATUS,C
        rrcf    arg16+1
        rrcf    arg16
        movf    arg16,W
        movwf   CCPR2L
        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