;***** I2C_S_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 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 を追加 ; bugfix: Ver. x.xx ; ;******************************************************* PicAsm 0250 ****** ;<使用外部ルーチン> wait_xxms, wait_100us ;<使用レジスタ> ;lcdtmp ;LCD への出力データの一時保存 ;lcdtmp2 ; ;i2ctmp ; ;wt1cnt ;ループカウンタ ;bit_cnt ;ループカウンタ ;addr_high ;読み出すデータの high アドレス ;addr_low ;読み出すデータの low アドレス ;#define _PORTC ;PORTC で I2C を行う場合は、include する側で #define 定義をすること ;========================================================================== ; 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) wait_26us movlw 10 ;1 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 return ;2 51+2=53 ; 53/8MHz*4 = 26.5 μ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 ;<使用例> 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 "Sp Watch",0 I2cLcd_Disp call tbl_read ;テーブルデータの読み出し bcf PCLATH,3 ;ページ 0 に戻す bcf PCLATH,4 incf addr_low,F ;読み出すデータの low アドレスの更新 btfsc STATUS,Z ;オーバーフローした場合は incf addr_high,F ;読み出すデータの high アドレスの更新 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 ;========================================================================== #ifndef _PORTC ;***** PORTA のとき ***** ; スタートコンディション i2c_start bsf PORTA,SCL ;SCL="H" bsf PORTA,SDA ;SDA="H" bcf PORTA,SDA ;SDA="L" bcf PORTA,SCL ;SCL="L" return ;-------------------------------------------------------------------------- ; ストップコンディション i2c_stop bsf PORTA,SCL ;SCL="H" bcf PORTA,SDA ;SDA="L" bsf PORTA,SDA ;SDA="H" return ;-------------------------------------------------------------------------- ; データ 1 バイト送信 byte_send movwf i2ctmp ;Wレジスタの内容を一時保存 movlw 8 movwf bit_cnt ;ループカウンタにセット bsend01 bcf PORTA,SDA ;SDA="L" btfsc i2ctmp,7 ;送り出しデータの 7ビット目 = 1 か? bsf PORTA,SDA ;Yes, SDA="H" bsf PORTA,SCL ;SCL="H"(一瞬) bcf PORTA,SCL ;SCL="L" rlf i2ctmp,F ;送り出しデータを 1ビット左にシフト decfsz bit_cnt,F ;8ビット送信した か? goto bsend01 ;No ; 1 バイト送信後の ACK チェック bsf STATUS,RP0 ;バンク 1 bsf TRISA,SDA ;SDA: 入力 bcf STATUS,RP0 ;バンク 0 bsf PORTA,SCL ;SCL="H" nop ;ACK のチェックをしない bcf PORTA,SCL ;SCL="L" bsf STATUS,RP0 ;バンク 1 bcf TRISA,SDA ;SDA: 出力 bcf STATUS,RP0 ;バンク 0 return ;-------------------------------------------------------------------------- ; データ 1 バイト受信 byte_reciv movlw 8 movwf bit_cnt ;ループカウンタにセット bsf STATUS,RP0 ;バンク 1 bsf TRISA,SDA ;SDA: 入力 bcf STATUS,RP0 ;バンク 0 brecv01 bsf PORTA,SCL ;SCL="H" bcf STATUS,C ;C=0 btfsc PORTA,SDA ;受け取り SDA = "H" か? bsf STATUS,C ;Yes, C=1 rlf i2ctmp,F ;受け取りデータを 1ビット左にシフト bcf PORTA,SCL ;SCL="L" decfsz bit_cnt,F ;8ビット受信した か? goto brecv01 ;No bsf STATUS,RP0 ;バンク 1 bcf TRISA,SDA ;SDA: 出力 bcf STATUS,RP0 ;バンク 0 movf i2ctmp,W ;W reg = 受信データ return ;-------------------------------------------------------------------------- ; ACK ack bcf PORTA,SDA ;SDA="L" bsf PORTA,SCL ;SCL="H" bcf PORTA,SCL ;SCL="L" bsf PORTA,SDA ;SDA="H" return ; NACK nack bsf PORTA,SDA ;SDA="H" bsf PORTA,SCL ;SCL="H" bcf PORTA,SCL ;SCL="L" return ;========================================================================== #else ;***** PORTC のとき ***** ; スタートコンディション i2c_start bsf PORTC,SCL ;SCL="H" bsf PORTC,SDA ;SDA="H" bcf PORTC,SDA ;SDA="L" bcf PORTC,SCL ;SCL="L" return ;-------------------------------------------------------------------------- ; ストップコンディション i2c_stop bsf PORTC,SCL ;SCL="H" bcf PORTC,SDA ;SDA="L" bsf PORTC,SDA ;SDA="H" return ;-------------------------------------------------------------------------- ; データ 1 バイト送信 byte_send movwf i2ctmp ;Wレジスタの内容を一時保存 movlw 8 movwf bit_cnt ;ループカウンタにセット bsend01 bcf PORTC,SDA ;SDA="L" btfsc i2ctmp,7 ;送り出しデータの 7ビット目 = 1 か? bsf PORTC,SDA ;Yes, SDA="H" bsf PORTC,SCL ;SCL="H"(一瞬) bcf PORTC,SCL ;SCL="L" rlf i2ctmp,F ;送り出しデータを 1ビット左にシフト decfsz bit_cnt,F ;8ビット送信した か? goto bsend01 ;No ; 1 バイト送信後の ACK チェック bsf STATUS,RP0 ;バンク 1 bsf TRISC,SDA ;SDA: 入力 bcf STATUS,RP0 ;バンク 0 bsf PORTC,SCL ;SCL="H" nop ;ACK のチェックをしない bcf PORTC,SCL ;SCL="L" bsf STATUS,RP0 ;バンク 1 bcf TRISC,SDA ;SDA: 出力 bcf STATUS,RP0 ;バンク 0 return ;-------------------------------------------------------------------------- ; データ 1 バイト受信 byte_reciv movlw 8 movwf bit_cnt ;ループカウンタにセット bsf STATUS,RP0 ;バンク 1 bsf TRISC,SDA ;SDA: 入力 bcf STATUS,RP0 ;バンク 0 brecv01 bsf PORTC,SCL ;SCL="H" bcf STATUS,C ;C=0 btfsc PORTC,SDA ;受け取り SDA = "H" か? bsf STATUS,C ;Yes, C=1 rlf i2ctmp,F ;受け取りデータを 1ビット左にシフト bcf PORTC,SCL ;SCL="L" decfsz bit_cnt,F ;8ビット受信した か? goto brecv01 ;No bsf STATUS,RP0 ;バンク 1 bcf TRISC,SDA ;SDA: 出力 bcf STATUS,RP0 ;バンク 0 movf i2ctmp,W ;W reg = 受信データ return ;-------------------------------------------------------------------------- ; ACK ack bcf PORTC,SDA ;SDA="L" bsf PORTC,SCL ;SCL="H" bcf PORTC,SCL ;SCL="L" bsf PORTC,SDA ;SDA="H" return ; NACK nack bsf PORTC,SDA ;SDA="H" bsf PORTC,SCL ;SCL="H" bcf PORTC,SCL ;SCL="L" return #endif ;***** ***** ***** ;=============================================================== end ======