Bitbanga I2C, PIC12F629, ASM, DS1624 problem..

Elektronikrelaterade (på komponentnivå) frågor och funderingar.
Användarvisningsbild
squiz3r
Inlägg: 5424
Blev medlem: 5 september 2006, 20:06:22
Ort: Lund
Kontakt:

Bitbanga I2C, PIC12F629, ASM, DS1624 problem..

Inlägg av squiz3r »

Hej! Nu har jag äntligen tillgång till en labbhörna igen och har återupptagit PIC-programmerandet som jag varit utan i två år. För att ytterliggare förstärka retrokänslan så kör jag assembler som jag inte har hållit på med på många år..

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.
i2c-kommenterad.PNG
Här är en mer inzoomad bild av signalen:
i2c_close_up.PNG
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

	end
Kan ni hitta något fel som jag gör? Kan det vara de där fula spänningsspikarna som förvillar temperatursensorn?

Edit: Är det ett problem att mina klocksignaler inte har samma frekvens genom hela sändningen?

Mvh. Daniel
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Användarvisningsbild
squiz3r
Inlägg: 5424
Blev medlem: 5 september 2006, 20:06:22
Ort: Lund
Kontakt:

Re: Bitbanga I2C, PIC12F629, ASM, DS1624 problem..

Inlägg av squiz3r »

Ingen som har någon ide?? Ströningarna fick jag bukt med nu i alla fall, jag hade bara glömt att jorda den ena mätproben, så det var bara oscilloskopet som gjorde det. Men lite lösa funderingar bör väll någon ha? :)
victor_passe
Inlägg: 2436
Blev medlem: 28 januari 2007, 18:45:40
Ort: Kungsbacka

Re: Bitbanga I2C, PIC12F629, ASM, DS1624 problem..

Inlägg av victor_passe »

Det är nog inte detta som skapar problemet, men det ser ut som att du har lite väl veka pullup.
Ganska dålig stigtid.
ToPNoTCH
Inlägg: 5283
Blev medlem: 21 december 2009, 17:59:48

Re: Bitbanga I2C, PIC12F629, ASM, DS1624 problem..

Inlägg av ToPNoTCH »

Håller med VP.

Kanske kass avkoppling, eller veka pullups.

Vore kul att se hur det ser ut nu när störningarna är borta.
Användarvisningsbild
squiz3r
Inlägg: 5424
Blev medlem: 5 september 2006, 20:06:22
Ort: Lund
Kontakt:

Re: Bitbanga I2C, PIC12F629, ASM, DS1624 problem..

Inlägg av squiz3r »

Har bytt till 1k2 i pull-ups nu, det gav mycket bättre stigtid. Men fortfarande samma konstiga svar.. Får väll testa att sätta i ett i2c minne eller något istället och se om jag kan få något korrekt svar från det. Men den gröten som jag har på slutet, först hög datasignal för ett not-ack och sen låg för att sedan kunna sätta den hög igen som en stoppbit, ser det rätt ut? I och för sig borde det inte påverka datan i svaret eftersom den redan har skickats då..

Fortfarande tycker jag att signalen ser mycket brusigare ut på datoroscilloskopet än på oscilloskopets skärm, men det beror väll bara på att det är en ögonblicksbild, på oscilloskopets skärm blir bruset halvtransparent eftersom det hela tiden flyttar på sig..
i2c-ej-brus.PNG
i2c-ej-brus_zoom.PNG
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Användarvisningsbild
squiz3r
Inlägg: 5424
Blev medlem: 5 september 2006, 20:06:22
Ort: Lund
Kontakt:

Re: Bitbanga I2C, PIC12F629, ASM, DS1624 problem..

Inlägg av squiz3r »

Jag kopplade in ett 24LC08B-minne på busen nu också och det fungerade klockrent direkt. Så frågan är, har jag missförstått termometerns kommandon, eller är något annat knas?..

Kod för att skriva och läsa från minnet (ihop med funktionerna från föregående inlägg såklart):

Kod: Markera allt

	; Skriv data till minnet (0xF0 till adress 0x00)
	call		i2c_start
	movlw		b'10100000'				; 1010=id, x, 00 = block 0, 0 = write
	call		i2c_send_byte
	movlw		b'00000000'				; skriv till adress 0...
	call		i2c_send_byte
	movlw		0xF0
	call		i2c_send_byte
	call		i2c_stop
	call		delay

	; Läs data från minnet (adress 0x00) om och om igen...
loop
	call		i2c_start
	movlw		b'10100000'				; 1010=id, x, 00 = block 0, 0 = write (adress)
	call		i2c_send_byte
	movlw		b'00000000'				; Läs adress 0...
	call		i2c_send_byte
	call		i2c_start				; Ny startbit...
	movlw		b'10100001'				; Läs!
	call		i2c_send_byte
	call		i2c_receive_byte_no_ack
	movwf		dat
	call		i2c_stop

	; Kolla om  mottagen data är 0xF0..
	bcf			STATUS,Z
	movlw		0xF0
	subwf		dat
	btfsc		STATUS,Z
	bsf			led
	btfss		STATUS,Z
	bcf			led

	call		delay
	goto		loop
Edit: DS1624 följer inte riktigt I2C-standarden pga att den ej fördröjer SDA relativt SCK. Hittade detta i appnoten länkad till här under. Detta ska dock inte medföra problem för mig då jag fördröjer SDA rejält efter att jag sänkt SCK... (Tänkte bara nämna det nu när jag hittat det ifall någon annan nån gång får problem med DS1624..)
AppNote

Edit2: Att skriva och läsa från DS1624'ans inbyggda EEPROM går också utmärkt... Bara temperaturläsning och läsning av statusreg. som inte blir rätt då..
ToPNoTCH
Inlägg: 5283
Blev medlem: 21 december 2009, 17:59:48

Re: Bitbanga I2C, PIC12F629, ASM, DS1624 problem..

Inlägg av ToPNoTCH »

Det är ju som vanligt svårt att sätta sig in i andras kod och projekt.

En sak som jag reagerar på är att du i kommentaren för den rad du adresserar chippet skriver

Kod: Markera allt

movlw      b'10011110'            ; Adress till en DS1624 med samtliga ingångar jordade.. + WRITE
Vad jag kan se så är adresspinnarna inte inverterade, så om även adresspinnarna är jordade (enlig kommentaren) så borde du rimligtvis adressera chippet med b'10010000'
Användarvisningsbild
squiz3r
Inlägg: 5424
Blev medlem: 5 september 2006, 20:06:22
Ort: Lund
Kontakt:

Re: Bitbanga I2C, PIC12F629, ASM, DS1624 problem..

Inlägg av squiz3r »

Nu är det löst!

(ToPNoTCH: Hoppsan, det har du rätt i! Men det är kommentaren som är felaktig. Pinnarna är spänningssatta. Konstigt att man alltid lyckas missa något sånt trots alla gånger man läser igenom för att försäkra sig om att det är rätt innan man postar...)

Problem 1: Även om den är inställd på kontinuerlig temp.mätning måste man skicka START CONVERT T [0xEE] för att den skall börja. Den håller sedan på tills man skickar en stop convert T.

Problem 2: Läsning av config reg. skall (såklart! :wall:) gå till enligt:
skicka adress + write
skicka 0xAC (acces config)
skicka upprepad startbit
skicka adress + read
ta emot en byte

Dock är min configbyte fortfarande lite knasig.. Jag läser av den som 00001010 när den enligt databladet skall vara DONE, 1, 0, 0, 1, 0, 1, 1SHOT dvs den näst första biten som alltid skall vara en etta är egentligen en nolla... Men what ever.. :)

Tack!
Skriv svar