#ifndef _i2cm_inc_ #define _i2cm_inc_ messg "include 'i2cm.inc'" LIST ; Title : I2C master interface ; By : komi ; Last update : 2005.09.03 ; Version : 0.1 NOLIST ;---------------------------------------------------------------------------- ; 解説 ;---------------------------------------------------------------------------- ; ; ;---------------------------------------------------------------------------- #ifndef CLOCK_FREQ error "Please define that is CPU CLOCK frequency.(I2CM.INC)" #endif variable _I2C_start_used_ = false variable _I2C_stop_used_ = false variable _I2C_restart_used_ = false variable _I2C_send_char_used_ = false variable _I2C_receive_char_used_ = false variable _I2C_acknowledge_used_ = false ;------------------------------------------------------------------ ; I2C master 初期化 I2C_master_init MACRO i2c_freq banksel SSPADD MOVLW (((CLOCK_FREQ/i2c_freq)/4) -1) MOVWF SSPADD banksel SSPSTAT BCF SSPSTAT, CKE BCF SSPSTAT, SMP banksel SSPCON MOVLW B'00101000' MOVWF SSPCON ENDM ;------------------------------------------------------------------ ; フラグクリア I2C_flag_clear MACRO banksel PIR1 BCF PIR1, SSPIF BCF PIR2, BCLIF ENDM ;------------------------------------------------------------------ ; I2C START I2C_start MACRO _I2C_start_used_ = true pagesel I2C_start_f CALL I2C_start_f ENDM ;------------------------------------------------------------------ ; I2C STOP I2C_stop MACRO _I2C_stop_used_ = true pagesel I2C_stop_f CALL I2C_stop_f ENDM ;------------------------------------------------------------------ ; I2C ReSTART I2C_restart MACRO _I2C_restart_used_ = true pagesel I2C_restart_f CALL I2C_restart_f ENDM ;------------------------------------------------------------------ ; I2C send I2C_send_char_W MACRO _I2C_send_char_used_ = true pagesel I2C_send_char_f CALL I2C_send_char_f ENDM I2C_send_char_U1 MACRO varU1 _I2C_send_char_used_ = true banksel varU1 MOVF varU1, W pagesel I2C_send_char_f CALL I2C_send_char_f ENDM I2C_send_char_V1 MACRO value _I2C_send_char_used_ = true MOVLW value pagesel I2C_send_char_f CALL I2C_send_char_f ENDM ;------------------------------------------------------------------ ; I2C send goto ; ACK, NAK, Bus衝突 で処理分岐 I2C_send_char_goto_core MACRO ack_jump, nak_jump, bcl_jump local label0, label1, label2, label3 BTFSC PIR2, BCLIF GOTO label2 banksel SSPCON2 BTFSC SSPCON2, ACKSTAT GOTO label1 label0: pagesel ack_jump CALL ack_jump GOTO label3 label1: pagesel nak_jump CALL nak_jump GOTO label3 label2: pagesel bcl_jump CALL bcl_jump label3: ENDM I2C_send_char_goto_W MACRO ack_jump, nak_jump, bcl_jump I2C_send_char_W I2C_send_char_goto_core ack_jump, nak_jump, bcl_jump ENDM I2C_send_char_goto_U1 MACRO varU1, ack_jump, nak_jump, bcl_jump I2C_send_char_U1 I2C_send_char_goto_core ack_jump, nak_jump, bcl_jump ENDM I2C_send_char_goto_V1 MACRO value, ack_jump, nak_jump, bcl_jump I2C_send_char_V1 value I2C_send_char_goto_core ack_jump, nak_jump, bcl_jump ENDM ;------------------------------------------------------------------ ; I2C receive W_I2C_receive_char MACRO _I2C_receive_char_used_ = true pagesel I2C_receive_char_f CALL I2C_receive_char_f MOVF SSPBUF, W ENDM U1_I2C_receive_char MACRO varU1 _I2C_receive_char_used_ = true pagesel I2C_receive_char_f CALL I2C_receive_char_f MOVF SSPBUF, W banksel varU1 MOVWF varU1 ENDM I2C_receive_char MACRO _I2C_receive_char_used_ = true pagesel I2C_receive_char_f CALL I2C_receive_char_f ENDM ;------------------------------------------------------------------ ; I2C ack/nak I2C_acknowledge_V1 MACRO value _I2C_acknowledge_used_ = true banksel SSPCON2 if value BCF SSPCON2, ACKDT else BSF SSPCON2, ACKDT endif pagesel I2C_acknowledge_f CALL I2C_acknowledge_f ENDM I2C_acknowledge_U1 MACRO varU1 _I2C_acknowledge_used_ = true banksel varU1 MOVF varU1, F banksel SSPCON2 BCF SSPCON2, ACKDT BTFSC STATUS, Z BSF SSPCON2, ACKDT ; ACKDT = (varU1 == 0) pagesel I2C_acknowledge_f CALL I2C_acknowledge_f ENDM ;------------------------------------------------------------------ ;---------------------------------------------------------------------------- ; 関数本体 I2CM_functions MACRO C_I2CM CODE #if _I2C_start_used_ _I2C_start_used_ = false I2C_start_f: banksel SSPCON2 BSF SSPCON2, SEN ; スタートコンディション開始 banksel PIR2 BTFSS PIR2, BCLIF GOTO $ +3 BCF PIR2, BCLIF GOTO I2C_start_f ; バス衝突ならやり直し banksel SSPCON2 BTFSC SSPCON2, SEN GOTO $ -1 ; 完了待ち RETURN #endif #if _I2C_stop_used_ _I2C_stop_used_ = false I2C_stop_f: banksel SSPCON2 BSF SSPCON2, PEN ; ストップコンディション開始 banksel PIR2 BTFSS PIR2, BCLIF GOTO $ +3 BCF PIR2, BCLIF GOTO I2C_stop_f ; バス衝突ならやり直し banksel SSPCON2 BTFSC SSPCON2, PEN GOTO $ -1 ; 完了待ち RETURN #endif #if _I2C_restart_used_ _I2C_restart_used_ = false I2C_restart_f: banksel SSPCON2 BSF SSPCON2, RSEN ; 繰り返しスタートコンディション開始 banksel PIR2 BTFSS PIR2, BCLIF GOTO $+3 BCF PIR2, BCLIF GOTO I2C_restart_f ; バス衝突ならやり直し banksel SSPCON2 BTFSC SSPCON2, RSEN GOTO $-1 ; 完了待ち RETURN #endif #if _I2C_send_char_used_ _I2C_send_char_used_ = false I2C_send_char_f: banksel SSPBUF MOVWF SSPBUF BTFSC PIR1, SSPIF RETURN ; ACK/NAK 受信終了 BTFSC PIR2, BCLIF RETURN ; バス衝突なら終了 GOTO $-4 #endif #if _I2C_receive_char_used_ _I2C_receive_char_used_ = true I2C_receive_char_f: banksel SSPCON2 BSF SSPCON2, RCEN ; 受信開始 banksel PIR1 BTFSS PIR1, SSPIF GOTO $-1 ; 完了待ち RETURN #endif #if _I2C_acknowledge_used_ _I2C_acknowledge_used_ = false I2C_acknowledge_f: BSF SSPCON2, ACKEN banksel PIR1 BTFSC PIR1, SSPIF RETURN ; 完了? BTFSC PIR2, BCLIF RETURN ; 衝突? GOTO $-4 #endif ENDM ;---------------------------------------------------------------------------- LIST #endif