山本ワールド
リアルタイムクロックRTC8564を使用した時刻表示
概要
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