Aus RN-Wissen.de
Version vom 9. August 2006, 17:44 Uhr von PicNick (Diskussion | Beiträge)

(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
Wechseln zu: Navigation, Suche
Laderegler Test Tueftler Seite

Bascom Software I2C Routinen

Beispiel 2313.bas

'----------------------------------------------
'   2313 oder was anderes als I2C Soft-Slave
'----------------------------------------------
'   PicNick was here  www.roboternetz.de
'----------------------------------------------
'   Das ist ein einfacher Sende- und Empfangs Slave
'----------------------------------------------
$crystal = 4000000                                ' Quarzfrequenz
$baud = 9600                                      'Baudrate für RS232 (Gewohnheit)

$hwstack = 48
$swstack = 16
$framesize = 16

Const Tmr_c_prescale = 64
Const Tmr_c_preload = 191

Const Tmr_c_divis = 1000

Config Timer0 = Timer , Prescale = Tmr_c_prescale 'Timer 1mS
On Timer0 Interrupt_ticker                        ' Timer for Timer Queue

Dim Timeout As Byte
Dim Timediv As Word

'-------------------------------------
'  Pin-definition  I2C
'-------------------------------------
Config I2cdelay = 5
Config Scl = Portd.3                              'Ports fuer IIC-Bus
Config Sda = Portd.2

'---------------------------  Library und definitionen ------------------
$include "MyI2c.BAS"

'-------------------------------------
'  Address-definition RNBFRA
'-------------------------------------

Const Pwr_adr = &H74                              'I2C Adress Powerport
Const Out_adr = &H72                              'I2C Adress Out PCF
Const Exp_adr = &H7E                              'I2C Adress PCF Expansion

Const Co1_adr = &H68                              'I2C Adress 2313    I
Const Co1_adrr = &H69                             'I2C Adress 2313    I

Const Mn1_adr = &H6A                              'I2C Adress Atmega  I
Const Mn1_adrr = &H6B                             'I2C Adress Atmega  I

Const Co2_adr = &H6C                              'I2C Adress 2313   II
Const Co2_adrr = &H6D                             'I2C Adress 2313   II

Const Mn2_adr = &H6E                              'I2C Adress Atmega II
Const Mn2_adrr = &H6F                             'I2C Adress Atmega II

Dim Sent_flag As Byte

Dim M32_byte(24) As Byte                          'I2C Buffer Senden & empfangen

   Enable Timer0

   Enable Interrupts

'---------------------------------------------
'
'---------------------------------------------
   I2cinit                                        ' Bascom soll auch was tun

   I2c_write = Varptr(m32_byte(1));               ' Data receive-Buffer
   I2c_read = Varptr(m32_byte(1));                ' Data send-Buffer

   Do
         Loadadr I2c_flag , Z
         Gosub I2c_get_addr                       ' I2C Adresse read
         Select Case I2c_addr
         Case Co1_adr:
            Loadadr I2c_flag , Z
            Gosub I2c_slave_rx_data               ' daten empfangen bis Stop/Rep
            Sent_flag = 1
            '------------------------------------
            ' WORKOUT Message
            '------------------------------------

         Case Co1_adrr:
            Loadadr I2c_flag , Z
            Gosub I2c_slave_tx_byte               ' daten senden bis NAK

         Case Else
            I2cinit
         End Select

         If Sent_flag = 1  And Timeout = 1 Then
            Sent_flag = 0
            Timeout = 0
            Gosub Out_transmit
         End If


   Loop
End
'-----------------------------------------------------
Interrupt_ticker:
   Timer0 = Tmr_c_preload
   Incr Timediv
   If Timediv >= Tmr_c_divis Then
      Timeout = 1
      Timediv = 0
   End If
   Return
'-----------------------------------------------------
'
'-----------------------------------------------------
Out_transmit:
   Do
      Gosub I2cwaitbus                            ' wait for Bus
      $asm
      ldi   r17, out_adr
      !Call I2cwmaster                            ' send SLA+W  & arbitr.Check
      $end Asm
      If Err = 0 Then
            Loadadr M32_byte(1) , X
            $asm
            ld    r17, x+
            !Call I2cwmaster                      ' send data  & arbitr.Check
            $end Asm
      End If
      If Err = 0 Then
         I2cstop
      End If
   Loop Until Err = 0
   I2cinit
   Return



Include-File MyI2c.bas

'----------------------------------------------
' MyI2C.BAS
'    I2c Soft-functions
'----------------------------------------------
'   PicNick was here  www.roboternetz.de
'----------------------------------------------

'---------------------------  Library und definitionen ------------------
$lib "MyI2c.LIB"


'--------------------------- Slave receive & Send ---------------------
Const I2c_m_start = 1

$external I2c_get_addr                            'wait for start-cond & read in I2C address
Declare Sub I2c_get_addr

$external I2c_slave_rx_data                       'ACK & receive master data
Declare Sub I2c_slave_rx_data

$external I2c_slave_tx_byte                       'ACK & send data to  master
Declare Sub I2c_slave_tx_byte

'--------------------------- Multimaster sending ---------------------
$external I2cwaitbus                              'wait for free bus & reserve it
Declare Sub I2cwaitbus

$external I2cwmaster                              'send byte & watch arbitration
Declare Sub I2cwmaster

'-------------------------------------
'  I2C-STRUCTURE
'-------------------------------------
Dim I2c_flag As Byte                              '0   Kontroll-flags
Dim I2c_addr As Byte                              '1   slave adresse
Dim I2c_cntr As Byte                              '2   bei empfang anzahl bytes
Dim I2c_write As Word                             '3/4 adresse empfangsbuffer
Dim I2c_read As Word                              '5/6 adresse sendebuffer

'---------------------------------------------
'
'---------------------------------------------
   I2cinit


Bascom Library Myi2c.lib

copyright 	= R.Toegel
www       	= http://www.oldformation.at
email     	= roberttoegel@aon.at
comment   	= BASCOM-AVR I2C Slave / Multimaster library add to I2c.LIB
libversion   	= 1.0.0.1
date         	= 26 Jun 2006
statement    	= Based on ATMEL application note
history      	= This lib is an addon to i2c.lib

;-----------------------------------------------------
;	I2c_slave_tx_ack	Send ACK
;	I2c_slave_tx_nak	Send NACK
;	I2c_release		Release Lines
;	I2c_wait_start		Wait for Start Condition
;	I2c_get_addr		Get Message Address
;	I2c_slave_tx_byte	Slave Transmitter
;	I2c_slave_rx_data	Slave Receiver
;	I2c_read_byte		Internal
;-----------------------------------------------------
;	I2cwaitbus	
;	I2cwmaster
;-----------------------------------------------------
[I2c_slave_tx_ack]
I2c_slave_tx_ack:
* 	sbi 	_sdaDDR,_sda    ;Hold SDA LO (ACK)
Wt_ack_scl:
*	in	r1, SREG	; save SREG
	cli			; disable interrupts
* 	cbi 	_sclDDR,_scl	;SCL Release
Wt_scl_hi2:
* 	sbis 	_sclPIN,_scl    ;SCL
  	rjmp    wt_scl_hi2     	;wait SCL hi
Wt_scl_lo3:
* 	sbic 	_sclPIN,_scl    ;SCL
   	rjmp     wt_scl_lo3     ;wait SCL lo
* 	sbi 	_sclDDR,_scl	;SCL Stretch
* 	cbi 	_sdaDDR,_sda    ;release SDA
*	out	SREG, R1
   	ret
[end]
;-----------------------------------------------------
[I2c_slave_tx_nak]
I2c_slave_tx_nak:
$external I2c_slave_tx_ack
* 	cbi 	_sdaDDR,_sda    ;Release SDA  
	rjmp 	Wt_ack_scl
[end]
;-----------------------------------------------------
[I2c_release]
I2c_release:
* 	cbi 	_sdaDDR,_sda    ;SDA Release
* 	cbi 	_sclDDR,_scl	;SCL Release
   	clr      r22
   	std      Z + 0, r22     ;clear flag
	ret
[end]
;-----------------------------------------------------
[I2c_wait_start]
I2c_wait_start:
	ldi	r22, 0
   	std  	Z + 0, r22     	; clear I2c_flag
Wt_hi_hi:
* 	sbis 	_sclPIN,_scl    ; SCL ?
   	rjmp     wt_hi_hi       ; wait SCL hi
* 	sbis 	_sdaPIN,_sda    ; SDA ?
   	rjmp     wt_hi_hi       ; wait SDA hi
Wt_sda_lo0:
* 	sbic 	_sdaPIN,_sda    ; SDA
	rjmp     wt_sda_lo0     ; wait SDA lo
* 	sbis 	_sclPIN,_scl    ; SCL start condition ?
   	rjmp     wt_hi_hi       ; no, repeat the whole sequence
Wt_scl_lo0:
* 	sbic 	_sclPIN,_scl    ; SCL
   	rjmp     wt_scl_lo0     ; wait SCL lo	
* 	sbi 	_sclDDR,_scl	; SCL Stretch
   	ret
[end]
;-----------------------------------------------------
[I2c_get_addr]
I2c_get_addr:
$external I2c_wait_start
   	ldd	r22, Z + 0 	; i2c_flag
*	cpi	r22, I2c_m_Start
        breq    rept_s		; start-cond. already set
	rcall	I2c_wait_start	; wait for Bus-start
rept_s:
*	clr 	r22
   	std  	Z + 0, r22     	;clear I2c_flag
   	ldi	r24 ,1         	;set 'end'-Bit
*	in	r1, SREG	; save SREG
	cli			; disable interrupts
   	clc			;clear carry
Wta_scl_hi:
* 	cbi 	_sclDDR,_scl	;SCL Release
* 	sbis 	_sclPIN,_scl    ;SCL
   	rjmp     wta_scl_hi     ;wait SCL hi
* 	sbic 	_sdaPIN,_sda    ;SDA = 0 ?
   	sec                     ;SDA = 1 -> set carry
Wta_scl_lo:
* 	sbic 	_sclPIN,_scl    ;SCL
   	rjmp     wta_scl_lo     ;wait SCL lo
* 	sbi 	_sclDDR,_scl	;SCL Stretch
   	rol      r24            ;roll carry in/out
   	brcc     Wta_scl_hi     ;Bit loop 
   	std      Z + 1, r24     ;Store i2c address
*	out	SREG, r1
   	ret
[end]
;-----------------------------------------------------
[I2c_slave_rx_data]
I2c_slave_rx_data:
   	ldd      xl, Z + 3           	; Load Buffer Address
   	ldd      xh, Z + 4           	;
   	clr      r23
   	std      Z + 2, r23          	; clear counter
I2c_read_loop:
$external I2c_slave_tx_ack
   	rcall	I2c_slave_tx_ack	; Send ACK 

*	in	r1, SREG	; save SREG
	cli			; disable interrupts
   	clt                          	; clear T-Bit
   	rcall   I2c_read_byte		; read 8 Bit
   	brtc    Rd_sto_ack		; T-Bit clear ? o.k.--> 
*	out	SREG, r1	
   	std     Z + 2, r23    		; store counter
   	std     z + 0, r22     		; set start/stop/none flag
   	ret
Rd_sto_ack:
*	out	SREG, r1	
   	st      x+, r24			; store character
	inc	r23			; data counter++
   	rjmp   I2c_read_loop		; no, cont'd next byte

'-------------------------------------------
I2c_read_byte:
   	ldi      r24 ,1                 ;set end-bit
   	clc                             ;clear carry
Rd_loop:
* 	cbi 	_sclDDR,_scl		;SCL Release
Wt_scl_hi:
* 	sbis 	_sclPIN,_scl    	; SCL
   	rjmp     wt_scl_hi              ; wait SCL hi
* 	sbis 	_sdaPIN,_sda    	; SDA ?
   	rjmp     Wt_chk_0		; SDA Low-Check
   	sec              		; SDA Hi-Check
Wt_chk_1:
* 	sbis 	_sclPIN,_scl    	; SCL
   	rjmp     wt_ok_x                ; scl low---> ok, next bit
* 	sbic 	_sdaPIN,_sda    	; SCL Hi & SDA lo --> repeated Start
   	rjmp     wt_chk_1               ; SCL & SDA Hi --> cont'd wait
Rep_start_cond:
* 	sbic 	_sclPIN,_scl    	; SCL			
   	rjmp     Rep_start_cond		; wait SCL lo
* 	sbi 	_sclDDR,_scl		; SCL STRETCH
   	SET				; set t-Bit
*	ldi 	r22, I2c_m_Start	; signal REP-Start
   	ret                                     
Wt_chk_0:				; SDA is Low
* 	sbis 	_sclPIN,_scl    	; SCL ?
   	rjmp     wt_ok_x             	; scl low---> ok, next bit
* 	sbis 	_sdaPIN,_sda    	; SDA ?
   	rjmp     wt_chk_0		; SCL Hi & SDA lo --> cont'd wait
Stop_cond:				: stop-condition
   	SET				; set t-bit
   	ret				; xit
Wt_ok_x:
* 	sbi 	_sclDDR,_scl		; STRETCH
   	rol      r24                    ; roll carry in/out
   	brcc     rd_loop		; next bit
   	ret				; byte done
[end]

;-----------------------------------------------------
[I2c_slave_tx_byte]
I2c_slave_tx_byte:
$external I2c_slave_tx_ack
   	rcall    I2c_slave_tx_ack	; Send ACK
   	ldd      xl, Z + 5 		;Load Buffer Address
   	ldd      xh, Z + 6      	;
*	in	r1, SREG	; save SREG
	cli			; disable interrupts
	rcall	Tx_loop
*	out	SREG, r1
	ret
;--------------------------------------------------
Tx_loop:
   	ld       r24, x+		; next character
   	ldi      r25, 8			; 8 Bit
Tx_c_loop:
   	Sbrc     R24 , 7        	;Data Bit ?
   	rjmp     Tx_Bit_1		;set SDA High
;--------------------------------------------------
;---------------- send NULL------------------------
* 	sbi 	_sdaDDR,_sda    	;set SDA Low
* 	cbi 	_sclDDR,_scl		;SCL Release--------------------
Tx0_scl_hi_0:
* 	sbis 	_sclPIN,_scl    	;SCL
   	rjmp     Tx0_scl_hi_0		;wait scl hi
	nop
	nop
Tx0_scl_lo_0:
* 	sbic 	_sclPIN,_scl    	;SCL
   	rjmp     Tx0_scl_lo_0		;wait scl lo

* 	sbi 	_sclDDR,_scl		;SCL Stretch
	rjmp	Tx_step
;--------------------------------------------------
;---------------- send HIGH------------------------
Tx_bit_1:
* 	cbi 	_sdaDDR,_sda    	;SDA Release High
* 	cbi 	_sclDDR,_scl		;SCL Release
Tx1_scl_hi_0:
* 	sbis 	_sclPIN,_scl    	;SCL
   	rjmp     Tx1_scl_hi_0		;wait scl hi
* 	sbis 	_sdaPIN,_sda    	;SDA HI  ?
	ret				;Bus Lost , anyhow
Tx1_scl_lo_0:
* 	sbic 	_sclPIN,_scl    	;SCL
   	rjmp     Tx1_scl_lo_0		;wait scl lo
* 	sbi 	_sclDDR,_scl		;SCL Stretch
Tx_step:
   	rol      r24            	;roll carry in/out
   	dec      r25			;count bits
   	brne     Tx_c_loop		;next bit
;--------------------------------------------------
;---------------- get ACK/NAK ---------------------
* 	cbi 	_sdaDDR,_sda    	;SDA Release
* 	cbi 	_sclDDR,_scl		;SCL Release
Tx_scl_hi_1:				;get ack bit
* 	sbis 	_sclPIN,_scl    	;SCL
   	rjmp     Tx_scl_hi_1		;wait scl hi
* 	sbic 	_sdaPIN,_sda    	;SDA (ACK) ?
   	ret             		;no-ack --> return
Tx_scl_lo_1:
* 	sbic 	_sclPIN,_scl    	;SCL
   	rjmp     Tx_scl_lo_1		;wait scl lo
* 	sbi 	_sclDDR,_scl		;SCL Stretch
   	rjmp    tx_loop			; next

[end]

;---------------------------------------------------------
;	MASTER Functions
;---------------------------------------------------------
;	Wait for free Bus
;---------------------------------------------------------
[I2cwaitbus]
I2cwaitbus:
$EXTERNAL _I2C
*	in	r1, SREG	; save SREG
	cli			; disable interrupts
Ck_1_x:
      	LDI   	r23,0x0f  	; 15 times
Ck_1_y:
* 	sbis	_sclPIN,_scl    ; SCL 
	RJMP	Ck_1_x          ; wait SCL Hi
* 	sbis 	_sdaPIN,_sda    ; SDA HI  ?
      	RJMP  	Ck_1_x          ; wait SDA Hi
      	DEC   	r23
      	BRNE  	Ck_1_y          ; (8) hang on
* 	sbi 	_sdaDDR,_sda    ; SDA down for Start
*	out	SREG, r1
	Rjmp 	_i2c_hp_delay   ; half period delay
[end]
;---------------------------------------------------------
;	Send one Byte R17 & check Arbitration
;---------------------------------------------------------
[I2cwmaster]
I2cwmaster:
$EXTERNAL _I2C
*	in	r1, SREG	; save SREG
	cli			; disable interrupts
      	Sec                                     ; set carry flag
      	Rol   	r17                             ; shift in carry and out bit one
	rcall	I2cwmaster_loop
*	out	SREG, r1
	ret
I2cwmaster_loop:
* 	sbi 	_sclDDR,_scl	                ;SCL DOWN
      	BRCC  	I2cwmaster_low                  ;carry clear --> send Low
; send High ------------------------------------------
      	NOP                                     ; filler
* 	cbi 	_sdaDDR,_sda      		; release SDA
      	RCALL 	_i2c_hp_delay                   ; wait
* 	cbi 	_sclDDR,_scl			; SCL Release
Tx_1_ck:
* 	sbis	_sclPIN,_scl    		; SCL 
      	RJMP  	Tx_1_ck                         ; wait SCL Hi
* 	sbis 	_sdaPIN,_sda    		; SDA still HI  ?
      	RJMP  	Tx_lost                         ; No, ---> arbitration lost
Tx_1_ok:
      	RCALL 	_i2c_hp_delay      		;wait
      	LSL   	r17                             ;2^^7 -->Cy
      	brne  	I2cwmaster_loop			;more bits ? 
;---------------------------------------------------
I2cwmaster_loop_x:                           	; Get ACK / NACK
* 	sbi 	_sclDDR,_scl	                ; SCL DOWN
* 	cbi 	_sdaDDR,_sda      		; release SDA
      	RCALL 	_i2c_hp_delay                   ; wait
* 	cbi 	_sclDDR,_scl			; SCL Release
Tx_x_ck:
* 	sbis	_sclPIN,_scl    		; SCL 
      	RJMP  	Tx_x_ck                         ; wait Hi
      	CLT                                     ; clear t-bit
* 	sbic 	_sdaPIN,_sda    		; SDA = ACK/NAK ?
Tx_lost:
      	SET                                     ; set t-bit
      	BLD 	r6,2              	    	; t-Bit -> to Bascom "ERR"
      	RJMP 	_i2c_hp_delay                   ; wait & return
' send Low ------------------------------------------
I2cwmaster_low:
* 	sbi 	_sdaDDR,_sda      		;down SDA
      	RCALL 	_i2c_hp_delay       		;wait
* 	cbi 	_sclDDR,_scl			;SCL Release
Tx_0_ck:
* 	sbis	_sclPIN,_scl    		;SCL 
      	RJMP  	Tx_0_ck                         ;wait SCL Hi
      	RJMP  	Tx_1_ok				;continue
[end]









Autor

Benutzer:PicNick

Web Links

http://www.oldformation.at/electronic/download/down.htm

Siehe auch


LiFePO4 Speicher Test