goo blog サービス終了のお知らせ 

JH7UBCブログ

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

MPLABアセンブラ PIC16F1827 AQM0802A表示テスト

2025-01-27 20:55:18 | MPLAB アセンブラ
 久しぶりにMPLABアセンブラによるPICのプログラミングの勉強を再開します。
 MPLAB IDE v9.82, MPASM v5.51, PICKit3の環境で、PIC16F1827のI2C LCD表示器AQM0802Aの表示テストをします。 

 回路図です。AQM0802Aは秋月電子のモジュールを使います。このモジュールにはI2Cプルアップ抵抗が内蔵されています。ICSPでプログラムの書き込みテストをします。電源は、PICKit3から3.3Vを供給します。


 PIC16F1827はMSSPモジュールを2つ持っています。今回はMSSP1を使います。
 クロックは、4MHzとします。
 入出力設定は、I2CのSDAとSCLになるRB1とRB4は、入力に他は出力に設定します。
 I2Cの設定をします。
 まず、SSP1CON1レジスタのbit5 SSP1EN=1,bit3:bit0=1000としてI2C Master Modeに設定します。


 次に、SSP1STAレジスタで、I2Cの速度を設定します。bit7のSMP=1として、I2C Master Modeの時の標準速度100KHzに設定します。
 

 この速度にするために、SSP1ADDレジスタの値を設定します。
 計算式は、ADD=Fosc/(4*clock) - 1
 Fosc=4000000hZ(4MHz),clock=100000Hz(100KHz)とすると
 ADD=4000000/(4*100000) -1 =9 となり、SSP1ADDに9を設定します。


 スタートコンディションとストップコンディションは、SSP1CON2で設定します。

 今回は、単純化して、I2C slaveデバイスからのACKは確認しません。また、slaveデバイスは1個のため、信号の衝突回避もしていません。
 
プログラムです。
----------------------------------
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; PIC16F1827 AQM0802A TEST
; 2025.1.27
; JH7UBC Keiji Hata
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

              LIST      P=PIC16F1827
              INCLUDE P16F1827.INC
              
              __CONFIG _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_ON & _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
              ERRORLEVEL    -302    ;ERRORメッセージ302を表示しない
              
              CBLOCK             020h
              COMMAND
              CHAR
              CNT1ms
              CNTms
              X
              Y
              ENDC
              
;定数定義
              #DEFINE             LCDADD            07Ch      ;AQM0802AのI2Cアドレス
              #DEFINE             LINE1    080h
              #DEFINE             LINE2    0C0h
                            
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                               ;RA5は入力、他は出力
              MOVLW              b'00010010'                       ;RB1とRB4は入力、他は出力
              MOVWF              TRISB

;I2C初期化
              BANKSEL           SSP1CON1
              MOVLW              b'00101000'                       ;SSPEN=1,I2C Master Mode
              MOVWF              SSP1CON1
              BANKSEL           SSP1STAT
              BSF                      SSP1STAT,SMP  ;標準速度モード(100KHz)
              BANKSEL           SSP1ADD
              MOVLW              09h                                                  ;Fosc/(4*Clock)-1,Clock=100KHz,Fosc=4MHz
              MOVWF              SSP1ADD

;LCD初期化
              MOVLW              028h                                                ;028h=40
              CALL     DELAY_ms                        ;40ms wait
              MOVLW              038h
              CALL     WRITE_COMMAND        ;8bit,2line
              MOVLW              039h
              CALL     WRITE_COMMAND        ;IS=1,extention mode set
              MOVLW              014h
              CALL     WRITE_COMMAND        ;Internal OSC Frequency
              MOVLW              070h
              CALL     WRITE_COMMAND        ;Contrast set
              MOVLW              056h
              CALL     WRITE_COMMAND        ;Power/ICON/Contrast Control
              MOVLW              06Ch
              CALL     WRITE_COMMAND        ;Follower control
              MOVLW              0C8h                                  ;0C8=200
              CALL     DELAY_ms                        ;200ms wait
              MOVLW              038h
              CALL     WRITE_COMMAND        ;IS=0,extention mode cancel
              MOVLW              0Ch
              CALL     WRITE_COMMAND        ;Display ON
              MOVLW              01h
              CALL     WRITE_COMMAND        ;Clear Display
              MOVLW              2
              CALL     DELAY_ms                        ;2ms wait

MAIN
              MOVLW              'J'
              CALL     WRITE_CHARACTER
              MOVLW              'H'
              CALL     WRITE_CHARACTER
              MOVLW              '7'
              CALL     WRITE_CHARACTER
              MOVLW              'U'
              CALL     WRITE_CHARACTER
              MOVLW              'B'
              CALL     WRITE_CHARACTER
              MOVLW              'C'
              CALL     WRITE_CHARACTER
              BANKSEL X
              MOVLW              2            ;CURSORをX=2,Y=1に移動
              MOVWF              X
              MOVLW              1
              MOVWF              Y
              CALL     CURSOR_XY
              MOVLW              'H'
              CALL     WRITE_CHARACTER
              MOVLW              'e'
              CALL     WRITE_CHARACTER
              MOVLW              'l'
              CALL     WRITE_CHARACTER
              MOVLW              'l'
              CALL     WRITE_CHARACTER
              MOVLW              'o'
              CALL     WRITE_CHARACTER
LOOP
              GOTO   LOOP
              
              GOTO   MAIN        
              
;LCDにコマンドを送る
WRITE_COMMAND
              BANKSEL           COMMAND
              MOVWF              COMMAND
              CALL     I2C_START
              MOVLW              LCDADD
              CALL     I2C_WRITE
              MOVLW              00h
              CALL     I2C_WRITE
              MOVFW              COMMAND
              CALL     I2C_WRITE
              CALL     I2C_STOP           
              RETURN
              
;LCDに文字を送る
WRITE_CHARACTER
              BANKSEL           CHAR
              MOVWF              CHAR
              CALL     I2C_START
              MOVLW              LCDADD
              CALL     I2C_WRITE
              MOVLW              40h
              CALL     I2C_WRITE
              MOVFW              CHAR
              CALL     I2C_WRITE
              CALL     I2C_STOP           
              RETURN

;Clear Display
CLEAR_DISPLAY
              MOVLW              01h
              CALL     WRITE_COMMAND
              MOVLW              2
              CALL     DELAY_ms
              RETURN
              
;Return Home
HOME_DISPLAY
              MOVLW              02h
              CALL     WRITE_COMMAND
              MOVLW              2
              CALL     DELAY_ms
              RETURN
              
;カーソルをX,Yにセット
CURSOR_XY
              BANKSEL X
              MOVFW              Y
              IORLW  00h
              BTFSS   W,Z                     ;Y=0ならYOへ Y!=0ならY1へ
              GOTO   Y1
Y0
              MOVLW              LINE1
              ADDWF X,W
              CALL     WRITE_COMMAND
              RETURN
Y1
              MOVLW              LINE2
              ADDWF X,W
              CALL     WRITE_COMMAND
              RETURN
              
;スタートコンディション
I2C_START
              BANKSEL           SSP1CON2
              BSF                      SSP1CON2,SEN
              BTFSC   SSP1CON2,SEN
              GOTO   $-1
              RETURN
              
;ストップコンディション
I2C_STOP
              BANKSEL           PIR1
              BCF                     PIR1,SSP1IF
              BANKSEL           SSP1CON2
              BSF                      SSP1CON2,PEN
              BTFSC   SSP1CON2,PEN
              GOTO   $-1
              BANKSEL           PIR1
              BCF                     PIR1,SSP1IF
              RETURN

;I2Cに1BYTE送信
I2C_WRITE
              BANKSEL           PIR1
              BCF                     PIR1,SSP1IF
              BANKSEL           SSP1BUF
              MOVWF              SSP1BUF
              BANKSEL           PIR1
              BTFSS   PIR1,SSP1IF
              GOTO   $-1
              RETURN
              
;任意のms待つ WREGに1から255をセットしてコールする
DELAY_ms
              BANKSEL           CNTms
              MOVWF              CNTms
LOOP2
              CALL     LOOP1ms
              DECFSZ              CNTms
              GOTO   LOOP2
              RETURN  
              
;1ms待つ
LOOP1ms
              BANKSEL           CNT1ms
              MOVLW              0F9h      ;0F9h=249
              MOVWF              CNT1ms
LOOP1
              NOP
              DECFSZ              CNT1ms,F
              GOTO   LOOP1
              RETURN
              
              END
----------------------------------

 ブレッドボードです。


 1行目に「JH7UBC」2行目(X=2,Y=1)に「Hello」が表示されました。

MPLABアセンブラ PIC16F1827 PWMテスト

2024-12-03 07:36:08 | MPLAB アセンブラ
 MPLAB IDE v9.82, MPASM v5.51, PICKit3の環境で、PIC16F1827のPWMのテストをします。

 PIC16F1827でPWM信号を発生するのは、CCP(Capture/Compare/PWM)モジュールです。この品種では、ECCP1,ECCP2,CCP3,CCP4が利用できます。なお、EがつくCCPモジュールは機能が拡張されています。

 今回は、CCP3を使い、タイマーはTMR2を使ってテストします。回路図です。ICSPでプログラミングし、電源5VはPICKit3から供給します。PWM信号はRA3(PWM3)から出力します。


 PIC16F1827でのPWM発生のしくみは、私のホームページ(JH7UBCホームページ)のこちらのページで詳しく解説しています。

 今回テストとして、PWM3で周波数500HzのPWMを発生し、DutyCycleを変化させ、RA3に接続したLEDの明るさを周期的に変化させてみます。

 CCP3でPWMに設定するには、CCP3CONレジスタのbit3:bit2(CCP3M3:CCPM2)を11の設定します。他のbitは0でOKです。説明書では、下のようにCCPXCONとなっています。Xはモジュールの番号1,2,3,4です。

 つまり、CCP3CON=b'00001100'とします。

 次に、CCPTMRSレジスタで、CCP3でTMR2を使うという設定をします。
 bit5:bit4(C3TSEL1:C3TSEL0)を00とします。他のbitは適当でよいの、すべて0にします。

 つまり、CCPTMRS=b'00000000'とします。

 PWMの周波数(周期)とDuty比(DutyCycle)を設定するのはPR2レジスタの値とCCPR3L+CCP3CON<5:4>で、次のような式で計算されます。



 今回、PICのクロックは内蔵の4MHzとしますので、Tosc=1/4000000 (sec)で、TMR2のPrescaler値を16とすると500Hz(周期は1/500 (sec))を発生させるPR2の値は、
PR2=(Period/(4*Tosc*TMR2Prescale Value))-1=(1/500/(4*(1/4000000))*16)-1
  =4000000/(500*4*16) -1 =125-1=124
となります。
 Duty比は、一番下の式できまりますので、PR2=124のときは、CCPR3Lの値を0から125まで設定すれば0から100%のDuty比のPWM信号を発生することができます。

 プログラムです。DUTYの値をカウントアップするか、カウントダウンするかは、FLAGの値で決めます。10msごとにDUTYをカウントアップカウントダウンして、LEDの明るさを決めています。
-------------------------------------------------
;;;;;;;;;;;;;;;;;;;;;;;;;;
; PIC16F1827 PWM TEST
; 2024.12.3
; 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
              
              ERRORLEVEL    -302

              CBLOCK             020h
              CNT1ms
              CNT10ms
              DUTY
              FLAG
              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は全て出力

;PWM設定
              BANKSEL           CCP3CON
              MOVLW              b'00001100'         ;PWM mode
              MOVWF              CCP3CON
              BANKSEL           CCPTMRS
              MOVLW              b'00000000'         ;bit5-bit4=00,CCP3にTimer2を割り当てる
              MOVWF              CCPTMRS
              BANKSEL           PR2
              MOVLW              07Ch                    ;07Ch=124
              MOVWF              PR2                                   ;Timer2の周期を設定
              BANKSEL           T2CON
              MOVLW              b'00000110'
              MOVWF              T2CON               ;prescale 1:16 Timer2 start

;変数初期値
              BANKSEL           DUTY
              CLRF     DUTY
              MOVLW              01h
              MOVWF              FLAG

MAIN
              BANKSEL           DUTY
              MOVFW              FLAG
              XORLW 01h
              BTFSS   STATUS,Z           ;FLAG=1ならINCDUTYへ、FLAG=0ならDECDUTYへ
              GOTO   DECDUTY
              
INCDUTY
              MOVFW              DUTY
              SUBLW 07Ch                    ;W=124-W
              BTFSC   STATUS,Z           ;DUTY><124ならスキップ
              GOTO   FLAGCHG                        ;DUTY=124ならFLAGCHGへ
              INCF      DUTY                  ;DUTY=DUTY+1
              GOTO   SETDUTY
              
DECDUTY
              DECFSZ              DUTY                  ;DUTY=DUTY-1 DUTY=0になったらスキップ
              GOTO   SETDUTY
              
FLAGCHG          
              MOVFW              FLAG
              SUBLW 01h
              MOVWF              FLAG                   ;FLAG=1-FLAG
              GOTO   SETDUTY

SETDUTY
              BANKSEL           DUTY
              MOVFW              DUTY
              BANKSEL           CCPR3L
              MOVWF              CCPR3L
                            
              CALL     LOOP10ms
              GOTO   MAIN
              
LOOP10ms
              BANKSEL           CNT10ms
              MOVLW              0Ah                      ;0Ah=10
              MOVWF              CNT10ms
LOOP2
              CALL     LOOP1ms
              DECFSZ              CNT10ms
              GOTO   LOOP2
              RETURN             
              
LOOP1ms
              MOVLW              0F9h      ;0F9h=249
              MOVWF              CNT1ms
LOOP1
              NOP
              DECFSZ              CNT1ms,F
              GOTO   LOOP1
              RETURN
                            
              END
-------------------------------------------------
RA3から出力されたPWMの波形です。周期は約2ms(周波数は約500Hz)で、ヂューティ比が時間とともに変化します。



 ブレッドボードです。赤いLEDが明るくなったり暗くなったりします。左下の緑色のLEDは電源確認用です。




MPLABアセンブラ PIC16F1827 ADCテスト

2024-11-28 13:30:49 | MPLAB アセンブラ
  MPLAB IDE v9.82, MPASM v5.51, PICKit3の環境で、PIC16F1827のADCのテストをします。 

 PIC16F1827は、10bit分解能のADコンバータ(ADC)を12チャンネル持っています。今回はこのADCの使い方を勉強します。

 回路図です。電圧はVRで調整して、17番ピンのAN0(RA0)から入力して、AD変換してその値をシリアル通信で出力してTeraTermで、その値を読み取ります。今回もICSPでプログラミングし、電源(5V)はUSBシリアル変換モジュールFT-234から供給します。PICのクロックは内蔵の4MHzとします。


 AD変換の手順です。
 1 アナログ入力ピンの指定とピンの入力設定
 2 ADCのチャンネル指定とADCを有効にする。
 3 ADCの準備時間(チャージ時間)を待ち、AD変換をスタート
 4 AD変換が終わったら変換結果を取り出す。

 まず、ANSELAレジスタとANSELBレジスタでアナログピンを指定します。


 AN0を使用しますので、bit0を1にして、他のビットは0にします。
 ANSELA=b'00000001'


 AN5~AN11は使わないので、
 ANSELB=b'00000000' つまり、CLRF  ANSELB

 つぎにADCのチャンネルをADCON0レジスタで指定します。


 bit6~bit2でチャンネルを設定します。AN0の場合、CHS4-CHS0=00000
 bit0のADON=1としてADCを有効にします。

 更にADCON1でADCの各種設定をします。
 AD変換結果を右詰めでADRESHとADRESLに格納しますので、bit7のADFM=1とします。また、ADCのクロックは、Fosc=4MHzの1/4で1MHz=1usとしますので、ADCS2-ADCS0=100とします。
 ADCの負参照電圧はVss(GND)としますので、bit2のADNREF=0、正参照電圧は、Vddとしますので、ADPREF1-ADPREF0=00とします。
 以上からADCON1=b'11000000'と設定します。


 EUSARTの設定とバイナリからBCDへの変換は、これまでの記事と同じです。

 プログラムです。1秒ごとにAN0の電圧をAD変換してシリアル通信で出力します。"ADC "+変換値でTeraTermに表示されます。チャージ時間は、MAINループ内で確保できると考え、特にとっていません。
-------------------------------------------------
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; PIC16F1827 ADC TEST
; 2014.11.28
; 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
              
              ERRORLEVEL    -302

              CBLOCK             020h
              BYTE0
              BYTE1
              DIGIT12
              DIGIT34
              SHIFT
              WORK1
              TEMP
              CNT1ms
              CNT250ms
              ENDC

SETUP
;クロック設定
              BANKSEL           OSCCON
              MOVLW              b'01101000'         ;PLLなし、4MHz,Fosc
              MOVWF              OSCCON
;入出力設定
              BANKSEL           TRISA
              MOVLW              b'00000001'         ;RA0とRA5は入力、他は出力
              MOVWF              TRISA
              MOVLW              b'00000010'         ;RB1は入力、他は出力
              MOVWF              TRISB
              BANKSEL           ANSELA
              MOVLW              b'00000001'         ;AN0を使用する。AN1-AN4使用しない
              MOVWF              ANSELA
              CLRF     ANSELB                            ;AN5-AN11使用しない
;ADC関係設定
              BANKSEL ADCON0
              MOVLW              b'00000001'         ;AN0を使う。ADC Enable
              MOVWF              ADCON0
              BANKSEL           ADCON1
              MOVLW              b'11000000'         ;右詰め、クロックFosc/4=1us、Vref-=Vss、Vref+=Vdd
              MOVWF              ADCON1
 
;USART設定
;RX,TX PIN 設定
              BANKSEL           APFCON0
              BCF                     APFCON0,7        ;RXDSEL=0 RX=RB1
              BCF                     APFCON1,0        ;RXCKSEL=0 TX=RB2     
              BANKSEL           TXSTA
              MOVLW              b'00100100'
              MOVWF              TXSTA                ;非同期モード、高速通信モードBRGH=1
              BANKSEL           RCSTA
              MOVLW              090h
              MOVWF              RCSTA                ;受信可、非同期モード
              BANKSEL           BAUDCON
              BCF                     BAUDCON,3      ;BRG16=0 BRG 8bit
              MOVLW              019h                    ;019h=25
              MOVWF              SPBRGL                            ;Fosc=4MHz,Baud Rate=9600bps
              
MAIN
              MOVLW              "A"
              CALL     SENDCHR
              MOVLW              "D"
              CALL     SENDCHR
              MOVLW              "C"
              CALL     SENDCHR
              MOVLW              " "
              CALL     SENDCHR
              BANKSEL           ADCON0
              BSF       ADCON0,ADGO ;AD変換スタート
              BTFSC  ADCON0,ADGO ;変換終了まで待つ
              GOTO   $-1
              BANKSEL           ADRESL
              MOVFW              ADRESL                            ;変換結果を格納
              BANKSEL           BYTE0
              MOVWF              BYTE0
              BANKSEL           ADRESH
              MOVFW              ADRESH
              BANKSEL           BYTE1
              MOVWF              BYTE1
              CALL     CONV_BCD        ;バイナリからBCDに変換
              CALL     NUMPRINT
              CALL     LOOP250ms
              CALL     LOOP250ms
              CALL     LOOP250ms
              CALL     LOOP250ms
              GOTO   MAIN

NUMPRINT
              BANKSEL           DIGIT34
              MOVFW              DIGIT34
              MOVWF              WORK1
              MOVWF              TEMP
              SWAPF  TEMP,W
              ANDLW 0Fh                      ;DIGIT34の上位4bitを取り出す
              IORLW  30h                      ;ASCIIコードに変換
              CALL     SENDCHR
              BANKSEL           WORK1
              MOVFW              WORK1
              ANDLW 0Fh                      ;DIGIT34の下位4bitを取り出す
              IORLW  30h                      ;ASCIIコードに変換
              CALL     SENDCHR
              BANKSEL           DIGIT12
              MOVFW              DIGIT12
              MOVWF              WORK1
              MOVWF              TEMP
              SWAPF  TEMP,W
              ANDLW 0Fh                      ;DIGIT12の上位4bitを取り出す
              IORLW  30h                      ;ASCIIコードに変換
              CALL     SENDCHR
              BANKSEL           WORK1
              MOVFW              WORK1
              ANDLW 0Fh                      ;DIGIT12の下位4bitを取り出す。
              IORLW  30h                      ;ASCIIコードに変換
              CALL     SENDCHR
              MOVLW              0Dh                     ;改行コード
              CALL    SENDCHR
     MOVLW       0Ah                      ;NLコード
     CALL     SENDCHR
              RETURN
              
;1文字送信          
SENDCHR
              BANKSEL           TXSTA
              BTFSS   TXSTA,TRMT     ;送信可能かチェック(1:可 0:禁止)
              GOTO   $-1
              MOVWF              TXREG
              RETURN
              
;1文字受信
GETCHR
              BANKSEL           PIR1
              BTFSS   PIR1,RCIF           ;RCIF=1ならスキップ
              GOTO   $-1
              BANKSEL           RCREG
              MOVFW              RCREG
              RETURN
              
;--------------------------------------------
; バイナリからBCDへの変換
;--------------------------------------------
CONV_BCD
              BANKSEL           STATUS
              BCF                     STATUS,C          ;キャリーをクリア
              MOVLW              10h                                    ;16ビットカウンタ
              MOVWF              SHIFT                 ;SHIFT=8 
              CLRF     DIGIT12                           ;BCDデータクリア
              CLRF     DIGIT34
LOOP
              RLF                     BYTE0,F                            ;shift  BYTE to DIGIT
              RLF                     BYTE1,F
              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

;250msタイマー
LOOP250ms
              MOVLW              0FAh                    ;0FAh=250
              BANKSEL           CNT250ms
              MOVWF              CNT250ms
LOOP2
              CALL     LOOP1ms
              DECFSZ              CNT250ms
              GOTO   LOOP2
              RETURN

;1msループ
LOOP1ms
              MOVLW              0F9h                    ;0F9h=249
              MOVWF              CNT1ms
LOOP1
              NOP
              DECFSZ              CNT1ms,F
              GOTO   LOOP1
              RETURN             
              
              END
              
-------------------------------------------------

 ブレッドボードです。


 TeraTermの画面です。
 ボリュームを回すと電圧が変化し、電圧(0~5V)に対応したAD変換値0~1023が表示されました。


 トラブルシューティング

 最初にプログラムを書いた時は、1秒ごとに"ADC 0000"とだけ表示され、ボリュームを回しても数値が変化しませんでした。
 IDEでシミュレーションするとバイナリBCD変換がうまくいっていないことが分かりました。このルーチンは既に何度も使用して動作は確認してあります。
 はて、何が原因か?分かるまで少し時間がかかりました。
 ADRESLとADRESHの値をBYTE0とBYTE1に格納するのですが、ここがうまくいっていませんでした。これまで、BYTE0やBYTE1などのGPRに数値を書き込むときはBANK切り替えを気にしていなかったのですが、この時もBANKSEL  BYTE0などと指定しなければならなかったようです。

 ということで、SFRの時はもちろんGPRの時もBANKSELでレジスタのバンクを指定することにしまいた。これで問題なく動作するようになりました。


MPLABアセンブラ PIC16F1827 EUSARTテストその2

2024-11-17 19:21:15 | MPLAB アセンブラ
 前の記事では、PIC16F1827のEUSARTの送信をテストしました。
 今回は、文字の受信テストとその文字でLEDを点灯、消灯してみます。

 回路図です。今回もICSPでテストしますが、5Vは、FT-234から供給します。この理由は後でトラブルシューティングで説明します。



 入出力設定、EUSARTの設定は、前の記事(PIC6F1827 EUSARTテストその1)と同じです。

 プログラムです。
 TeraTermから1文字受信し、文字が"1"なら"LED ON"と送信し、LEDを点灯します。文字が"0"なら"LED OFF"と送信し、LEDを消灯します。

---------------------------------------------------
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; PIC16F1827 EUSART TEST
; 2024.11.17
; 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
              
              ERRORLEVEL    -302
              
              CBLOCK             020h
              TEMP
              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は入力)
              MOVLW              b'000000010'       ;RB1は入力、他は出力
              MOVWF              TRISB
;USART設定
;RX,TX PIN 設定
              BANKSEL           APFCON0
              BCF                     APFCON0,7        ;RXDSEL=0 RX=RB1
              BCF                     APFCON1,0        ;RXCKSEL=0 TX=RB2     
              BANKSEL           TXSTA
              MOVLW              b'00100100'
              MOVWF              TXSTA                ;非同期モード、高速通信モードBRGH=1
;             BANKSEL           RCSTA
              MOVLW              090h
              MOVWF              RCSTA                ;受信可、非同期モード
;             BANKSEL           BAUDCON
              BCF                     BAUDCON,3      ;BRG16=0 BRG 8bit
              MOVLW              019h                    ;019h=25
              MOVWF              SPBRGL                            ;Fosc=4MHz,Baud Rate=9600bps

;PORTA,PORTBクリア
              BANKSEL           LATA
              CLRF     LATA
              CLRF     LATB

MAIN
              CALL     GETCHR
              MOVWF              TEMP                  ;受信した文字をTEMPに格納
              XORLW 031h
              BTFSS   STATUS,Z           ;受信した文字が"1"ならスキップ
              GOTO   NEXT    
              CALL     MSG1
              CALL     LED_ON
              GOTO   MAIN
NEXT
              MOVFW              TEMP
              XORLW 030h
              BTFSS   STATUS,Z           ;受信した文字が"0"ならスキップ
              GOTO   MAIN
              CALL     MSG2
              CALL     LED_OFF
              GOTO   MAIN
              
LED_ON
              BANKSEL           LATA
              BSF                      LATA,1
              RETURN
              
LED_OFF
              BANKSEL LATA
              BCF                     LATA,1
              RETURN

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

MSG1
              MOVLW              "L"
              CALL     SENDCHR
              MOVLW              "E"
              CALL     SENDCHR
              MOVLW              "D"
              CALL     SENDCHR
              MOVLW              " "
              CALL     SENDCHR
              MOVLW              "O"
              CALL     SENDCHR
              MOVLW              "N"
              CALL     SENDCHR
              MOVLW              0Dh
              CALL     SENDCHR
              MOVLW              0Ah
              CALL     SENDCHR
              RETURN
              
MSG2
              MOVLW              "L"
              CALL     SENDCHR
              MOVLW              "E"
              CALL     SENDCHR
              MOVLW              "D"
              CALL     SENDCHR
              MOVLW              " "
              CALL     SENDCHR
              MOVLW              "O"
              CALL     SENDCHR
              MOVLW              "F"
              CALL     SENDCHR
              MOVLW              "F"
              CALL     SENDCHR
              MOVLW              0Dh
              CALL     SENDCHR
              MOVLW              0Ah
              CALL     SENDCHR
              RETURN

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

 ブレッドボードです。


TeraTermの画面です。

 トラブルシューティング
 最初、Vdd(5V)をPICKit3から供給していたのですが、TeraTermがFT-234のあるCOMポートを認識しなくなるトラブルがありました。そこで、PICKit3からの電源供給をやめ、VddをFT-234モジュールから供給するようにしたら問題が解決しました。

MPLABアセンブラ PIC16F1827 EUSARTテストその1

2024-11-15 20:33:28 | MPLAB アセンブラ
 MPLAB IDE v9.82, MPASM v5.51, PICKit3の環境で、PIC16F1827のEUSARTのテストをします。まず、送信テストをします。

 回路図です。今回もICSPでテストをします。
 PIC16F1827から送信した信号をシリアルUSB変換モジュールFT-234を通してパソコンに接続し、通信ソフトTeraTermで受信します。BaudRateは、9600bpsとします。



 PIC16F1827は、APFCON0とAPFCON1の設定で、各種機能のピン割り当てを変更することができます。
 今回は、APFCON0のbit7 RXDTSEL=0(RX/DT=RB1)、APFCON1のbit0 TXCKSEL=0(TX/CK=RB2)としました。



 通信プロトコルは、非同期、8bitとします。
  TXSTAは、TXEN=1,BRGH=1とします。(他のビットはデフォルト)

 RCSTAは、SPEN=1,CREN=1とします。(他のビットはデフォルト)

 PIC16F1827では、より広範囲なクロック、通信速度に対応するためにSPBRGレジスタが16bitに拡張され、SPBRGHとSPBRGLの2つになりました。8bitにするか16bitにするかは、BAUDCONレジスタのbit3 BRG16で設定します。今回は、8bitで使用しますので、BRG16=0とします。



 BaudRateを計算する式は、次の表のようにSYNC=0(非同期),BRG16=0(SPBRG 8bit),BRGH=1(高速モード)の時は、Fosc{16(n+1)}です。
 Fosc=4MHz=4000000Hz,BaudRate=9600bpsの時、SPBRGの値は、25となります。(SPBRGL=25)


 この値は、説明書にも掲載されています。誤差は、0.16%です。



 "Hello World!"の後に、数値を0から255までカウントアップしながら、1秒ごとに送信するプログラムを作ってみました。

------------------------------------------------------------------
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; PIC16F1827 EUSART TEST
; 2024.11.15
; 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
              
              ERRORLEVEL    -302
              
              CBLOCK             020h
              CNT1ms
              CNT250ms
              COUNTER
              BYTE0
              DIGIT12
              DIGIT34
              SHIFT
              WORK1
              TEMP
              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は入力)
              MOVLW              b'00000010'       ;RB1は入力、他は出力
              MOVWF              TRISB
;USART設定
;RX,TX PIN 設定
              BANKSEL           APFCON0
              BCF                     APFCON0,7        ;RXDTSEL=0 RX=RB1
              BCF                     APFCON1,0        ;TXCKSEL=0 TX=RB2     
              BANKSEL           TXSTA
              MOVLW              b'00100100'
              MOVWF              TXSTA                ;非同期モード、高速通信モードBRGH=1
;             BANKSEL           RCSTA
              MOVLW              090h
              MOVWF              RCSTA                ;受信可、非同期モード
;             BANKSEL           BAUDCON
              BCF                     BAUDCON,3      ;BRG16=0 BRG 8bit
              MOVLW              019h                    ;019h=25
              MOVWF              SPBRGL                            ;Fosc=4MHz,Baud Rate=9600bps

              CLRF     COUNTER                        ;COUNTERクリア
                            
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

              MOVFW              COUNTER
              MOVWF              BYTE0
              CALL     CONV_BCD        ;COUNTERの値(バイナリ)をBCDに変換しDIGIT34,DIGIT12に格納
              MOVFW              DIGIT34
              ANDLW 0Fh                                    ;DIGIT34の下位4bitを取り出す
              IORLW  30h                                    ;ASCIIコードに変換
              CALL     SENDCHR
              MOVFW              DIGIT12
              MOVWF              WORK1
              MOVWF              TEMP
              SWAPF  TEMP,W
              ANDLW 0Fh                                    ;DIGIT12の上位4bitを取り出す
              IORLW  30h                                    ;ASCIIコードに変換
              CALL     SENDCHR
              MOVFW              WORK1
              ANDLW 0Fh                                    ;DIGIT12の下位4bitを取り出す。
              IORLW  30h                                    ;ASCIIコードに変換
              CALL     SENDCHR
              MOVLW              0Dh                                   ;改行コード
              CALL     SENDCHR
              MOVLW              0Ah                                    ;NLコード
              CALL     SENDCHR
              
              INCF      COUNTER                        ;COUNTER+1

              CALL     LOOP250ms
              CALL     LOOP250ms
              CALL     LOOP250ms
              CALL     LOOP250ms
              GOTO   MAIN

;1文字送信          
SENDCHR
              BANKSEL           TXSTA
              BTFSS   TXSTA,TRMT     ;送信可能かチェック(1:可 0:禁止)
              GOTO   $-1
              MOVWF              TXREG
              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
                            
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
------------------------------------------------------------------

ブレッドボードです。


 PIC16F1827から送信された文字が、TeraTermに表示されました。
 数値は、0から255ですが、ゼロ消しの処理をしていませんので、0が表示されます。