Min tanke är att med en PIC12F629 läsa av temperaturen från en DS1624 (Datablad) via I2c kommunikation. 12F629 har ju ingen hårdvaru I2c, så det är bitbanging som gäller. I2C har jag aldrig testat innan, men jag har läst på en hel del så jag tror jag har ganska bra koll på hur det ska se ut.
Min DS1624 är kopplad med A0-A2 till spänningsmatningen (5v) och SDA kopplad med pull-up på 10k till GP5 på min PIC och SCLK är kopplad med lika stor pull-up till GP4.
Om jag förstår databladet rätt så är DS1624 inställd från fabrik på att göra konstanta temperaturmätningar och START CONVERT T kommandot skall alltså ej användas. För att få temperaturen bör jag alltså bara skicka START, ADRESS + R/W = 0, READ TEMPERARURE (AAh), UPPREPAD START, ADRESS + R/W = 1, DS1624 SKICKAR HÖG BYTE, DS1624 SKICKAR LÅG BYTE, STOP?
Mitt försök att skicka detta kan ses på bilden nedan. Som synes får jag bara två bytes med 00h tillbaks..
Signalen ser inte så fin ut heller... Den ser dock betydligt värre ut på denna datorversionen av bilden än vad den gör direkt på oscilloskopet.. Men jag har kopplat av både PIC;en och DS1624;an med varsin 330nF konding. Om jag strömförsörjer från PICKIT2 eller från labbagget spelar ingen roll alls.. Allt sitter på ett breadboard. Här är en mer inzoomad bild av signalen: Min kod till processorn ser ut såhär:
Kod: Markera allt
list p=12F629
include <p12f629.inc>
__config _MCLRE_ON & _CP_OFF & _WDT_OFF & _INTRC_OSC_NOCLKOUT
; Definiera pinnar...
#define led GPIO,0
#define ledTris TRISIO,0
#define sda GPIO,5
#define sdaTris TRISIO,5
#define sclk GPIO,4
#define sclkTris TRISIO,4
; Definiera adress till variabler..
dly1 equ 0x20
dly2 equ dly1 + 1
dly3 equ dly2 + 1
i2cByte equ dly3 + 1
; Starta på vektor 0 och hoppa över int.vektorn (4)...
org 0x0000
goto start
start org 0x05
movlw 0xff
movwf CMCON ; Stäng av komparator..
bsf STATUS,RP0 ; Gå till bank 1..
bcf ledTris ; Sätt LED till utgång...
bcf STATUS,RP0 ; Bank 0...
call init_i2c ; Sätt SDA och SCLK till högimpedans..
loop
call i2c_start ; Skicka startbit
movlw b'10011110' ; Adress till en DS1624 med samtliga ingångar jordade.. + WRITE
call i2c_send_byte ; Skicka data i W-reg.
movlw 0xaa ; Kommando för att läsa temperatur..
call i2c_send_byte
call i2c_start ; Upprepad start..
movlw b'10011111' ; Adress + READ
call i2c_send_byte
call i2c_receive_byte ; Ta emot första byte och skicka ACK på den..
call i2c_receive_byte_no_ack ; Ta emot andra byte, skicka inte ACK.
call i2c_stop ; Skicka stoppbit.
call delay
goto loop
; **********************************
; DELAY ROUNTINE
delay
movlw 10
movwf dly2
delay_2
movlw 0
movwf dly1
delay_1
decfsz dly1,1
goto delay_1
decfsz dly2,1
goto delay_2
return
; ***********************************
; I2C BITBANGING
sda_high_imp
bsf STATUS,RP0
bsf sdaTris
bcf STATUS,RP0
return
sda_low_imp
bcf sda
bsf STATUS,RP0
bcf sdaTris
bcf STATUS,RP0
return
sclk_high_imp
bsf STATUS,RP0
bsf sclkTris
bcf STATUS,RP0
return
sclk_low_imp
bcf sclk
bsf STATUS,RP0
bcf sclkTris
bcf STATUS,RP0
return
init_i2c
call sda_high_imp ; Gör till ingång (låt busen gå hög)
bcf sda
call sclk_high_imp
bcf sclk
return
i2c_start ; Skicka startbit.
call sclk_high_imp
call i2c_dly
call sda_low_imp
call i2c_dly
call sclk_low_imp
call i2c_dly
return
i2c_stop ; Skicka stoppbit.
call sda_low_imp
call i2c_dly
call sclk_high_imp
call i2c_dly
call sda_high_imp
call i2c_dly
return
i2c_send_byte ; Lägger de åtta bitar på busen som finns i w-reg.
movwf i2cByte ; Spara data från W-reg till variabel.
; Skicka BIT7
movlw b'10000000'
call i2c_send_bit
;BIT6
movlw b'01000000'
call i2c_send_bit
;BIT5
movlw b'00100000'
call i2c_send_bit
;BIT4
movlw b'00010000'
call i2c_send_bit
;BIT3
movlw b'00001000'
call i2c_send_bit
;BIT2
movlw b'00000100'
call i2c_send_bit
;BIT1
movlw b'00000010'
call i2c_send_bit
;BIT0
movlw b'00000001'
call i2c_send_bit
; Ta emot en ack-bit ( Antar att slav skickar ACK och inte EJ-ACK, ingen kontroll sker...)
call i2c_dly
call sda_high_imp
call sclk_high_imp
call i2c_dly
call sclk_low_imp ; Sätt sclk låg men låt SDA vara hög..
return
i2c_send_bit ; Lägger en bit på busen, bit = i2cByte && W-reg.
bcf STATUS,Z ; Nolla zeroflaggan...
andwf i2cByte,0 ; Kolla bara på bit7.. (spara resultat i w)
btfsc STATUS,Z
call sda_low_imp ; Skicka en nolla...
btfss STATUS,Z
call sda_high_imp ; Skicka en etta...
call i2c_dly
call sclk_high_imp ; Skicka en klockpuls..
call i2c_dly
call sclk_low_imp
call i2c_dly
call sda_low_imp
return
i2c_receive_byte
call sda_high_imp
clrf i2cByte
; bit 7...
call sclk_high_imp
nop
btfsc sda
bsf i2cByte,7
call sclk_low_imp
call i2c_dly
; bit 6...
call sclk_high_imp
nop
btfsc sda
bsf i2cByte,6
call sclk_low_imp
call i2c_dly
; bit 5...
call sclk_high_imp
nop
btfsc sda
bsf i2cByte,5
call sclk_low_imp
call i2c_dly
; bit 4...
call sclk_high_imp
nop
btfsc sda
bsf i2cByte,4
call sclk_low_imp
call i2c_dly
; bit 3...
call sclk_high_imp
nop
btfsc sda
bsf i2cByte,3
call sclk_low_imp
call i2c_dly
; bit 2...
call sclk_high_imp
nop
btfsc sda
bsf i2cByte,2
call sclk_low_imp
call i2c_dly
; bit 1...
call sclk_high_imp
nop
btfsc sda
bsf i2cByte,1
call sclk_low_imp
call i2c_dly
; bit 0...
call sclk_high_imp
nop
btfsc sda
bsf i2cByte,0
call sclk_low_imp
call i2c_dly
; Skicka acknowledge-bit...
call sda_low_imp ; ack..
call sclk_high_imp
call i2c_dly
call sclk_low_imp
call sda_high_imp
return
i2c_receive_byte_no_ack
call sda_high_imp
clrf i2cByte
; bit 7...
call sclk_high_imp
nop
btfsc sda
bsf i2cByte,7
call sclk_low_imp
call i2c_dly
; bit 6...
call sclk_high_imp
nop
btfsc sda
bsf i2cByte,6
call sclk_low_imp
call i2c_dly
; bit 5...
call sclk_high_imp
nop
btfsc sda
bsf i2cByte,5
call sclk_low_imp
call i2c_dly
; bit 4...
call sclk_high_imp
nop
btfsc sda
bsf i2cByte,4
call sclk_low_imp
call i2c_dly
; bit 3...
call sclk_high_imp
nop
btfsc sda
bsf i2cByte,3
call sclk_low_imp
call i2c_dly
; bit 2...
call sclk_high_imp
nop
btfsc sda
bsf i2cByte,2
call sclk_low_imp
call i2c_dly
; bit 1...
call sclk_high_imp
nop
btfsc sda
bsf i2cByte,1
call sclk_low_imp
call i2c_dly
; bit 0...
call sclk_high_imp
nop
btfsc sda
bsf i2cByte,0
call sclk_low_imp
call i2c_dly
; Skicka EJ acknowledge-bit...
call sda_high_imp ; EJ ack..
call sclk_high_imp
call i2c_dly
call sclk_low_imp
call sda_high_imp
return
i2c_dly ; call + return = 2 + 2 = 4 Tcycle..
return
endEdit: Är det ett problem att mina klocksignaler inte har samma frekvens genom hela sändningen?
Mvh. Daniel
