山本ワールド
PIC18F46K22でPWMにより任意パルス列作成サンプル(アセンブラ)
概要
PIC18F46K22 のTimer2でCCP3を用い4つの任意周期と任意のhi期間のパルスを繰り返します。
回路はPIC18F46K22でLEDを点滅(アセンブラ)のとおりである。
PWMの設定方法は、PIC18 PWMの設定例を参照されたい。
パルス列の例
プログラムの説明
メインルーチン
最初の1個目のパルス周期とパルス幅はメインルーチンで設定します。メインプログラムでCCP3とタイマー2を関連付けてPRレジスタに周期を設定してからタイマー設定を行う。
パルス幅と周期はソースプログラムの最後の方のTBLアドレス以降のSYNC_TIMマクロで設定する。
SYNC_TIMマクロの第1引数がパルス周期(n秒単位)、第2引数がパルス幅(n秒単位)を表す。
パルスの数はTBL_MAXで設定している。
Timer2の割り込みを有効にしてメインルーチンは無限ループに入る。
割り込み処理ルーチン
TMR2とPRが一致すると割り込みが発生するので、次のパルスの周期と2パルス目のパルス幅を設定し割り込みを終了する。次のパルス幅ではなく、2パルス目を入力するのは、CCPR3Lレジスタの値が有効になるのは、次にカウンタがリセットされるときだからである。
タイマーとCCPの動作
①PR2==TMR2の時、PICはカウンタのリセットとCCPR3LレジスタをCCPR3Hレジスタに転送します。出力はHiになります。
②カウンタ値とCCPR3Hレジスタと一致したとき出力がLowになります。
③PR2==TMR2の時、PICはカウンタのリセットとCCPR3LレジスタをCCPR3Hレジスタに転送します。出力はHiになります。
以上を4回繰り返し後、1個目のパルスから再度実行する。
RB4はオシロスコープの同期用に割り込み処理ルーチンで発生している。
周期とhi期間はTBLラベル以降に設定します。
PLUSE_TIMEマクロによりns単位で周期,hi期間,波形回数,プリスケーラ設定値を直観的に指定できます。
波形回数を1以上にすると同じ波形を繰り返します。
次のソースは上記の写真の波形を得るための設定例です。
波形は4種類でその数はTBL_MAXで4個を設定します。4種類の波形を繰り返し表示します。
TBL ; 周期ns hi期間ns 回数 プリスケーラ PLUSE_TIM d'60000', d'8000',1,4 PLUSE_TIM d'40000',d'20000',1,4 PLUSE_TIM d'20000',d'10000',1,4 PLUSE_TIM d'40000', d'8000',1,4
PWMのブロック図
タイマー設定値
FOSC/4=16MHzプリスケーラ 1:4
PR2 255
周期 16MHz/4/(1+256)=15.625KHz
ソースファイル
以下のファイルで構成されているpwm1a.asm ・・・ メインプログラムと割り込み処理プログラム
ソースファイルのダウンロード pwm1a.zip
; 任意パルス列作成サンプル 2014/03/11 22:00
; 慈渓博瑞テクノロジー株式会社 PIC18F46K22 マイコンキット Ver2013.12.08用
; http://akizukidenshi.com/catalog/g/gK-07231/
; 水晶は16MHzに交換してPICを64MHzで駆動
; MPLAB X IDE v1.85 Microchip MPASM(v5.51)
; PicKit 3
;
; 波形出力例(単位μs)
;
; RB4 __|~~~~~~|_____________|
;
; CCP3 __|~|____|~|__|~|_|~|__|
; S R S R S R S R S
; Hi <20> <10> <4> <8>
; 周期 <-60-><-40-><20><-40->
#INCLUDE <p18f46k22.inc>
; 水晶発振(16MHz) クロック分周無 PLL有効(*4) プライマリクロック有効
; ウォッチドッグタイマ無効 低電圧プログラム書き込みモード無効
CONFIG FOSC = HSHP,PLLCFG=ON,PRICLKEN=ON,WDTEN=OFF,LVP=OFF
bank0 UDATA ; 変数の定義 バンク0
num RES 1 ; 現在のパルス位置
tbl_ads RES 3 ; SYNC_TBLアドレス
pluse_count RES 1 ; パルス個数カウント
SYNCTRG_ADS EQU PORTB ; オシロスコープ用のトリガ
SYNCTRG_BIT EQU RB4 ; オシロスコープ用のトリガ
TBL_MAX EQU 4 ; 波形数
; プログラムメモリのアドレスadsをTBLPTRレジスタに設定
LDTBLPTR MACRO ads
movlw UPPER (ads)
movwf TBLPTRU
movlw HIGH (ads)
movwf TBLPTRH
movlw LOW (ads)
movwf TBLPTRL
ENDM
CODE
org 0
goto start
org 08h
goto inth ; 割り込み
start
movlb d'15'
clrf CCPTMRS0,BANKED ; Timer2をソースとする
movlw b'00001100' ; PWM
movwf CCP3CON,BANKED
movlw b'00000101' ; PS 1:4 Timer2 On
movwf T2CON,BANKED
movlw b'00001111' ; RB5 RB4をIO
movwf ANSELB,BANKED ; bank 0Fh
movlw b'00001111' ; RB5 RB4をOUT
movwf TRISB
LDTBLPTR TBL
tblrd *+
movff TABLAT,PR2
tblrd *+
movff TABLAT,CCPR3L
tblrd *+
movf TABLAT,W
iorwf CCP3CON
tblrd *+
movff TABLAT,pluse_count
movff TBLPTRL,tbl_ads
movff TBLPTRH,tbl_ads+1
movff TBLPTRU,tbl_ads+2
clrf num
bsf PIE1,TMR2IE
bsf INTCON,PEIE
bsf INTCON,GIE
goto $
inth ; 高位割り込み
bcf PIR1,TMR2IF ; 割り込みフラグクリア
decf pluse_count
bz inth_pluse_count_zero
movlw 1
cpfseq pluse_count
retfie FAST ; pluse_count!=1 && pluse_count!=0 同一パルス繰返し中
; 次のhi期間を設定する pluse_count==1
movlw TBL_MAX-1
cpfseq num
bra inth_non_zero_pluse_count
; 次の期間がnum=0のケース
LDTBLPTR TBL+1
bra inth_ccpcon_L1
inth_non_zero_pluse_count
movff tbl_ads,TBLPTRL
movff tbl_ads+1,TBLPTRH
movff tbl_ads+2,TBLPTRU
tblrd *+
inth_ccpcon_L1
tblrd *+
movff TABLAT,CCPR3L
movlw b'11001111'
andwf CCP3CON
tblrd *+
movf TABLAT,W
iorwf CCP3CON
retfie FAST
inth_pluse_count_zero ; pluse_count==0 次のパルス設定 周期
incf num
movlw TBL_MAX
cpfseq num
bra inth_non_num_max
; numがMAXなので0に戻す
clrf num
clrf num+1
LDTBLPTR TBL
bsf SYNCTRG_ADS,SYNCTRG_BIT;オシロスコープ用の立ち上がりトリガを作成
bra inth_L2
inth_non_num_max
bcf SYNCTRG_ADS,SYNCTRG_BIT;オシロスコープ用の立ち上がりトリガを作成
movff tbl_ads,TBLPTRL
movff tbl_ads+1,TBLPTRH
movff tbl_ads+2,TBLPTRU
inth_L2
tblrd *+
movff TABLAT,PR2
tblrd *+
tblrd *+
tblrd *+
movff TABLAT,pluse_count
movff TBLPTRL,tbl_ads
movff TBLPTRH,tbl_ads+1
movff TBLPTRU,tbl_ads+2
movlw 2
cpfslt pluse_count
retfie FAST
; pluse_count<2
movlw TBL_MAX-1
cpfseq num
bra num_max_non
LDTBLPTR TBL
num_max_non
tblrd *+
bra inth_ccpcon_L1
CLK EQU d'16' ; 16MHz
PLUSE_TIM MACRO PR,CPP,X,PRX
; PR2 CCPR3L CCP3CON(5-4bit) 回数
#IF 1
#IF PRX==16
DB (PR/d'1000'*CLK/16) ,(CPP/d'1000'*CLK/16*4)/4
DB ((CPP/d'1000'*CLK/16*4) & b'11')<<4,X
#ENDIF
#IF PRX==4
#ENDIF
DB (PR/d'1000'*CLK/4) ,(CPP/d'1000'*CLK/4*4)/4
DB ((CPP/d'1000'*CLK/4*4) & b'11')<<4,X
#IF 1
#ENDIF
#IF PRX==1
DB (PR/d'1000'*CLK/1) ,(CPP/d'1000'*CLK/1*4)/4
DB ((CPP/d'1000'*CLK/1*4) & b'11')<<4,X
#ENDIF
#ENDIF
ENDM
TBL
; 周期ns hi期間ns 回数 プリスケラ
PLUSE_TIM d'60000',d'20000',1,4
PLUSE_TIM d'40000',d'10000',1,4
PLUSE_TIM d'20000', d'4000',1,4
PLUSE_TIM d'40000', d'8000',1,4
END
Copyright (C) 2012 山本ワールド All Rights Reserved.