;***** I2C_S2_LCD.sub ***************************************************** ; ; I2C LCD 制御サブルーチン (ソフトウエア I2C 版) ; ; (I2cLcd_Cmd, I2cLcd_Data, I2cLcd_Init, I2cLcd_Disp) ; (i2c_start, i2c_stop, byte_send, byte_reciv, ack, nack) ; ; Copyright (C) 2020-2023 by M.Yamamoto. All rights reserved. ; ; ( coding: Ver. 0.00 2020/04/01 by M.Yamamoto ) ; coding: Ver. 1.00 2020/04/05 ; update: Ver. 1.01 2020/10/02 I2cLcd_Disp を変更 ; update: Ver. 1.02 2020/10/11 PORTC に対応 ; update: Ver. 1.03 2020/10/27 byte_reciv, ack, nack を追加 ; update: Ver. 1.04 2022/01/14 PORTX, PIC16F1ファミリに対応 ; update: Ver. 1.05 2023/08/08 4 MHz クロックに対応 ; update: Ver. 1.06 2023/10/20 I2cLcd_Disp を変更 ; bugfix: Ver. x.xx ; ;***************************************************** PicAsm 0250-2 ****** ;#define TRISX TRISC ;例. PORTC で I2C を行う場合は、 ;#define PORTX PORTC ;include する側で #define 定義をすること ;#define _PIC16F1 ;PIC16F1ファミリで使用する場合は、 〃 ;#define _4MHz ;4 MHz クロックで使用する場合は、 〃 ;<使用外部ルーチン> wait_xxms, wait_100us ;<使用レジスタ> ;lcdtmp ;LCD への出力データの一時保存 ;lcdtmp2 ; ;i2ctmp ; ;wt1cnt ;ループカウンタ ;bit_cnt ;ループカウンタ ;addr_high ;読み出すデータの high アドレス ;addr_low ;読み出すデータの low アドレス ;========================================================================== ; I2C LCD へコマンドを出力 ;========================================================================== ;入力: W reg: コマンド I2cLcd_Cmd movwf lcdtmp ;Wレジスタの内容を一時保存 movlw h'00' ;コントロールバイト(Co=0,RS=0) goto i2clcd01 ;========================================================================== ; I2C LCD へデータを出力 ;========================================================================== ;入力: W reg: データ I2cLcd_Data movwf lcdtmp ;Wレジスタの内容を一時保存 movlw h'40' ;コントロールバイト(Co=0,RS=1) i2clcd01 movwf lcdtmp2 ;コントロールバイトを保存 call i2c_start ;スタートコンディション movlw h'7c' ;スレーブアドレス call byte_send ;1 バイト送信 movf lcdtmp2,W ;コントロールバイト(Co=0,RS=0/1) call byte_send ;1 バイト送信 movf lcdtmp,W ; call byte_send ;1 バイト送信 call i2c_stop ;ストップコンディション call wait_26us ;26.3us待つ return ;-------------------------------------------------------------------------- ; 26.3μ秒 ウェイトルーチン (at 8 MHz or 4 MHz) wait_26us #ifdef _4MHz movlw 5 ;1 #else movlw 10 ;1 #endif movwf wt1cnt ;1 w26_01 goto $+1 ;2 decfsz wt1cnt,F ;1,2 goto w26_01 ;2,0 1+1+(2+1+2)*9+(2+2+0)=51 8 MHz ;2,0 1+1+(2+1+2)*4+(2+2+0)=26 4 MHz return ;2 51+2=53 / 26+2=28 ; 53/8MHz*4 = 26.5 μS ; 28/4MHz*4 = 28.0 μS ;========================================================================== ; I2C LCD 初期設定 ;========================================================================== ;使用外部ルーチン: wait_xxms, wait_100us I2cLcd_Init movlw 40 call wait_xxms ;wait 40ms (40ms以上を確保) movlw h'38' ;Function set call I2cLcd_Cmd ; movlw h'39' ;Function set, IS=1: 拡張コマンド call I2cLcd_Cmd ; movlw h'14' ;Internal OSC Frequency call I2cLcd_Cmd ; movlw h'70' ;Contrast set call I2cLcd_Cmd ; movlw h'56' ;Power/ICON/Contrast Control call I2cLcd_Cmd ; movlw h'6c' ;Follower Control call I2cLcd_Cmd ; movlw 200 call wait_xxms ;wait 200ms (200ms以上を確保) movlw h'38' ;Function set, IS=0: 拡張コマンド解除 call I2cLcd_Cmd ; movlw h'0c' ;Display ON call I2cLcd_Cmd ; movlw h'01' ;Clear Display call I2cLcd_Cmd ; movlw 1 call wait_xxms ;wait 1ms (1.08ms以上を確保) call wait_100us return ;========================================================================== ; I2C LCD 1行メッセージ表示 ;========================================================================== ;使用レジスタ: addr_low, addr_high, wt1cnt ;<使用例> movlw h'80' ;表示位置の DDRAM のアドレスをセット ; call I2cLcd_Cmd ;LCD へコマンドを出力 ; movlw high st_msg ;メッセージデータの先頭アドレスの high アドレス ; movwf addr_high ; ; movlw low st_msg ;メッセージデータの先頭アドレスの low アドレス ; movwf addr_low ; ; call I2cLcd_Disp ;メッセージデータ1行表示 ; : ;st_msg dt "StpWatch",0 I2cLcd_Disp call tbl_read ;テーブルデータの読み出し incf addr_low,F ;読み出すデータの low アドレスの更新 btfsc STATUS,Z ;オーバーフローした場合は incf addr_high,F ;読み出すデータの high アドレスの更新 #ifdef _PIC16F1 movlp high $ #else movwf wt1cnt ;ワーク変数へ退避 movlw high $ movwf PCLATH ; movf wt1cnt,W ;ワーク変数から復帰 #endif addlw 0 btfsc STATUS,Z ;h'00' か? goto i2cldsp01 ;Yes call I2cLcd_Data ;LCD へデータを1文字出力 goto I2cLcd_Disp i2cldsp01 return ; テーブルデータの1文字読み出し tbl_read movf addr_high,W ;読み出すデータの high アドレス movwf PCLATH movf addr_low,W ;読み出すデータの low アドレス movwf PCL ;========================================================================== ; I2C ルーチン ; ; original: http://t4053x.jp/download.htm 内の ; SubRtin.lzh に収録の I2C_0A.asm ;========================================================================== ; スタートコンディション i2c_start bsf PORTX,SCL ;SCL="H" bsf PORTX,SDA ;SDA="H" bcf PORTX,SDA ;SDA="L" bcf PORTX,SCL ;SCL="L" return ;-------------------------------------------------------------------------- ; ストップコンディション i2c_stop bsf PORTX,SCL ;SCL="H" bcf PORTX,SDA ;SDA="L" bsf PORTX,SDA ;SDA="H" return ;-------------------------------------------------------------------------- ; データ 1 バイト送信 byte_send movwf i2ctmp ;Wレジスタの内容を一時保存 movlw 8 movwf bit_cnt ;ループカウンタにセット bsend01 bcf PORTX,SDA ;SDA="L" btfsc i2ctmp,7 ;送り出しデータの 7ビット目 = 1 か? bsf PORTX,SDA ;Yes, SDA="H" bsf PORTX,SCL ;SCL="H"(一瞬) bcf PORTX,SCL ;SCL="L" rlf i2ctmp,F ;送り出しデータを 1ビット左にシフト decfsz bit_cnt,F ;8ビット送信した か? goto bsend01 ;No ; 1 バイト送信後の ACK チェック #ifdef _PIC16F1 movlb 1 ;バンク 1 #else bsf STATUS,RP0 ;バンク 1 #endif bsf TRISX,SDA ;SDA: 入力 #ifdef _PIC16F1 movlb 0 ;バンク 0 #else bcf STATUS,RP0 ;バンク 0 #endif bsf PORTX,SCL ;SCL="H" nop ;ACK のチェックをしない bcf PORTX,SCL ;SCL="L" #ifdef _PIC16F1 movlb 1 ;バンク 1 #else bsf STATUS,RP0 ;バンク 1 #endif bcf TRISX,SDA ;SDA: 出力 #ifdef _PIC16F1 movlb 0 ;バンク 0 #else bcf STATUS,RP0 ;バンク 0 #endif return ;-------------------------------------------------------------------------- ; データ 1 バイト受信 byte_reciv movlw 8 movwf bit_cnt ;ループカウンタにセット #ifdef _PIC16F1 movlb 1 ;バンク 1 #else bsf STATUS,RP0 ;バンク 1 #endif bsf TRISX,SDA ;SDA: 入力 #ifdef _PIC16F1 movlb 0 ;バンク 0 #else bcf STATUS,RP0 ;バンク 0 #endif brecv01 bsf PORTX,SCL ;SCL="H" bcf STATUS,C ;C=0 btfsc PORTX,SDA ;受け取り SDA = "H" か? bsf STATUS,C ;Yes, C=1 rlf i2ctmp,F ;受け取りデータを 1ビット左にシフト bcf PORTX,SCL ;SCL="L" decfsz bit_cnt,F ;8ビット受信した か? goto brecv01 ;No #ifdef _PIC16F1 movlb 1 ;バンク 1 #else bsf STATUS,RP0 ;バンク 1 #endif bcf TRISX,SDA ;SDA: 出力 #ifdef _PIC16F1 movlb 0 ;バンク 0 #else bcf STATUS,RP0 ;バンク 0 #endif movf i2ctmp,W ;W reg = 受信データ return ;-------------------------------------------------------------------------- ; ACK ack bcf PORTX,SDA ;SDA="L" bsf PORTX,SCL ;SCL="H" bcf PORTX,SCL ;SCL="L" bsf PORTX,SDA ;SDA="H" return ; NACK nack bsf PORTX,SDA ;SDA="H" bsf PORTX,SCL ;SCL="H" bcf PORTX,SCL ;SCL="L" return ;=============================================================== end ======