概要

I2C接続のリアルタイムクロックRTC8564を使用しLCD液晶に時刻を表示する。
バッテリバックアップされているので電源を切っても時刻はカウントされる。
ただし時刻修正機能はないので、最初にプログラムで設定された時刻でカウントを続ける。
ソフトウェアディレイにより約1秒置きにRTC8564より時刻を呼び出しLCDに表示
クロックはUSB-IOで接続済みの12MHzのセラミック振動子を使用しPLLで4倍にしている。書込みはPICKit3を前提とする。
液晶表示例

2013/10/09
21:00:00
回路は次のとおりである。
回路図(PNG) 回路図(PDF) 回路図(DXF)

プログラムの説明

ソースファイル

以下のファイルで構成されている
rtc1a.asm ・・・ メインプログラム
i2c.asm   ・・・ I2Cサポートライブラリ Version 1.00
i2c.inc   ・・・ I2Cサポートライブラリ Version 1.00
lcd.asm   ・・・ LCD表示用ライブラリ Version 1.00
lcd.inc   ・・・ LCD表示用インクルードファイル Version 1.00
rtc.asm   ・・・ RTC8564ライブラリ Version 1.00
rtc.inc   ・・・ RTC8564ライブラリ Version 1.00
stdlib.asm ・・・ 8bit,16bit割り算、2進,10進,16進数値変換等のライブラリ Version 1.00
stdlib.inc ・・・ 8bit,16bit割り算、2進,10進,16進数値変換等のインクルートファイル Version 1.00

ソースファイルのダウンロード rtc1a.zip

i2c.asm

PIC内蔵のI2Cモジュールを使用したI2Cの基本的なプロトコルをサポート
スタート・ストップ・リスタート・1byte書き込み・1byte読み込み・ブロック書き込み・ブロック読み込みをサブルーチン化している。
詳細は以下のリンクを参照されたい
i2c.asm

lcd.asm

主にSC1602向けのLCD液晶表示用のライブラリである。
液晶モジュールと接続するポートはマクロで変更可能である。
busyフラグはチェックせずソフトウェアディレイで対応しているためクロック周波数が変更された場合はディレイの調整が必要
詳細は以下のリンクを参照されたい
lcd.asm

rtc.asm

RTC8564の書き込み・読み込み等をサポートしたライブラリである。

詳細は以下のリンクを参照されたい
rtc.asm

stdlib.asm

8bit,16bit割り算、2進,10進,16進数値変換等をサポートしたライブラリである

詳細は以下のリンクを参照されたい
stdlib.asm

rtc1a.asm

メインプログラムである。
IOポートの入出力の設定・I2Cモジュールの初期化をし、LCDの初期化、RTCの初期化が必要かチェックし電圧の低下等が検出されれば初期化、その後、約1秒おきに時刻を取得しLCDに表示する。

; RTC-8564を使用した液晶時計  Version 1.00
; File:        rtc1a.asm
; Target:      PIC18F14K50 48Mhz
; アセンブラ:   Microchip MPASM(v5.51)
; 書き込み:     PICKit 3
; リリース:     2013/10/01 21:00

        DB      "2012/09/23      "
        DB      "23:45:56        "

        #INCLUDE <p18f14k50.inc>
        ; 水晶発振(12MHz) クロック分周無 PLL有効(*4)
        ; ウォッチドッグタイマ無効 低電圧プログラム書き込みモード無効
        CONFIG FOSC = HS,CPUDIV = NOCLKDIV,PLLEN=ON,WDTEN=OFF,LVP=OFF

        #INCLUDE "lcd.inc"
        #INCLUDE "stdlib.inc"
        #INCLUDE "i2c.inc"
        #INCLUDE "rtc.inc"

;   プログラムメモリadsのアドレスをTLPTRレジスタに上書きする

LDTBLPTR MACRO ads
        movlw   UPPER ads
        movwf   TBLPTRU
        movlw   HIGH ads
        movwf   TBLPTRH
        movlw   LOW ads
        movwf   TBLPTRL
        ENDM

bank0        UDATA   ; 変数の定義 バンク0 アクセスバンク
Tcount1     RES 1      ; wait
Tcount2     RES 1      ; wait
Tcount3     RES 1      ; wait
LCD_WRITE   RES 1      ; writeデータを指定
LCD_TEMP    RES 1
Temp1       RES 1      ; サブルーチン用の変数
ARG1        RES 1      ; サブルーチン引数
ARGL        RES 1
ARGH        RES 1
BYTE2HEX_TEMP RES 1

DIV_A       RES 1 ; 除算の被除数を指定 サブルーチンコール後答えが返る
DIV_MOD     RES 1 ; サブルーチンコール後余りが返る
DIV_B       RES 1 ; 除算の除数を指定
DIV_AL      RES 1
DIV_AH      RES 1
DIV_MODL    RES 1
DIV_MODH    RES 1
LCD_BUF     RES 32     ; 16*2文字分のバッファ
RTC_SADS    RES 1 ; スレーブアドレス
RTC_ADS     RES 1 ; アドレス
RTC_BUF     RES 16  ; レジスタ読み書き用

        GLOBAL LCD_WRITE,LCD_TEMP,Temp1,Tcount1,Tcount2,Tcount3
        GLOBAL DIV_MOD,DIV_A,DIV_B,DIV_MODL,DIV_MODH,DIV_AL,DIV_AH,ARG1,ARGL,ARGH
        GLOBAL BYTE2HEX_TEMP

        CODE
        ORG 0
        goto   start    ;   リセット時

start
        clrf    ANSEL   ; RC3-RC0,RA4をデジタル入力バッファに設定
        clrf    ANSELH  ; RB5-RB4,RC7-RC6をデジタル入力バッファに設定
        clrf    SLRCON  ; PORTA,PORTB,PORTCをスルーレートを標準に設定
        clrf    TRISA   ; PORTAを全部出力に設定
        movlw   0f0h
        movwf   TRISB   ; RB7-RB4を入力に設定
        clrf    TRISC   ; PORTCを全部出力に設定する
        clrf    PORTC   ; PORTCを全部0にする。

        movlw   b'00101000' ; SSPモジュールon,I2Cマスターモード
        movwf   SSPCON1
        clrf    SSPCON2     ;
        movlw   01dh
        movwf   SSPADD      ; 400kbps
        clrf    SSPSTAT
        bcf     RCON,IPEN   ; 割り込み優先順位なし
        bsf     IPR1,SSPIP  ; 高位レベル

        rcall   lcd_init    ;   液晶初期化

;      プログラムメモリからデーターメモリへ転送するLCD

        LDTBLPTR lcd_init_str ; マクロでTBLPTRレジスタにlcd_init_strを設定

        movlw   d'32'
        movwf   Temp1

        lfsr    FSR0,LCD_BUF
lcd_init_str_set_loop
        tblrd   *+          ;   プログラムメモリTBLPTRから読み出し後TBLPTRを+1する
        movf    TABLAT,W
        movwf   POSTINC0    ;   間接アドレッシング アドレスはアクセス後に+1される
        decfsz  Temp1       ;   Temp1から1を引き結果が0になるまで繰り返す
        bra     lcd_init_str_set_loop
       
        rcall   rtc_vl_chk  ;   RTCがバックアップされていたか確認
        btfss   ARG1,7
        goto    loop        ;   RTCはバックアップされていたので初期化しない


rtc_init    ;   RTCを初期化
        LDTBLPTR rtc_init_tbl
        movlw   d'18'
        movwf   Temp1
        lfsr    FSR0,RTC_SADS
rtc_init_loop
        tblrd   *+          ;   プログラムメモリTBLPTRから読み出し後TBLPTRを+1する
        movf    TABLAT,W
        movwf   POSTINC0    ;   間接アドレッシング アドレスはアクセス後に+1される
        decfsz  Temp1       ;   Temp1から1を引き結果が0になるまで繰り返す
        bra     rtc_init_loop
rtc_mem_write
        rcall   i2c_start   ;   スタートコンディションを出力
        lfsr    FSR1,RTC_SADS
        movlw   d'18'
        rcall   i2c_block_write
        rcall   i2c_stop    ;   ストップコンディションを出力
        rcall   rtc_start

loop
        rcall   i2c_start   ;   スタートコンディションを出力
        movlw   RTC8564_SADS
        rcall   i2c_write
        movlw   0
        rcall   i2c_write
        rcall   i2c_restart
        movlw   RTC8564_SADS+1  ; 読み込みモード
        rcall   i2c_write

        lfsr    FSR1,RTC_BUF
        movlw   d'16'
        rcall   i2c_block_read
        rcall   i2c_stop    ;   ストップコンディションを出力

        movf    RTC_BUF+RTC_YEAR,W,BANKED   ; 年を読みだす
        movwf   ARG1
        lfsr    FSR1,LCD_BUF+d'2'
        rcall   byte2hex

        movf    RTC_BUF+RTC_MONTH,W,BANKED   ; 月を読みだす
        andlw   b'00011111' ; 上位ビットをマスク
        movwf   ARG1
        lfsr    FSR1,LCD_BUF+d'5'
        rcall   byte2hex

        movf    RTC_BUF+RTC_DAY,W,BANKED   ; 日を読みだす
        andlw   b'00111111' ; 上位ビットをマスク
        movwf   ARG1
        lfsr    FSR1,LCD_BUF+d'8'
        rcall   byte2hex

        movf    RTC_BUF+RTC_HOUR,W,BANKED   ; 時刻を読みだす
        andlw   b'00111111' ; 上位ビットをマスク
        movwf   ARG1
        lfsr    FSR1,LCD_BUF+d'16'
        rcall   byte2hex

        movf    RTC_BUF+RTC_MIN,W ,BANKED  ; 分を読みだす
       andlw   b'01111111' ; 最上位ビットをマスク
        movwf   ARG1
        lfsr    FSR1,LCD_BUF+d'19'
        rcall   byte2hex

        movf    RTC_BUF+RTC_SEC,W,BANKED  ; 秒を読みだす
        andlw   b'01111111' ; 最上位ビットをマスク
        movwf   ARG1
        lfsr    FSR1,LCD_BUF+d'22'
        rcall   byte2hex

        lfsr    FSR1,LCD_BUF
        rcall   lcd_disp

        rcall   wait500
        rcall   wait500

        goto    loop


rtc_init_tbl        ; RTCの初期定数
        DB      RTC8564_SADS,  0 ;スレーブアドレス,アドレス
        DB      b'00100000', b'00000000' ; CTL1,CTL2
        DB      h'34', h'26'       ; 02h 秒,分
        DB      h'23' ,h'15'       ; 04h 時,日
        DB      d'04' ,h'08'       ; 06h 曜日,月
        DB      h'13' , h'80'       ; 08h 年,アラーム 分
        DB      h'80' , h'80'       ; 0ah アラーム 時,アラーム  日
        DB      h'80' ,h'00'       ; 0ch アラーム 曜日,CLOCKOUT 周波数
        DB      h'00' , h'00'       ; 0eh タイマーCTL,タイマー

lcd_init_str
;                0123456789abcdef
        DB      "2012/09/23      "
        DB      "23:45:56        "

wait500                 ; 0.5秒Wait
        movlw   d'50'  ; 10ms*50=0.5s
        movwf   Tcount1
dloop1
        movlw   d'200'	; 50μs*200=10ms
        movwf   Tcount2
dloop2                   ; t=(12+12*count3)/48MHz 50μs
        movlw   d'199'
        movwf   Tcount3
        nop
dloop3
        decfsz  Tcount3
        goto    dloop3
        decfsz  Tcount2
        goto    dloop2
        decfsz  Tcount1
        goto    dloop1
        return

        END