山本ワールド
PIC18F46K22 PWM(Timer2+CCP2+CCP1)による2色LEDの明るさ変更(アセンブラ)
概要
PIC18F46K22 のtimer2とCCP1,CCP2を使用してPWMをRC1,RC2端子に出力します。
デューティ比を約0~100%を約6.4秒で変化させます。
RC1端子にLEDが接続されていますので消灯から最大明るさまで変化させることができます。
回路図を以下に示します。LEDが5個接続されていますが本プログラムに必要なLEDはRC1,RC2に接続されているLEDのみです。
回路図(PDF)
PWMの動作について
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をソースとしてCCP1,CCP2をシングルPWMで初期化します。
パルスステアリングモードによりPWMの出力をCCP2→P2A(RC1)に割り当てます。(PSTR2CONレジスタ)
同様にPWMの出力をCCP1→P1A(RC2)に割り当てます。(PSTR1CONレジスタ)
メモリ上の16bitカウンタcount16をクリアします。
PWMのパルス幅を設定するためにcount16の値を引数としてサブルーチンSetDCPWMxを呼び出します。
ソフトウェアディレイにより6.25m秒待機します。
count16に1を加算し、上記のPWMのパルス幅設定の処理へジャンプします。
メインプログラムでタイマー設定を行い、無限ループとする。
カウンタ値は下位10bitが有効となります。
6.25m秒×1024=6.4秒がLEDの明るさの変化の1周期となります。
arg16の下位2bitの値をCCPxCONの5~4bitにコピーします。
arg16の9~2bitの値をCCPRxLにコピーします。
パルスステアリングモードによりPWMの出力をCCP2→P2A(RC1)に割り当てます。(PSTR2CONレジスタ)
同様にPWMの出力をCCP1→P1A(RC2)に割り当てます。(PSTR1CONレジスタ)
プリスケーラー 1:4 PWM周波数 FOSC/4/4/256=15.625kHzRC1を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にコピーします。
ソースファイル
以下のファイルで構成されているpwm4a.asm ・・・ プログラム
ソースファイルのダウンロード pwm4a.zip
; timer2+CCP2(PWM P2A(RC1)出力 青LED)+CCP1(PWM P1A(RC2)出力 赤LED)よる2色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_ACS ; 変数の定義 アクセスバンク
Tcount2 RES 1
Tcount3 RES 1
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 CCP2CON
movwf CCP1CON
movlw b'00000101' ; PS 1:4 Timer2 On
movwf T2CON
movwf T1CON
movlw b'00000001' ; CCP2->P2A(RC1)
movwf PSTR2CON,BANKED
movlw b'00000001' ; CCP1->P1A(RC2)
movwf PSTR1CON,BANKED
movlw b'11111001' ; RC1 RC2をIO
movwf ANSELC,BANKED
movlw b'11111001' ; RC1 RC2をOUT
movwf TRISC
clrf count16
clrf count16+1
loop
movff count16,arg16
movff count16+1,arg16+1
call SetDCPWM2
movff count16,arg16
movff count16+1,arg16+1
call SetDCPWM1
incf count16
clrf WREG
addwfc count16+1
call wait6_25ms
goto loop
; PWM設定 arg16:パルス幅
SetDCPWM1
movlw b'11001111'
andwf CCP1CON
movf arg16,W
andlw b'00000011'
swapf WREG
iorwf CCP1CON
bcf STATUS,C
rrcf arg16+1
rrcf arg16
bcf STATUS,C
rrcf arg16+1
rrcf arg16
movf arg16,W
movwf CCPR1L
return
; 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
Copyright (C) 2012 山本ワールド All Rights Reserved.