ToFセンサVL6180とPIC12F629を使った近接スイッチのプロトタイプができました。以下、動作の様子、42秒ほどの短い動画です。
点灯している赤色LEDの代わりにSSR(Solid State Relay)を繋ぐことでLED照明のスイッチにします。
以下、ソースコードです。バグがあるかも知れません。無保証です。
VL6180Xの初期化とコンフィグはarduinoライブラリのソースを参考にしていますが、これで十分なのか過剰なのか理解できていません。データシートが英語で87ページもあって全ては読めませんでした。読んでも理解できたか不明ですが。一応動いているようなので趣味で使うにはOKとしてます。
;---------------------------------------------------------------------
; TOF近接センサVL6180Xを使った非接触スイッチ
;
; 2026.02.22 naka
; 1. 概要
; 近接センサの前で手をかざすとオンオフ動作するスイッチ
; ・距離は150mm位まではOK(動作確認時190mm程度までは反応した)#defineで設定
; ・スイッチ動作はオルタネート(一度近づくとオン、一旦離れてもう一度でオフ)
; ・距離測定は0.1秒毎、オンオフ動作時は1秒後に確認(チャタリング的な動作を避けるため)
;
; 2. ピンアサイン
;
; (1). GP0 [in] : (ICSP DAT)
; (2). GP1 [in] : (ICSP CLK)
; (3). GP2 [out]: LED(デバッグ時に使用;最終的にSSRに置き換える)
; (4). GP3 [in] : (ICSP VPP)
; (5). GP4 [in] : I2C SDA
; (6). GP5 [in] : I2C SCL
;
; 3. 備考
; ・動作クロック :内蔵OSC 4MHz
; ・電源 :3V(TOFセンサが2.8-3.0Vなので)
;
; 4. 改版履歴
; 2026.02.14 new
; 2026.02.22 色々修正
;
;---------------------------------------------------------------------
;---------------------------------------------------------------------
; デバイス定義
;---------------------------------------------------------------------
list P=12F629
include <P12F629.INC>
__config _INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_ON & _MCLRE_OFF & _BODEN_OFF & _CP_OFF
ERRORLEVEL -302 ;アセンブル時のバンク警告メッセージ抑制
;---------------------------------------------------------------------
; ピン定義
;---------------------------------------------------------------------
#define LED 2
#define SDA 4
#define SCL 5
;---------------------------------------------------------------------
; TOFセンサ VL6180X I2Cアドレス
;---------------------------------------------------------------------
#define TOFADDR 0x52
;---------------------------------------------------------------------
; TOFセンサが反応する距離(mm) これより近いとオン/オフする
;---------------------------------------------------------------------
#define ACTDIST D'150'
;---------------------------------------------------------------------
; 変数レジスタの定義
;---------------------------------------------------------------------
WAIT1 EQU H'20'
WAIT2 EQU H'21'
CNT EQU H'22'
TMP EQU H'23'
CNT1 EQU H'24'
CNT2 EQU H'25'
CNT3 EQU H'26'
BUFF EQU H'27' ; 27-2B (LCD 5文字分)
;
binH EQU H'30'
binL EQU H'31'
bcdH EQU H'32'
bcdM EQU H'33'
bcdL EQU H'34'
counter EQU H'35'
temp EQU H'36'
;
OFFSET EQU H'37'
RANGE EQU H'38'
TIMOUTH EQU H'39'
TIMOUTL EQU H'3A'
TOGGLE EQU H'3B' ; 0ビット:トグル、1ビット:前回状態
; H'40'からI2C通信に利用(下の方で定義)
;
;---------------------------------------------------------------------
; マクロ
;---------------------------------------------------------------------
; TOFセンサ8ビットレジスタ設定
REG8BIT MACRO IDXH,IDXL,DATA
RETLW IDXH
RETLW IDXL
RETLW DATA
ENDM
; TOFセンサ16ビットレジスタ設定
REG16BIT MACRO IDXH,IDXL,DATAH,DATAL
RETLW IDXH
RETLW IDXL
RETLW DATAH
RETLW DATAL
ENDM
;
; TOFセンサレジスタ書き込み
WTREG MACRO HIGH,LOW,DATA
MOVLW TOFADDR
CALL I2CWSTART
MOVLW HIGH
MOVWF datao
CALL TX
MOVLW LOW
MOVWF datao
CALL TX
MOVLW DATA
MOVWF datao
CALL TX
CALL I2CSTOP
ENDM
RDREG MACRO HIGH,LOW
MOVLW TOFADDR
CALL I2CWSTART
MOVLW HIGH
MOVWF datao
CALL TX
MOVLW LOW
MOVWF datao
CALL TX
CALL I2CSTOP
;
MOVLW TOFADDR
CALL I2CRSTART
CALL RX
CALL I2CSTOP
ENDM
;
;---------------------------------------------------------------------
; リセットベクタ
;---------------------------------------------------------------------
ORG 00H ; リセット時の飛び込み先
GOTO MAIN ;
;
ORG 04H ; 割り込み時の飛び込み先
;---------------------------------------------------------------------
; 割り込み処理
;---------------------------------------------------------------------
INTRUPT
RETFIE
;---------------------------------------------------------------------
; メイン処理
;---------------------------------------------------------------------
MAIN
CALL DEVINIT
CALL LCDINIT
;
CALL VL6180INIT
CALL VL6180CONFIG
;
MOVLW D'255'
CALL DSPLCD
;
CLRF TOGGLE
MAIN_LP
;
CLRF RANGE
CALL READRANGE ; 測定
;
MOVF RANGE,W
SUBLW ACTDIST ; アクティブか否かチェック
BTFSS STATUS,C
GOTO INACT
; 前回もアクティブなら何もしない(そうしないと点滅する)
BTFSC TOGGLE,1
GOTO MAININTR
BSF TOGGLE,1 ; 前回アクティブではないのでトグル動作
GOTO TOGGLESW
;
INACT
BCF TOGGLE,1
GOTO MAININTR
TOGGLESW
MOVF TOGGLE,W
XORLW H'01'
MOVWF TOGGLE
;
BTFSS TOGGLE,0
GOTO $+3
BSF GPIO,LED
GOTO $+2
BCF GPIO,LED
;
MOVF RANGE,W
CALL DSPLCD ; LCD表示
;
CALL W05S ; トグル動作時は1秒待つ
CALL W05S
GOTO MAIN_LP
;
MAININTR
CALL W100MS ; 100ミリ秒ごとに測定
GOTO MAIN_LP
;
;---------------------------------------------------------------------
; 初期化
;---------------------------------------------------------------------
DEVINIT
CLRF INTCON ;全割込み禁止
;
BANKSEL CMCON
MOVLW B'00000111' ; GP0-2をデジタルI/Oに設定
MOVWF CMCON ; デフォルトはコンパレータ
; BANKSEL 1
; CALL 3FFH ; 内部OSCのキャリブレーションデータ
; MOVWF OSCCAL ; OSCCALレジスタにセット
BANKSEL TRISIO
MOVLW B'00000011' ; RA0,RA1 input
MOVWF TRISIO
BANKSEL GPIO
;
BCF GPIO,LED
;
RETURN
;
;---------------------------------------------------------------------
; 文字列表示
;---------------------------------------------------------------------
DSPTXT
MOVLW D'5'
MOVWF CNT
CLRF TMP
MOVLW BUFF
MOVWF FSR
;
MOVLW H'80' + H'0B' ; LCD1行目先頭へ
CALL LCDCMD
DSPTXTLP
MOVF CNT,W
DSPTXT1
MOVF INDF,W
CALL LCDDATA
INCF FSR,F
;
DECFSZ CNT,F
GOTO DSPTXTLP
;
RETURN
;---------------------------------------------------------------------
; LCD初期化(データシート通り)
;---------------------------------------------------------------------
LCDINIT
CALL W20MS ; 電源が安定するまでの待ち時間
CALL W20MS
;
MOVLW H'38' ; Function set
CALL LCDCMD
;
MOVLW H'39' ; Functino set
CALL LCDCMD
;
MOVLW H'14' ; Intrenal OSC frequency
CALL LCDCMD
;
; ; Contrast= B'10 1000' = D'40'
MOVLW H'70'+H'08' ; Contrast set
CALL LCDCMD
;
MOVLW H'54'+H'02' ; Power/ICON/Contrast control
; MOVLW H'51' ; +5V
CALL LCDCMD
;
MOVLW H'6C' ; Follower control
CALL LCDCMD
CALL W200MS
;
MOVLW H'38' ; Function set
CALL LCDCMD
;
MOVLW H'0C' + H'01' ; Display ON/OFF control
CALL LCDCMD
;
MOVLW H'01' ; Clear Display
CALL LCDCMD
;
RETURN
;
;---------------------------------------------------------------------
; LCDコマンド (W:CMD)
;---------------------------------------------------------------------
LCDCMD
MOVWF TMP ; 一時退避
;
MOVLW H'7C' ; I2Cアドレス
CALL I2CWSTART
MOVLW H'00' ; Command (RS=0)
MOVWF datao
CALL TX
MOVF TMP,W
MOVWF datao
CALL TX
CALL I2CSTOP
;
MOVLW H'01' ; Clear Display
SUBWF TMP,W
BTFSC STATUS,Z
GOTO LCDW1MS
MOVLW H'02' ; Return Home
SUBWF TMP,W
BTFSC STATUS,Z
GOTO LCDW1MS
;
CALL W27US ; Normal command
RETURN
LCDW1MS
CALL W1MS
RETURN
;
;---------------------------------------------------------------------
; LCD データ(Wレジ内容をLCDに書き込む)
;---------------------------------------------------------------------
LCDDATA
MOVWF TMP ; 書き込みデータ一時退避
;
MOVLW H'7C'
CALL I2CWSTART
;
MOVLW H'40' ; Data (RS=1)
MOVWF datao
CALL TX
;
MOVF TMP,W
MOVWF datao
CALL TX
;
CALL I2CSTOP
;
RETURN
;
;---------------------------------------------------------------------
; LCD表示(入力W)
;---------------------------------------------------------------------
DSPLCD
CLRF binH
MOVWF binL
CALL _bin2bcd ; BCD変換
;
MOVF bcdM,W
ANDLW H'0F'
ADDLW '0'
MOVWF BUFF
SWAPF bcdL,W
ANDLW H'0F'
ADDLW '0'
MOVWF BUFF+1
MOVF bcdL,W
ANDLW H'0F'
ADDLW '0'
MOVWF BUFF+2
;
MOVLW 'm'
MOVWF BUFF+3
MOVLW 'm'
MOVWF BUFF+4
;
; ゼロサプレス(上位桁が0なら空白にする)
MOVF BUFF,W
SUBLW '0'
BTFSS STATUS,Z
GOTO DISP
MOVLW ' '
MOVWF BUFF
MOVF BUFF+1,W
SUBLW '0'
BTFSS STATUS,Z
GOTO DISP
MOVLW ' '
MOVWF BUFF+1
DISP
CALL DSPTXT
RETURN
;
;---------------------------------------------------------------------
; VL6180レジスタindex (#define名は32文字まで)
;---------------------------------------------------------------------
#define READOUT__AVERAGING_SAMPLE_PERIOD 0x01,0x0A
#define SYSALS__ANALOGUE_GAIN 0x00,0x3F
#define SYSALS__INTEGRATION_PERIOD 0x00,0x40
#define SYSALS__INTERMEASUREMENT_PERIOD 0x00,0x3E
#define SYSRANGE__VHV_REPEAT_RATE 0x00,0x31
#define SYSRANGE__VHV_RECALIBRATE 0x00,0x2E
#define SYSRANGE__INTERMEASUREMENT_PERIO 0x00,0x1B
#define SYSRANGE__MAX_CONVERGENCE_TIME 0x00,0x1C
#define SYSTEM__INTERRUPT_CONFIG_GPIO 0x00,0x14
#define SYSTEM__INTERRUPT_CLEAR 0x00,0x15
#define INTERLEAVED_MODE__ENABLE 0x02,0xA3
#define RESULT__RANGE_STATUS 0x00,0x4D
#define RESULT__INTERRUPT_STATUS_GPIO 0x00,0x4F
#define SYSRANGE__START 0x00,0x18
#define RESULT__RANGE_VAL 0x00,0x62
;
;---------------------------------------------------------------------
; VL6180初期化(メモリ節約のためベタ書きではなくループを回した)
;---------------------------------------------------------------------
VL6180INIT
CALL W20MS
CLRF OFFSET
CALL REG8BITDT
MOVWF CNT1 ; 設定パラメタ数
VLINIT_LP1
MOVLW H'52' ; アドレス
CALL I2CWSTART
MOVLW D'3' ; indexHigh, indexLow, data の3バイトを送る
MOVWF CNT2
VLINIT_LP2
INCF OFFSET,F
CALL REG8BITDT
MOVWF datao
CALL TX ; I2C送信
DECFSZ CNT2,F
GOTO VLINIT_LP2
;
CALL I2CSTOP
;
DECFSZ CNT1,F
GOTO VLINIT_LP1
;
RETURN
REG8BITDT ; 以下のテーブルから順に取り出す
ORG H'200'
MOVLW H'02'
MOVWF PCLATH
MOVF OFFSET,W
ADDWF PCL,F
RETLW D'31' ; 31パラメタ
REG8BIT 0x02,0x07,0x01 ; indexHigh, indexLow, data
REG8BIT 0x02,0x08,0x01
REG8BIT 0x00,0x96,0x00
REG8BIT 0x00,0x97,0xFD ; RANGE_SCALER = 253
REG8BIT 0x00,0xE3,0x01
REG8BIT 0x00,0xE4,0x03
REG8BIT 0x00,0xE5,0x02
REG8BIT 0x00,0xE6,0x01
REG8BIT 0x00,0xE7,0x03
REG8BIT 0x00,0xF5,0x02
REG8BIT 0x00,0xD9,0x05
REG8BIT 0x00,0xDB,0xCE
REG8BIT 0x00,0xDC,0x03
REG8BIT 0x00,0xDD,0xF8
REG8BIT 0x00,0x9F,0x00
REG8BIT 0x00,0xA3,0x3C
REG8BIT 0x00,0xB7,0x00
REG8BIT 0x00,0xBB,0x3C
REG8BIT 0x00,0xB2,0x09
REG8BIT 0x00,0xCA,0x09
REG8BIT 0x01,0x98,0x01
REG8BIT 0x01,0xB0,0x17
REG8BIT 0x01,0xAD,0x00
REG8BIT 0x00,0xFF,0x05
REG8BIT 0x01,0x00,0x05
REG8BIT 0x01,0x99,0x05
REG8BIT 0x01,0xA6,0x1B
REG8BIT 0x01,0xAC,0x3E
REG8BIT 0x01,0xA7,0x1F
REG8BIT 0x00,0x30,0x00
REG8BIT 0x00,0x16,0x00 ;SYSTEM__FRESH_OUT_OF_RESET
;
;---------------------------------------------------------------------
; VL6180 configureDefault
;---------------------------------------------------------------------
VL6180CONFIG
CALL W20MS
CLRF OFFSET
CALL CONFIGDT
MOVWF CNT1 ; 設定パラメタ数
VLCONFIG_LP1
MOVLW H'52' ; アドレス
CALL I2CWSTART
MOVLW D'3' ; indexHigh, indexLow, data の3バイトを送る
MOVWF CNT2
VLCONFIG_LP2
INCF OFFSET,F
CALL CONFIGDT
MOVWF datao
CALL TX ; I2C送信
DECFSZ CNT2,F
GOTO VLCONFIG_LP2
;
CALL I2CSTOP
;
DECFSZ CNT1,F
GOTO VLCONFIG_LP1
;
; テーブルのラストにある16bitパラメタ1個のみ
MOVLW D'4' ; indexHigh, indexLow, dataHigh, dataLow の4バイトを送る
MOVWF CNT2
VLCONFIG_LP3
INCF OFFSET,F
CALL CONFIGDT
MOVWF datao
CALL TX ; I2C送信
DECFSZ CNT2,F
GOTO VLCONFIG_LP3
;
CALL I2CSTOP
;
RETURN
;
CONFIGDT ; 以下のテーブルから順に取り出す
MOVLW H'02'
MOVWF PCLATH
MOVF OFFSET,W
ADDWF PCL,F
RETLW D'9' ; 8bit 9パラメタ + 16bit 1パラメタ
REG8BIT READOUT__AVERAGING_SAMPLE_PERIOD,0x30
REG8BIT SYSALS__ANALOGUE_GAIN,0x46
REG8BIT SYSRANGE__VHV_REPEAT_RATE,0xFF
REG8BIT SYSRANGE__VHV_RECALIBRATE,0x01
REG8BIT SYSRANGE__INTERMEASUREMENT_PERIO,0x09 ; 100ms
REG8BIT SYSALS__INTERMEASUREMENT_PERIOD,0x31 ; 500ms
REG8BIT SYSTEM__INTERRUPT_CONFIG_GPIO,0x24
REG8BIT SYSRANGE__MAX_CONVERGENCE_TIME,0x31 ; 49ms
REG8BIT INTERLEAVED_MODE__ENABLE,0x00
REG16BIT SYSALS__INTEGRATION_PERIOD,0x00,0x63 ; 16bitパラメタ(1個のみ)
;
;---------------------------------------------------------------------
; VL6180 readRange
;---------------------------------------------------------------------
READRANGE
; デバイスがreadyになるまで待つ
RDREG RESULT__RANGE_STATUS
MOVF datai,W
ANDLW H'01'
BTFSC STATUS,Z
GOTO READRANGE
;
; 測定開始フラグ設定
WTREG SYSRANGE__START,0x01
;
CLRF TIMOUTH ; タイムアウトカウント用
CLRF TIMOUTL
READRANGLP
CALL CHKTIMEOUT ; タイムアウト確認
BTFSS STATUS,Z
GOTO READRANGE2
MOVLW D'255' ; タイムアウト
MOVWF RANGE
RETURN
;
READRANGE2
; 測定完了確認
RDREG RESULT__INTERRUPT_STATUS_GPIO
MOVF datai,W
ANDLW 0x07
SUBLW 0x04
BTFSS STATUS,Z
GOTO READRANGLP
;
; 値を読み出す
RDREG RESULT__RANGE_VAL
MOVF datai,W
MOVWF RANGE
;
; 割り込みフラグクリア
WTREG SYSTEM__INTERRUPT_CLEAR, 0x01
;
RETURN
;
;---------------------------------------------------------------------
; センサのタイムアウトチェック(500ms)
; 1回の測定にざっと200usかかるとして 500ms/200us ... TIMOUTH=10
;---------------------------------------------------------------------
CHKTIMEOUT
MOVF TIMOUTL,W
ADDLW D'1'
MOVWF TIMOUTL
BTFSS STATUS,Z
RETURN
;
MOVF TIMOUTH,W
ADDLW D'1'
MOVWF TIMOUTH
SUBLW D'10' ; Zフラグを持ってリターン
RETURN
;---------------------------------------------------------------------
; ウェイト色々
;---------------------------------------------------------------------
W27US
MOVLW D'7'
MOVWF WAIT1
W27USLP
DECFSZ WAIT1,F
GOTO W27USLP
NOP
RETURN
;
W1MS
MOVLW D'110'
MOVWF WAIT1
W1MSLP
GOTO $+1
GOTO $+1
GOTO $+1
DECFSZ WAIT1,F
GOTO W1MSLP
GOTO $+1
GOTO $+1
NOP
RETURN
;
W20MS
MOVLW D'20'
MOVWF WAIT2
W20MSLP
CALL W1MS
DECFSZ WAIT2,F
GOTO W20MSLP
RETURN
;
W100MS
MOVLW D'100'
MOVWF WAIT2
W100MSLP
CALL W1MS
DECFSZ WAIT2,F
GOTO W100MSLP
RETURN
;
W200MS
MOVLW D'200'
MOVWF WAIT2
W200MSLP
CALL W1MS
DECFSZ WAIT2,F
GOTO W200MSLP
RETURN
;
W05S
MOVLW D'100'
MOVWF WAIT2
W05SLP
CALL W1MS
CALL W1MS
CALL W1MS
CALL W1MS
CALL W1MS
DECFSZ WAIT2,F
GOTO W05SLP
RETURN
;
;---------------------------------------------------------------------
; I2Cアクセスルーチン
; 流用元:Microchip Applicatin Note : AN982
; Interfacing I2C Serial EEPROMs to PIC10 and PIC12 Drivers
;---------------------------------------------------------------------
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;
; Filename: i2c_routines.inc
; Date: March 21, 2005
; File Version: 1.0
; Assembled using: MPLAB IDE 7.00.00.0
;
; Author: Chris Parris
; Company: Microchip Technology, Inc.
;
;*******************RAM register definitions**********************
#define STARTRAM 0x40 ; Start RAM at address 0x40
cblock STARTRAM
buffer ; Transfer/Receive bit buffer
datai ; Data input byte buffer
datao ; Data output byte buffer
bitcount ; Bit loop counter
bytecount ; Byte loop counter
addressH ; Word address pointer
addressL ; Word address pointer
loops ; Delay loop counter
loops2 ; Delay loop counter
pollcnt ; Polling loop counter
i2caddr
endc
;*******************Bit definitions*******************************
DO equ 0 ; TX/RX buffer output bit
DI equ 1 ; TX/RX buffer input bit
ACKB equ 2 ; ACK/NO ACK select bit
;*******************Delay Macros**********************************
; Each macro delay for 1 inst. cycle less than
; required, as the instruction immediately
; before the macro call provides 1 inst. cycle.
;*****************************************************************
THIGH macro ; Clock high time delay (5 us)
goto $+1 ; 2-inst. cycle delay (2 us)
goto $+1 ; 2-inst. cycle delay (2 us)
nop ; 1us
endm
THDSTA macro ; Start condition hold time delay (5 us)
goto $+1 ; 2-inst. cycle delay (2 us)
goto $+1 ; 2-inst. cycle delay (2 us)
nop ; 1us
endm
TSUSTA macro ; Start condition setup time delay (5 us)
goto $+1 ; 2-inst. cycle delay (2 us)
goto $+1 ; 2-inst. cycle delay (2 us)
nop ; 1us
endm
TSUSTO macro ; Stop condition setup time delay (5 us)
goto $+1 ; 2-inst. cycle delay (2 us)
goto $+1 ; 2-inst. cycle delay (2 us)
nop ; 1us
endm
TAA macro ; Output valid from clock delay (4 us)
goto $+1 ; 2-inst. cycle delay (2 us)
goto $+1 ; 2-inst. cycle delay (2 us)
endm
;-------------------------------------------------------------------
; I2Cアクセス
;-------------------------------------------------------------------
I2CWSTART
MOVWF i2caddr ; I2Cアドレス退避
call BSTART ; Generate start bit
; Now send the control byte
; for a write, to set address
movf i2caddr,W ; I2Cアドレス
movwf datao ; Copy control byte to buffer
call TX ; Output control byte to device
RETURN
I2CSTOP
CALL NOACK
call BSTOP ; Generate stop bit
RETURN
;
I2CRSTART
IORLW H'01'
MOVWF i2caddr ; I2Cアドレス退避
call BSTART ; Generate start bit
; Now send the control byte
; for a write, to set address
movf i2caddr,W
movwf datao ; Copy control byte to buffer
call TX ; Output control byte to device
RETURN
;*******************Start bit subroutine**************************
; This routine generates a Start condition
; (high-to-low transition of SDA while SCL
; is still high.
;*****************************************************************
BSTART
bsf GPIO,SCL ; Make sure SCL is high
TSUSTA ; Start condition setup time delay
BANKSEL 1
BCF TRISIO,SDA ; Configure SDA to be an output
BANKSEL 0
bcf GPIO,SDA ; Pull SDA low to initiate
; Start condition
THDSTA ; Start condition hold time delay
bcf GPIO,SCL ; Bring SCL low in preparation
; for data transfer
BANKSEL 1
BSF TRISIO,SDA ; Configure SDA to be an input
BANKSEL 0
retlw 0
;*******************Stop bit subroutine***************************
; This routine generates a Stop condition
; (low-to-high transition of SDA while SCL
; is still high.
;*****************************************************************
BSTOP
BANKSEL 1
BCF TRISIO,SDA ; Configure SDA to be an output
BANKSEL 0
bcf GPIO,SDA ; Pull SDA low
bsf GPIO,SCL ; Make sure SCL is high
TSUSTO ; Stop condition setup time delay
BANKSEL 1
BSF TRISIO,SDA ; Configure SDA to be an input
BANKSEL 0
retlw 0
;*******************Bit output subroutine*************************
; This routine outputs bit 'DO' in 'buffer' to
; the serial EEPROM device.
;*****************************************************************
BITOUT
bcf GPIO,SCL ; Make sure SCL is low
btfss buffer,DO ; Check for state of bit to xmit
goto bitlow ; If bit is low, pull SDA low
clockout ; If bit is high, leave SDA high
bsf GPIO,SCL ; Bring SCL high to begin transfer
THIGH ; Clock high time delay
bcf GPIO,SCL ; Bring SCL low again
BANKSEL 1
BSF TRISIO,SDA ; Configure SDA to be an input
BANKSEL 0
retlw 0
bitlow
BANKSEL 1
BCF TRISIO,SDA ; Configure SDA to be an output
BANKSEL 0
bcf GPIO,SDA ; Pull SDA low
goto clockout
;*******************Bit input subroutine**************************
; This routine inputs a bit of data from the
; serial EEPROM device, and stores it in bit
; 'DO' of 'buffer'.
;*****************************************************************
BITIN
bcf GPIO,SCL ; Make sure SCL is low
BANKSEL 1
BSF TRISIO,SDA ; Configure SDA to be an input
BANKSEL 0
bsf buffer,DI ; Assume input bit is high
bsf GPIO,SCL ; Bring SCL high to begin transfer
TAA ; Output valid from clock delay
btfss GPIO,SDA ; Check for state of SDA bit
bcf buffer,DI ; If SDA is low, set bit low
bcf GPIO,SCL ; Bring SCL low again
retlw 0
;*******************Data transmit subroutine**********************
; This routine transmits the byte of data
; stored in 'datao' to the serial EEPROM
; device. Instructions are also in place
; to check for an ACK bit, if desired.
; Just replace the 'goto' instruction,
; or create an 'ackfailed' label, to provide
; the functionality.
;*****************************************************************
TX
movlw .8
movwf bitcount ; Initialize loop counter to 8
txlp
bsf buffer,DO ; Assume output bit is high
btfss datao,7 ; Check state of next output bit
bcf buffer,DO ; If low, set buffer bit low
call BITOUT ; Call routine to output bit
rlf datao,F ; Rotate datao left for next bit
decfsz bitcount,F ; Decrement counter, check if done
goto txlp ; Keep looping
CALL ACK
retlw 0
;*******************Data receive subroutine***********************
; This routine reads in one byte of data from
; the serial EEPROM device, and stores it in
; 'datai'. It then responds with either an
; ACK or a NO ACK bit, depending on the value
; of 'ACKB' in 'buffer'.
;*****************************************************************
RX
clrf datai ; Clear input buffer
movlw .8
movwf bitcount ; Initialize loop counter to 8
bcf STATUS,C ; make sure carry bit is low
rxlp
rlf datai,F ; Rotate datai 1 bit left
call BITIN ; Read a bit
btfsc buffer,DI
bsf datai,0 ; Set bit 0 if necessary
decfsz bitcount,F ; 8 bits done?
goto rxlp ; If not, do another
call BITIN ; Call routine to read ACK bit
RETLW 0
ACK
bcf buffer,DO ; If ACKB = 1, send ACK (DO = 0)
call BITOUT ; Send bit
retlw 0
NOACK
bsf buffer,DO ; If ACKB = 1, send ACK (DO = 0)
call BITOUT ; Send bit
retlw 0
;
;---------------------------------------------------------------------
;---------------------------------------------------------------------
; 16-bit binary to BCD conversion
; pete griffiths 2007
; http://picprojects.org.uk/projects/pictips.htm
;
; These file register variables will
; need to be defined elsewhere.
; binH
; binL
; bcdH
; bcdM
; bcdL
; counter
; temp
;
; binH, binL contain the binary value to
; convert. Conversion process destroys contents.
; Result is in bcdH, bcdM, bcdL on return.
; Call _bin2bcd to perform conversion.
;
; Executes in 454 instructions
_bin2bcd movlw d'16'
movwf counter
clrf bcdL
clrf bcdM
clrf bcdH
_repeat rlf binL,F
rlf binH,F
rlf bcdL,F
rlf bcdM,F
rlf bcdH,F
decfsz counter,F
goto _adjust
return
_adjust movlw d'14'
subwf counter,W
skpnc
goto _repeat
movfw bcdL
addlw 0x33
movwf temp
movfw bcdL
btfsc temp,3
addlw 0x03
btfsc temp,7
addlw 0x30
movwf bcdL
movfw bcdM
addlw 0x33
movwf temp
movfw bcdM
btfsc temp,3
addlw 0x03
btfsc temp,7
addlw 0x30
movwf bcdM
goto _repeat
; we only need to do the test and add +3 for
; the low and middle bcd variables since the
; largest binary value is 0xFFFF which is
; 65535 decimal so the high bcd byte variable
; will never be greater than 6.
; We also skip the tests for the first two
; shifts.
;---------------------------------------------------------------------
END
;---------------------------------------------------------------------
; 終わり
;---------------------------------------------------------------------





















