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
Der Testaufbau schaut so aus: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
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)







Zitieren

Lesezeichen