;***** I2C_XS_100K.sub **************************************************** ; ; I2C (SCLクロック周波数 = 100 KHz) サブルーチン (ソフトウエア I2C 版) ; ; (i2c_start, i2c_stop, i2c_byte_send, i2c_byte_reciv, i2c_ack, i2c_nack) ; ; Copyright (C) 2020-2021 by M.Yamamoto. All rights reserved. ; ; ( coding: Ver. 0.00 2020/12/10 by M.Yamamoto ) ; coding: Ver. 1.00 2020/12/15 ; update: Ver. 1.01 2021/01/01 I2Cルーチンを分離 ; update: Ver. 1.01b 2021/02/17 管理番号を変更 ; bugfix: Ver. x.xx ; ;***************************************************** PicAsm 0257-2 ****** ;#define TRISX TRISC ;例. PORTC で I2C を行う場合は、 ;#define PORTX PORTC ;include する側で #define 定義をすること ;<使用レジスタ> ;i2ctmp ;送受信データの一時保存 ;bit_cnt ;ループカウンタ ;-------------------------------------------------------------------------- ; ウェイト・ルーチン (8 MHz のとき) ;-------------------------------------------------------------------------- i2c_wait goto $+1 ;2 goto $+1 ;2 goto $+1 ;2 ;; goto $+1 ;2 return ;2 ;Total 10/8MHz*4 = 5 μS ;-------------------------------------------------------------------------- ; スタートコンディション ;-------------------------------------------------------------------------- i2c_start bsf PORTX,SCL ;SCL="H" bsf PORTX,SDA ;SDA="H" call i2c_wait bcf PORTX,SDA ;SDA="L" call i2c_wait bcf PORTX,SCL ;SCL="L" return ;-------------------------------------------------------------------------- ; ストップコンディション ;-------------------------------------------------------------------------- i2c_stop bcf PORTX,SDA ;SDA="L" bsf PORTX,SCL ;SCL="H" call i2c_wait bsf PORTX,SDA ;SDA="H" return ;-------------------------------------------------------------------------- ; データ 1 バイト送信 ;-------------------------------------------------------------------------- ;使用レジスタ: i2ctmp, bit_cnt ;入力: W reg: 送信データ i2c_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" call i2c_wait bsf PORTX,SCL ;SCL="H" call i2c_wait bcf PORTX,SCL ;SCL="L" rlf i2ctmp,F ;送り出しデータを 1ビット左にシフト decfsz bit_cnt,F ;8ビット送信した か? goto bsend01 ;No ; 1 バイト送信後の ACK チェック bsf STATUS,RP0 ;バンク 1 bsf TRISX,SDA ;SDA: 入力ポート bcf STATUS,RP0 ;バンク 0 call i2c_wait bsf PORTX,SCL ;SCL="H" call i2c_wait nop ;ACK のチェックをしない bcf PORTX,SCL ;SCL="L" bsf STATUS,RP0 ;バンク 1 bcf TRISX,SDA ;SDA: 出力ポート bcf STATUS,RP0 ;バンク 0 return ;-------------------------------------------------------------------------- ; データ 1 バイト受信 ;-------------------------------------------------------------------------- ;使用レジスタ: i2ctmp, bit_cnt ;出力: W reg: 受信データ i2c_byte_reciv movlw 8 movwf bit_cnt ;ループカウンタにセット bsf STATUS,RP0 ;バンク 1 bsf TRISX,SDA ;SDA: 入力ポート bcf STATUS,RP0 ;バンク 0 brecv01 call i2c_wait 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ビット左にシフト call i2c_wait bcf PORTX,SCL ;SCL="L" decfsz bit_cnt,F ;8ビット受信した か? goto brecv01 ;No bsf STATUS,RP0 ;バンク 1 bcf TRISX,SDA ;SDA: 出力ポート bcf STATUS,RP0 ;バンク 0 movf i2ctmp,W ;W reg = 受信データ return ;-------------------------------------------------------------------------- ; ACK 応答 ;-------------------------------------------------------------------------- i2c_ack bcf PORTX,SDA ;SDA="L" bsf PORTX,SCL ;SCL="H" call i2c_wait bcf PORTX,SCL ;SCL="L" bsf PORTX,SDA ;SDA="H" return ;-------------------------------------------------------------------------- ; NACK 応答 ;-------------------------------------------------------------------------- i2c_nack bsf PORTX,SDA ;SDA="H" bsf PORTX,SCL ;SCL="H" call i2c_wait bcf PORTX,SCL ;SCL="L" return ;=============================================================== end ======