Hallo,
hab nun auch ein paar Tage frei, deshalb darf mein Tiny dran glauben 
Wer sich mal versuchen will, ist die AppNote 312 als Bascom-Version.
Verändert werden sollte erstmal nix, ausser evtl. der Slaveadresse, und dem Soundausgang 
Ansonsten kann für die Funktion nicht garantiert werden 
Code:
' USI-I2C Testprogramm
' Slave @ $40
'
' mit Interrupt und ohne Timer
$regfile = "attiny2313.dat"
$crystal = 16000000
$baud = 9600
$hwstack = 40
'$framesize = 16
$swstack = 16
' Unterprogramme für die USI-Kommunikation
Declare Sub Usi_twi_slave_initialise()
Declare Sub Usi_twi_transmit_byte(zeichen As Byte)
Declare Function Usi_twi_receive_byte() As Byte
On Uci_start Usi_start_condition_isr , Nosave
On Uci_ovflw Usi_counter_overflow_isr , Nosave
' einige Aliases anlegen
Pout_usi_scl Alias Portb.7
Pin_usi_scl Alias Pinb.7
Ddr_usi_scl Alias Ddrb.7
Pout_usi_sda Alias Portb.5
Pin_usi_sda Alias Pinb.5
Ddr_usi_sda Alias Ddrb.5
Dim Usi_twi_errorstate As Byte ' eigener Fehlerstatus
' Array der Daten die übertragen werden
Dim Twi_txbuf(16) As Byte
Dim Twi_rxbuf(16) As Byte
' Zeiger auf Buffer
Dim Twi_rxhead As Byte
Dim Twi_rxtail As Byte
Dim Twi_txhead As Byte
Dim Twi_txtail As Byte
Dim Temp_usi As Byte
Dim Temp_usi_isr As Byte ' Byte das in den ISRs verwendet wird
Dim Usi_twi_data_in_receive_buffer As Bit ' Flag ob Buffer Daten enthält
Dim Usi_twi_overflow_state As Byte
Const Twi_slaveaddress = &H40
' Möglichkeiten für Usi_twi_overflow_state
Const Usi_sl_check_address = 0
Const Usi_sl_send_data = 1
Const Usi_sl_req_reply_from_send_data = 2
Const Usi_sl_chk_reply_from_send_data = 3
Const Usi_sl_req_data = 4
Const Usi_sl_get_data_and_send_ack = 5
' Ausgänge für LEDs
Config Portb.6 = Output
Config Portb.2 = Output
Config Portb.1 = Output
Config Portb.0 = Output
Config Portd.6 = Output
Config Portd.4 = Output
Enable Interrupts ' IRQs global erlauben
Call Usi_twi_slave_initialise
Waitms 500 ' Sicherheitspause nach Reset
Sound Portd.5 , 300 , 450 ' BEEP
Print
Print "USI Slavetest"
' Hauptprogramm
Do
Gosub Check_if_data_in_receive_buf
If Usi_twi_data_in_receive_buffer = 1 Then
Temp_usi = Usi_twi_receive_byte()
' Wert an LEDs anzeigen
Portb.6 = Temp_usi.5
Portb.2 = Temp_usi.4
Portb.1 = Temp_usi.3
Portb.0 = Temp_usi.2
Portd.6 = Temp_usi.1
Portd.4 = Temp_usi.0
Temp_usi = Not Temp_usi
Print Temp_usi
'Usi_twi_transmit_byte(Temp_usi)
Else
' Print "nix"
Waitms 100
End If
'Print Twi_rxhead ;
'Print " ";
'Print Twi_rxtail ;
'Print " ";
'Print Twi_txhead ;
'Print " ";
'Print Twi_txtail
Loop
End
' Unterprogramme
' Initialise USI for TWI Slave mode.
Sub Usi_twi_slave_initialise()
Gosub Flush_twi_buffers ' Flushes the TWI buffers
' Direction Out
Ddr_usi_scl = 1
Ddr_usi_sda = 0 ' SDA Input
' Release SCL & SDA
Pout_usi_scl = 1
Pout_usi_sda = 1
' Preload dataregister with "released level" data.
Usidr = &HFF
' Enable Start Condition Interrupt. Disable Overflow Interrupt.
' Set USI in Two-wire mode. No USI Counter overflow prior
' To First Start Condition(potentail Failure)
' Shift Register Clock Source = External , Positive Edge
Usicr = &B10101000
' Clear flags, and reset counter.
Usisr = &B11110000
End Sub
' Puts data in the transmission buffer, Waits if buffer is full.
Sub Usi_twi_transmit_byte(zeichen As Byte)
Local Tmphead As Byte
' Calculate Buffer Index.
Tmphead = Twi_txhead + 1
Tmphead = Tmphead And &H0F
' Wait for free space in buffer.
While Tmphead = Twi_txtail
Wend
Twi_txbuf(tmphead + 1) = Zeichen ' Store Data In Buffer.
Twi_txhead = Tmphead ' Store new index.
End Sub
' Returns a byte from the receive buffer. Waits if buffer is empty
Function Usi_twi_receive_byte() As Byte
Local Tmptail As Byte
' warten bis etwas im Buffer steht
While Twi_rxhead = Twi_rxtail
Wend
' Tmptail =(twi_rxtail + 1 ) & Twi_rx_buffer_mask;
' Calculate buffer index
Tmptail = Twi_rxtail + 1
Tmptail = Tmptail And &H0F
Twi_rxtail = Tmptail ' Store new index
Usi_twi_receive_byte = Twi_rxbuf(tmptail + 1) ' Return data from the buffer.
End Function
' ISR für Startsequenz erkannt
Usi_start_condition_isr:
$asm
PUSH R16
PUSH R20
PUSH R24
PUSH R25
PUSH R26
IN R24,&H3F
PUSH R24
$end Asm
' Code
Usi_twi_overflow_state = Usi_sl_check_address
Ddr_usi_sda = 0 ' Enable SDA as input.
' Wait for SCL to go low.
' If a Stop condition arises then leave the interrupt to prevent waiting forever.
While Pin_usi_scl = 1 And Usisr.5 = 0 ' USIPF
Wend
' Enable Overflow and Start Condition Interrupt. (Keep StartCondInt to detect RESTART)
' Set USI in Two-wire mode.
' Shift Register Clock Source = External, positive edge
Usicr = &B11111000
' Clear flags, and reset counter.
Usisr = &B11110000
$asm
POP R24
Out &H3F , R24
POP R26
POP R25
POP R24
POP R20
POP R16
$end Asm
Return
' ISR für Counteroverflow
Usi_counter_overflow_isr:
$asm
PUSH R10
PUSH R16
PUSH R20
PUSH R24
PUSH R26
IN R24,&H3F
PUSH R24
$end Asm
' Code
'Print Usi_twi_overflow_state
Select Case Usi_twi_overflow_state
' -- Address mode --
' Check address and send ACK (and next USI_SL_SEND_DATA) if OK, else reset USI.
Case Usi_sl_check_address :
Temp_usi_isr = Usidr And &HFE ' 0. Bit ausblenden falls RW gleich 1
If Temp_usi_isr = Twi_slaveaddress Then
' Read oder Write ? 1 - Master will was von uns haben
If Usidr.0 = 1 Then
Usi_twi_overflow_state = Usi_sl_send_data
Else
Usi_twi_overflow_state = Usi_sl_req_data
End If
Gosub Set_usi_to_send_ack
Else
Gosub Set_usi_to_twi_start_cond_mode
'Print "nicht ich"
End If
' -- Master write data mode --
' Check reply and goto USI_SL_SEND_DATA if OK, else reset USI.
Case Usi_sl_chk_reply_from_send_data :
' If NACK, the master does not want more data.
If Usidr = 0 Then
Gosub Set_usi_to_twi_start_cond_mode
Goto Fertig_usi_counter_overflow_isr
Else
' From here we just drop straight into USI_SL_SEND_DATA if the master sent an ACK
If Twi_txhead <> Twi_txtail Then
' Twi_txtail = (twi_txtail + 1 ) And Twi_tx_buffer_mask
Temp_usi_isr = Twi_txtail + 1
Temp_usi_isr = Temp_usi_isr And &H0F
Twi_txtail = Temp_usi_isr
Usidr = Twi_txbuf(temp_usi_isr + 1)
Else
' If the buffer is empty then:
Gosub Set_usi_to_twi_start_cond_mode
Goto Fertig_usi_counter_overflow_isr
End If
Usi_twi_overflow_state = Usi_sl_req_reply_from_send_data
Gosub Set_usi_to_send_data
End If
' Copy data from buffer to USIDR and set USI to shift byte. Next USI_SL_REQ_REPLY_FROM_SEND_DATA
Case Usi_sl_send_data :
If Twi_txhead <> Twi_txtail Then
' Twi_txtail = (twi_txtail + 1 ) And Twi_tx_buffer_mask
Temp_usi_isr = Twi_txtail + 1
Temp_usi_isr = Temp_usi_isr And &H0F
Twi_txtail = Temp_usi_isr
Usidr = Twi_txbuf(temp_usi_isr + 1)
Else
' If the buffer is empty then:
Gosub Set_usi_to_twi_start_cond_mode
Goto Fertig_usi_counter_overflow_isr
End If
Usi_twi_overflow_state = Usi_sl_req_reply_from_send_data
Gosub Set_usi_to_send_data
' Set USI to sample reply from master. Next USI_SL_CHK_REPLY_FROM_SEND_DATA
Case Usi_sl_req_reply_from_send_data :
Usi_twi_overflow_state = Usi_sl_chk_reply_from_send_data
Gosub Set_usi_to_read_ack
' -- Master read data mode --
' Set USI to sample data from master. Next USI_SL_GET_DATA_AND_SEND_ACK.
Case Usi_sl_req_data :
Usi_twi_overflow_state = Usi_sl_get_data_and_send_ack
Gosub Set_usi_to_read_data
' Copy data from USIDR and send ACK. Next USI_SL_REQ_DATA
Case Usi_sl_get_data_and_send_ack :
' Put data into Buffer
' Twi_rxhead = (twi_rxhead + 1 ) & Twi_rx_buffer_mask
Temp_usi_isr = Twi_rxhead + 1
Temp_usi_isr = Temp_usi_isr And &H0F
Twi_rxhead = Temp_usi_isr
Twi_rxbuf(temp_usi_isr + 1) = Usidr
Usi_twi_overflow_state = Usi_sl_req_data
Gosub Set_usi_to_send_ack
End Select
Fertig_usi_counter_overflow_isr:
$asm
POP R24
Out &H3F , R24
POP R26
POP R24
POP R20
POP R16
POP R10
$end Asm
Return
' Einstellungen für Read und Write
'
Set_usi_to_twi_start_cond_mode:
' Enable Start Condition Interrupt. Disable Overflow Interrupt
' Set USI in Two-wire mode. No USI Counter overflow hold.
' Shift Register Clock Source = External, positive edge
Usicr = &B10101000
'Clear all flags, except Start Cond
Usisr = &B01110000
Return
'
Set_usi_to_send_ack:
Usidr = 0 ' Prepare ACK
Ddr_usi_sda = 1 ' Set Sda As Output
' Clear all flags, except Start Cond
' Set Usi Counter To Shift 1 Bit
Usisr = &B01111110
Return
'
Set_usi_to_read_ack:
Ddr_usi_sda = 0 ' Set Sda As Intput
Usidr = 0 ' Prepare ACK
' Clear all flags, except Start Cond
' set USI counter to shift 1 bit
Usisr = &B01111110
Return
'
Set_usi_to_send_data:
Ddr_usi_sda = 1 ' Set Sda As Output
' Clear all flags, except Start Cond
' set USI to shift out 8 bits
Usisr = &B01110000
Return
'
Set_usi_to_read_data:
Ddr_usi_sda = 0 ' Set Sda As Intput
' Clear all flags, except Start Cond
' set USI to shift out 8 bits
Usisr = &B01110000
Return
'
Check_if_data_in_receive_buf:
If Twi_rxtail <> Twi_rxhead Then
Usi_twi_data_in_receive_buffer = 1
Else
Usi_twi_data_in_receive_buffer = 0
End If
Return
' hauwech
Flush_twi_buffers:
Twi_rxtail = 0
Twi_rxhead = 0
Twi_txtail = 0
Twi_txhead = 0
Return
Der Testaufbau schaut so aus:
Die LEDs links auf dem RN-Control, sind von oben die ersten beiden für den I2C-Bus, der Rest ist für die Anzeige der Daten, die vom RN-Mega8 gesendet werden.
Der Mega8 liest die Temperatur vom DS1621, und gibt den Wert an einen PCF8574 weiter, der Tiny2313 spielt eben diesen vor, und gibt den Wert an den 6 LEDs aus.
Das Muster ist dasselbe wie auf dem RN-M8 LEDs unten.
Testprogramm auf dem RN-M8 ist dieses vom Wiki:
https://www.roboternetz.de/wissen/in...it_und_Receive
€dit:
Ich hab die If-Abfrage (Zeile 236-237) umgebaut, da der Slave nicht auf ein Master-Read reagiert hat, so geht das jetzt auch. (Falls was im Puffer steht)
Lesezeichen