Aus RN-Wissen.de
Version vom 9. August 2006, 17:44 Uhr von PicNick (Diskussion | Beiträge)
Inhaltsverzeichnis
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
Web Links
http://www.oldformation.at/electronic/download/down.htm
Siehe auch