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