JH7UBCブログ

アマチュア無線 電子工作 家庭菜園など趣味のブログです

MPL AB アセンブラ PIC16F1827 LED点滅

2024-11-12 20:30:18 | MPLAB アセンブラ
 PICの品種を8bitPICの定番的存在のPIC16F1827に変えて、アセンブラの勉強を進めていきます。
 環境は、MPLAB IDE v9.82, MPASM v5.51, PICKit3と同じです。

 PIC16F1シリーズは、PIC16Fシリーズに比べ、機能が大幅に拡大され、強化されています。

 PIC16F1827のスペックは
 Program Memory       4K word
 SRAM       384 byte
 EEPROM     256byte
 I/O        16
 ADC(12bit)      12
 CapSense     12
 Comperator      2
 Timer(8/16bit)    4/1
 EUSART      1
 MSSP        2
 ECCP(Full Bridge)   1
 ECCP(Half Bridge)  1
 CCP         2
 となり、SRLatch機能が加わりました。
 クロックは、31KHzから32MHzと広範囲で動作します。

 まず、最初に恒例のLチカ(LED点滅)をやってみましょう。

 回路図です。ICSPでRB3に接続したLEDを点滅させてみます。

 

 プログラムです。クロックは、内蔵の4MHzとしました。
 PIC16F1827のCONFIGレジスタは、CONFIG1とCONFIG2があり、それぞれ設定します。
 SFRのバンクは拡大されていますので、BANKSELでで指定します。
 出力はoutput latchのLATxレジスタにセットします。

----------------------------------------------------
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; PIC16F1827 LED BLINK
; 2024.11.12
; JH7UBC Keiji Hata
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

              LIST      P=PIC16F1827
              INCLUDE           P16F1827.INC
              
              __CONFIG _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_OFF & _MCLRE_ON & _CP_OFF & _CPD_OFF & _BOREN_OFF & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF
     __CONFIG _CONFIG2, _WRT_OFF & _PLLEN_OFF & _STVREN_OFF & _BORV_19 & _LVP_OFF

              CBLOCK             020h
              CNT1ms
              CNT250ms
              ENDC

SETUP
              BANKSEL           OSCCON
              MOVLW              b'01101000'         ;PLLなし、4MHz,Fosc
              MOVWF              OSCCON
              BANKSEL           ANSELA
              CLRF     ANSELA                            ;AN0-AN4使用しない
              CLRF     ANSELB                            ;AN5-AN11使用しない
              BANKSEL           TRISA
              CLRF     TRISA   ;PORTAは全て出力(RA5は入力)
              CLRF     TRISB   ;PORTBは全て出力
              BANKSEL           LATA
              CLRF     LATA    ;PORTAクリア
              CLRF     LATB    ;PORTBクリア
              
MAIN
              BANKSEL           LATB
              BSF                      LATB,3
              CALL     LOOP250ms
              CALL     LOOP250ms
              BCF                     LATB,3
              CALL     LOOP250ms
              CALL     LOOP250ms
              GOTO   MAIN

LOOP250ms
              MOVLW              0FAh      ;0FAh=250
              MOVWF              CNT250ms
LOOP2
              CALL     LOOP1ms
              DECFSZ              CNT250ms
              GOTO   LOOP2
              RETURN             
              
LOOP1ms
              MOVLW              0F9h      ;0F9h=249
              MOVWF              CNT1ms
LOOP1
              NOP
              DECFSZ              CNT1ms,F
              GOTO   LOOP1
              RETURN
             
              END
----------------------------------------------------

 ブレッドボードです。


 アセンブルの後、PICKit3でプログラムをPICに書き込みましたが、なかなかPICの新種を確認しませんでした。USBを何度か抜き差ししてようやく認識しました。MPLABとPICKit3は、何とも相性が悪いです。

 参考までに、MPLAB X + XC8 + MCCでプログラミングするとMCCで各種設定をしますので、ソースリストが次のように、非常に簡単になります。
--------------------------------------------------------
#include "mcc_generated_files/system/system.h"

int main(void)
{
     SYSTEM_Initialize();

    while(1)
    {
         LATB3 = 1;
     __delay_ms(500);
         LATB3 = 0;
     __delay_ms(500);
     }    
}
--------------------------------------------------------

 各種設定が、ブラックボックスになってしまうのですが、プログラム開発はアセンブラとは比較にならないほど速くなりますね。

 ただ、アセンブラでのプログラミングは、クイズを解くような面白さがあります。マイコン遊びのじいさんには、良い頭の体操です。(笑)

11月13日追記
 推測なのですが、MPLAB IDEには、PIC16F1827用のファームウェアがなかったのかも知れません。MPLAB X IDEでは、すんなり書き込みができました。その時にファームウェアがダウンロードされ、その後、MPLABで書き込みをしたらPIC16F1827を認識して、書き込みができのではないかと思いました。

MPLABアセンブラ PIC16F648A 7セグメントLED表示テスト

2024-11-10 18:47:43 | MPLAB アセンブラ
 MPLAB IDE v8.92 MPASM v5.51 PICKit3の環境で、PIC16F648Aで7セグメントLEDの表示テストをやってみます。

 PICが開発された時代、表示器の主流はLEDでした。特に数字を表示するには7セグメントが用いられました。(PIC16F648AにはI2C機能は搭載されていません)

 今回は、カソードコモンの3桁7セグメントLEDをを使い、ダイナミック点灯表示します。

 回路図です。a~gセグメントは、RB0~RB6に接続します。カソード1Y~3YはRA0~RA2に接続します。今回DPは接続していません。カソードをON/OFFするのは、デジタルトランジスタDTC114です。電流制限抵抗は、1KΩと少し大きくして輝度を抑えています。


 プログラムです。数値020h=128を表示します。ダイナミック点灯の間隔は、ちらつきが目立たない程度で5ms間隔としました。
 クロックは内蔵の4MHzです。
----------------------------------------------------------
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; PIC16F648A 7seg LED TEST
; 2024.11.10
; JH7UBC Keiji Hata
;;;;;;;;;;;;;;;;;;;;;;;;;;;;

              LIST      P=PIC16F648A
              INCLUDE           P16F648A.INC

              __CONFIG _INTOSC_OSC_NOCLKOUT & _CP_OFF & _CPD_OFF & _WDTE_OFF & _PWRTE_ON & _BOREN_OFF & _LVP_OFF & _MCLRE_OFF
              ERRORLEVEL    -302
              
;レジスタ
              CBLOCK             020h
              CNT_1ms
              CNT_5ms
              SHIFT
              BYTE0
              DIGIT12
              DIGIT34
              WORK1
              TEMP
              ENDC

;入出力設定           
              BANKSEL           TRISA
              CLRF     TRISA                 ;PORTAはすべて出力、ただし、RA5は入力
              CLRF     TRISB                 ;PORTBはすべて出力
              BANKSEL           CMCON
              MOVLW              b'00000111'
              MOVWF              CMCON                            ;コンパレータOFF
              
;データセットとBCD変換
              MOVLW              080h
              MOVWF              BYTE0
              CALL     CONV_BCD

;データ表示          
MAIN
              BANKSEL           PORTB
              MOVFW              DIGIT34
              ANDLW 0Fh
              CALL     BCD2LED
              MOVWF              PORTB
              MOVLW              b'00000001'
              MOVWF              PORTA
              CALL     LOOP5mS
              MOVFW              DIGIT12
              MOVWF              WORK1
              MOVWF              TEMP
              SWAPF  TEMP,W
              ANDLW 0Fh
              CALL     BCD2LED
              MOVWF              PORTB
              MOVLW              b'00000010'
              MOVWF              PORTA
              CALL     LOOP5mS
              MOVFW              WORK1
              ANDLW 0Fh
              CALL     BCD2LED
              MOVWF              PORTB
              MOVLW              b'00000100'
              MOVWF              PORTA
              CALL     LOOP5mS           
              GOTO   MAIN    
              
;5ms待つルーチン
LOOP5mS
              MOVLW              05h                      ;05h=5
              MOVWF              CNT_5ms
LOOP2
              CALL     LOOP1mS
              DECFSZ              CNT_5ms
              GOTO   LOOP2
              RETURN

;1ms待つルーチン
LOOP1mS
              MOVLW              0F9h                    ;0F9h=249
              MOVWF              CNT_1ms
LOOP1
              NOP
              DECFSZ              CNT_1ms,F
              GOTO   LOOP1
              RETURN             

;--------------------------------------------
; バイナリからBCDへの変換
;--------------------------------------------
CONV_BCD
              BCF                     STATUS,C          ;キャリーをクリア
              MOVLW               08h                     ;8ビットカウンタ
              MOVWF               SHIFT                 ;SHIFT=8 
              CLRF                   DIGIT12              ;BCDデータクリア
              CLRF                   DIGIT34
LOOP
              RLF                     BYTE0,F              ;shift  BYTE to DIGIT
              RLF                     DIGIT12,F
              RLF                     DIGIT34,F
              DECFSZ              SHIFT,F              ;end check
              GOTO                 ADJST                 ;adjust to BCD
              RETURN
ADJST
              MOVF                 DIGIT12,W         ;DIGIT12 adjust TO BCD
              CALL                   ADJBCD
              MOVWF              DIGIT12
              MOVF                 DIGIT34,W         ;DIGIT34 adjust to BCD
              CALL                   ADJBCD
              MOVWF              DIGIT34
              GOTO                 LOOP

;****   Each digit adjust to BCD  ****
ADJBCD
               MOVWF             WORK1               ;save
               MOVLW              3                          ;W+3
               ADDWF              WORK1,W
               MOVWF             TEMP
               BTFSC               TEMP,3               ;Test W+3>7
               MOVWF             WORK1               ;>7 then W+3 else W
               MOVLW             030h                    ;W+30
                ADDWF              WORK1,W
                MOVWF             TEMP    
               BTFSC                 TEMP,7               ;Test W+30>7*
               MOVWF               WORK1               ;>70 then W+30 else W
               MOVF                 WORK1,W
                RETURN
                            
BCD2LED
              ADDWF PCL,F

              RETLW 03Fh      ;0
              RETLW 006h      ;1
              RETLW 05Bh      ;2
              RETLW 04Fh      ;3
              RETLW 066h      ;4
              RETLW 06Dh     ;5
              RETLW 07Dh     ;6
              RETLW 007h      ;7
              RETLW 07Fh      ;8
              RETLW 06Fh      ;9
              RETLW 040h      ;a
              RETLW 040h      ;b
              RETLW 040h      ;c
              RETLW 040h      ;d
              RETLW 040h      ;e
              RETLW 040h      ;f

              END

----------------------------------------------------------

 データの数値はバイナリでBYTE0に保存します。
 このデータをBCDに変換してDIGIT12,DIGIT34に格納します。
 DIGIT12の下位4ビット、DIGIT34の上位4ビット、DIGIT34の下位4ビットの順に表示を繰り返します。
 数値データに対応したLED用のデータ取得は、BCD2LEDルーチンです。 
 PICでは、配列データから任意のデータを取得するには、このサブルーチンのようにWレジスタにデータをセットしてプログラムカウンタにWレジスタの値を加えたアドレスのデータをWレジスタにセットしてリターンするという方法がとられます。 

 ブレッドボードです。データ080h=128が表示されました。



MPLABアセンブラ PIC16F648A タイマー割り込みテスト

2024-11-04 15:22:29 | MPLAB アセンブラ
  MPLAB IDE v8.92 MPASM v5.51 PICKit3の環境で、PIC16F648Aのタイマー割り込みの使い方を勉強します。 

 PIC16F648Aは、8bitタイマーを2個(TMR0とTMR2)と16bitタイマー1個(TMR1)持っています。今回は、TMR2を使ってなるべく正確な1秒を発生させて、LEDを点滅させてみます。

 正確性を上げるためには、外部のクリスタルオシレータからクロックを供給します。今回は20MHzのクリスタルオシレータ(SG-8002)を使い、TMR2のオーバーフロー割り込みを利用して1秒を発生させます。(正確な1秒を発生させることができれば、周波数カウンタや時計などに利用することができます。)

 回路図です。



 今回もICSPでテストします。クリスタルオシレータは、RA7に接続します。RB0に接続したLEDを1秒ごとに点滅させます。

 外部クロックを利用する場合、__CONFIGには、_EXTCLK_OSCと記載します。他の設定は、これまでと同じです。

 TMR2のブロックダイアグラムです。TMR2はPWMにも利用されますので、このような形になっています。

 Prescalerは 1:16,Postscalerは1:1とします。
 Fosc=20MHz=20000000Hzですので、Prescalerを通過すると20MHz/4=5MHz=5000000Hzが、5000000/16=312500Hz(周期3.2us)となり、TMR2に供給されます。

 TMR2は8BITですから、さらに256分の1されます。Postscalerは、1:1ですので、312500/256=1220.703125Hz、つまり1秒間に約1220回割り込みが発生します。周期にすると3.2us×256=819.2usごとに1回の割り込みが発生します。割り込み回数をカウントするカウンタを設定して、1220回または1221回カウントすれば良いことになります。

 時間の精度を上げるために更に工夫します。カウンタ初期値を1221とし、割り込みがあるたびにデクリメントします。3.2us周期の割り込みですから、カウンタが0になった時、時間経過は1221×819.2=1000243.2us=1.0002432sとなり、1秒を超えてしまいます。そこでTMR2に256から、243.2us/3.2=76を引いた値、256-76=180をセットしておくことにより、最初の割り込みの時に243.2us早く割り込みを発生させます。これでカウンタが0になった時に、正確な1秒を得ることができます。

 各レジスタの設定です。
TMR21のPrescalerとPostscalerの設定は、T2CONレジスタで行います。

 Prescalerの設定は、T2CKPS1とT2CKPS0で行い、1:16の場合は、1Xです。(Xは0でも1でもよい)
 Postscalerの設定は、TOUTPS3~TOUTPS0で行い、1:1の場合は、0000です。
 
 割り込み関係設定をします。PIE1レジスタのbit1 TMR2IEを1として、TMR2への割り込みを許可します。


 また、全割り込み、汎用割り込みをINTCONレジスタのGIEとPEIEを1にして割り込みを有効にします。



 割り込みが発生した時は、PIR1レジスタのTMR2IFが1になります。



 プログラムです。
 割り込みが発生した時の入り口は0X04番地です。
 割り込み処理ルーチンで、最初にWレジスタとSTATUSレジスタの内容を待機させ、最後に復帰させます。割り込みフラッグTMR2IFは最初にクリアしておきます。
-----------------------------------------------
              LIST      P=PIC16F648A
              INCLUDE           P16F648A.INC
              
              __CONFIG _EXTCLK_OSC & _CP_OFF & _CPD_OFF & _WDTE_OFF & _PWRTE_ON & _BOREN_OFF & _LVP_OFF & _MCLRE_OFF
              ERRORLEVEL -302

;レジスタ
              CBLOCK             020h
              CNTH
              CNTL
              SAVE_W
              SAVE_ST
              ENDC
              
              ORG      0x00                    ;電源ON,RESET入口
              GOTO   SETUP
              
              ORG      0x04                    ;割り込み時の入口
INTR
;WレジスタとSTATUSレジスタの内容を保存
              MOVWF              SAVE_W
              SWAPF  STATUS,W
              MOVWF              SAVE_ST
              
              BANKSEL           PIR1
              BCF                     PIR1,TMR2IF      ;TMR2割り込みフラッグクリア
              DECFSZ              CNTL
              GOTO   INTEXIT                                         ;COUNTERL!=0なら割り込み処理終了
              MOVFW              CNTH
              IORLW  00h
              BTFSC   STATUS,Z                         ;ゼロでないならスキップ
              GOTO   LEDTOGGLE
              DECF    CNTH,F
              GOTO   INTEXIT
              
LEDTOGGLE
              BANKSEL PORTB
              BTFSS   PORTB,0
              GOTO   LED_ON
LED_OFF
              BCF                     PORTB,0                          ;LED OFF
              GOTO   TOGGLE_END
LED_ON
              BSF                      PORTB,0                          ;LED ON
TOGGLE_END

;TMR2に初期値セット
              BANKSEL           TMR2
              MOVLW              0B4h                    ;0B4h=180
              MOVWF              TMR2                  ;TMR2初期値セット
;COUNTERに1221=04C5hをセット          
              MOVLW              04h
              MOVWF              CNTH
              MOVLW              0C5h
              MOVWF              CNTL

INTEXIT
;STATUSレジスタとWレジスタの内容を復帰
              SWAPF  SAVE_ST,W
              MOVWF              STATUS
              SWAPF  SAVE_W,F
              SWAPF  SAVE_W,W

              RETFIE
              
SETUP
;入出力設定
              BANKSEL           TRISA
              CLRF     TRISA                 ;PORTAは全て出力(RA5は入力に設定される)
              CLRF     TRISB                 ;PORTBは全て出力
              BANKSEL           CMCON
              MOVLW              07h
              MOVWF              CMCON                            ;コンパレータは使わない
              BANKSEL           PORTB
              CLRF     PORTB
              
;TMR2設定
              BANKSEL           T2CON
              MOVLW              B'00000110'        ;
              MOVWF              T2CON               ;postscalere 1:1,prescaler 1:16,TMR2ON
              BANKSEL           PIE1
              BSF                      PIE1,TMR2IE      ;TIMER2割り込み許可
;割り込み設定
              BANKSEL INTCON
              BSF                      INTCON,GIE                    ;全割り込み許可
              BSF                      INTCON,PEIE                  ;汎用割り込み許可
              
MAIN
              GOTO   MAIN

              END
----------------------------------------------- 

 ブレッドボードです。LEDが1秒ごとに点灯、消灯を繰り返します。


 クリスタルオシレータの精度やプログラムにより、数us程度の誤差がでると思います。周波数カウンタなどのタイムベースに使う場合は、更に誤差を少なくする工夫が必要になります。

MPLABアセンブラ PIC16F648A USARTテスト

2024-10-29 19:22:30 | MPLAB アセンブラ
 MPLAB IDE v8.92 MPASM v5.51 PICKit3の環境で、PIC16F648AのUSART(Universal Synchronous Asynchronous Receiver Transmitter)の使い方を勉強します。今回は、PICとパソコンの間で通信テストをします。

 回路図です。今回もICSPでテストを行います。PIC16F648AのUSARTの入出力は、入力RXが7ピン(RB1)、出力TXが8ピン(RB2)に設定されています。RX,TXとも入力に設定します。ここにUSBシリアル変換モジュールFT234を接続します。FT234の入出力は3.3Vですが、入力は5Vトレラント(耐性)なので、直接接続しても大丈夫です。


 パソコン側は通信ソフトTeraTermを使います。SWを押したら文字「Hello World!」を送出するプログラムを組みます。

 PICとパソコンの間の通信プロトコルを決めます。非同期モードで、通信速度は9600bpsとします。これらの設定は、TXSTAとRCSTAレジスタで行います。
 まず、TXSTAレジスタでは、bit4のSYNCはデフォルト0(非同期),bit2のBRGHは1(高速モード)とし、bit5のTXENは1(送信可)とします。TXSTA=b'00100100'=024h


 次にRCSTAレジスタは、bit7のSPENは1(シリアル)とし、bit4のCRENは1(継続受信可)とします。RCSTA=b'10010000'=090h

 通信速度(Baud Rate)の設定は、SPBRGで行います。
 BRGH=1の時は、次の式で設定値xを計算します。
 Baud Rate=Fosc/16(x+1)
 x = Fosc/(16*Baud Rate) -1
 クロック周波数Fosc=4MHz=4000000Hz
 Baud Rate = 9600bps
 とすると
 x=4000000/(16*9600) - 1 = 25 = 019h
 となり、エラーは0.16%です。

 プログラムです。PICのプログラムでやっかいなのが、SFRのBANK指定です。PIC16F648Aの場合、BANK0からBANK3ですので、それほどではありませんが、BANKSELというマクロ命令を使うとSFRに対するBANKを自動的に設定してくれます。
 ERRORLEVEL -302は、エラー番号302のエラー表示をしないようにするマクロ命令です。

-----------------------------------------------------
              LIST      P=PIC16F648A
              INCLUDE           P16F648A.INC
              
              __CONFIG _INTOSC_OSC_NOCLKOUT & _CP_OFF & _CPD_OFF & _WDTE_OFF & _PWRTE_ON & _BOREN_OFF & _LVP_OFF & _MCLRE_OFF
            ERRORLEVEL -302
;入出力設定
              BANKSEL           TRISA
              MOVLW              b'00100001'
              MOVWF              TRISA                 ;RA0とRA5は入力、他は出力
              MOVLW              b'00010110'
              MOVWF              TRISB                 ;RB1,RB2は入力、他は出力
              BANKSEL           CMCON
              MOVLW              b'00000111'
              MOVWF              CMCON                            ;コンパレータOFF
              
;USART設定
              BANKSEL           TXSTA
              MOVLW              b'00100100'
              MOVWF              TXSTA                ;非同期モード、高速通信モード
              MOVLW              019h                    ;
              MOVWF              SPBRG                ;4MHz,9600bps
              BANKSEL           RCSTA
              MOVLW              090h
              MOVWF              RCSTA                ;受信可、非同期モード
              
MAIN
              BANKSEL           PORTA
              BTFSC   PORTA,0                          ;RA0=0ならスキップ
              GOTO   MAIN
              MOVLW              "H"
              CALL     SENDCHR
              MOVLW              "e"
              CALL     SENDCHR
              MOVLW              "l"
              CALL     SENDCHR
              MOVLW              "l"
              CALL     SENDCHR
              MOVLW              "o"
              CALL     SENDCHR
              MOVLW              " "
              CALL     SENDCHR
              MOVLW              "W"
              CALL     SENDCHR
              MOVLW              "o"
              CALL     SENDCHR
              MOVLW              "r"
              CALL     SENDCHR
              MOVLW              "l"
              CALL     SENDCHR
              MOVLW              "d"
              CALL     SENDCHR
              MOVLW              "!"
              CALL     SENDCHR
              MOVLW              " "
              CALL     SENDCHR
              
              GOTO   MAIN
              
SENDCHR
              BANKSEL           TXSTA
              BTFSS   TXSTA,TRMT     ;送信可能かチェック(1:可 0:禁止)
              GOTO   $-1
              BANKSEL           TXREG
              MOVWF              TXREG
              RETURN
              
              END
-----------------------------------------------------

ブレッドボードです。ICSPで書き込みます。


 SWを押すとTeraTermに「Hello World!」がSWを押している間表示されました。


 これで送信機能は確認できました。次に受信機能を確認します。同じ回路で、Tera Termから送信された文字を受信して送り返すエコーバックをやってみます。
 プログラムです。
----------------------------------------------------
              LIST      P=PIC16F648A
              INCLUDE P16F648A.INC
              __CONFIG _INTOSC_OSC_NOCLKOUT & _CP_OFF & _CPD_OFF & _WDTE_OFF & _PWRTE_ON & _BOREN_OFF & _LVP_OFF & _MCLRE_OFF
              ERRORLEVEL    -302
              
;入出力設定
              BANKSEL           TRISA
              CLRF     TRISA                 ;PORTAはすべて出力、ただし、RA5は入力
              MOVLW              b'00010110'
              MOVWF              TRISB                 ;RB1,RB2は入力、他は出力
              BANKSEL           CMCON
              MOVLW              b'00000111'
              MOVWF              CMCON                            ;コンパレータOFF

;USART設定
              BANKSEL           TXSTA
              MOVLW              b'00100100'
              MOVWF              TXSTA                ;非同期モード、高速通信モード
              MOVLW              019h                    ;
              MOVWF              SPBRG                ;4MHz,9600bps
              BANKSEL           RCSTA
              MOVLW              090h
              MOVWF              RCSTA                ;受信可、非同期モード

MAIN
              CALL     GETCHR                           ;1文字受信
              CALL     SENDCHR                        ;1文字送信
              GOTO   MAIN
              
;1文字受信
GETCHR
              BANKSEL           PIR1
              BTFSS   PIR1,RCIF           ;RCIF=1ならスキップ
              GOTO   $-1
              BANKSEL           RCREG
              MOVFW              RCREG
              RETURN
              
;1文字送信
SENDCHR
              BANKSEL           TXSTA
              BTFSS   TXSTA,TRMT     ;送信可能かチェック(1:可 0:禁止)
              GOTO   $-1
              BANKSEL           TXREG
              MOVWF              TXREG
              RETURN
              
              END
----------------------------------------------------


パソコンのキーボードを押した文字がPICに送信され、PICから送り出された文字がTera Termに表示されます。


MPLABアセンブラ PIC16F648A PWM テスト

2024-10-22 16:00:06 | MPLAB アセンブラ
 MPLAB IDE v8.92 MPASM v5.51 PICKit3の環境で、PIC16F648AのPWM(Pulse Width Modulation)の使い方を勉強します。

 このPICでPWMを出力するには、CCP1モジュールを使います。PWMのブロックダイアグラムです。(PIC16F648Aの取説より)


 PWM信号発生の原理は、私のホームページ(JH7UBCホームページ)のこちらのページで説明していますので、参照してください。

 PWM信号は下の図のようにPWM PeriodとDuty Cycleで決まり、それぞれ下の式のように、PR2,Tosc,TMR2 prescale value,CCP1RL,CCP1CON<5:4>で計算できます。



 例として、1000Hz,デューティ比50%のPWM信号を発生させてみます。
クロックは、内蔵クロック4MHz(4000000Hz)とし、TMR2 prescale valueは4(1:4)とします。

 以上の値でPR2の値を計算すると
 PR2 =( 4000000 / 1000 ・4・4) - 1 = 249
 デューティ比50%なので、CCPRL1=(RP2+1)・0.5=125 となります。

 これらの値でプログラミングするわけですが、それぞれのレジスタ(SFR)に値をセットするときに注意しなければならないのがBANK切り替えです。
 PIC16F648AのBANKマップは次のようになっていますので注意します。


 プログラムです。
------------------------------------------
              LIST      P=PIC16F648A
              INCLUDE           P16F648A.INC
              
              __CONFIG _INTOSC_OSC_NOCLKOUT & _CP_OFF & _CPD_OFF & _WDTE_OFF & _PWRTE_ON & _BOREN_OFF & _LVP_OFF & _MCLRE_OFF
              
;入出力設定
      BSF                      STATUS,RP0      ;BANK1
     CLRF            TRISA                 ;PORTAはすべて出力、ただし、RA5は入力
     CLRF            TRISB                 ;PORTBはすべて出力
     BCF                            STATUS,RP0      ;BANK0
     MOVLW       b'00000111'
     MOVWF       CMCON                            ;コンパレータOFF
;PWM設定
              MOVLW              b'00001100'
              MOVWF              CCP1CON                         ;PWMモード
              MOVLW              b'00000101'
              MOVWF              T2CON               ;TMR2 ON,プリスケーラ1:4      
              BSF                      STATUS,RP0      ;BANK1               
              MOVLW              0F9h                    ;249
              MOVWF              PR2

;カウンタ、レジスタ初期値
              BCF                     STATUS,RP0      ;BANK0
              CLRF     CCPR1L
              CLRF     CCPR1H
              CLRF     TMR2
                            
;デューティサイクルセット
              MOVLW              07Dh                    ;デューティ比50% 250/2=125=07Dh
              MOVWF              CCPR1L 

LOOP
              GOTO LOOP
     END
------------------------------------------
 テストした回路図です。



 アセンブルしてPICにプログラムを書き込むと、PWM信号は、RB3から出力されます。

 出力されたPWM信号をPicoScopeで見てみました。約1000Hz(周期約1ms)でデューティ比50%の信号が確かに出力されました。


 周波数を測定してみました。1028Hzで若干高めの周波数が出力されました。内部クロックの誤差と思われます。


 CCPR1Lの値をPR2の1/4(25%)にした時のPWM波形です。


 デューティ比25%のPWM信号が出力されました。

 次に、500Hz、デューティ比50%の信号を発生させてみましょう。
 TMR2のプリスケーラ値が4のままですと、PR2の値が255を超えてしまいますので、プリスケーラ値を16とします。プリスケーラ値を決めるのは、T2CONレジスタのbit1とbit0で、これを11とします。つまり
  MOVWL    b'00000111'
       MOVWF    T2CON
とします。PR2とCCP1RLの値は
 PR2 =( 4000000 / 500 ・4・16) - 1 = 124
 CCP1RL = (PR2+1)・0.5 = 62 となります。



 512HzのPWMが出力されました。