概要

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