Hallo,
ich bin dabei eine Wandfackel zu konstruieren, die sich über den I2C bzw. TWI steuern lässt. Um die verschiedenen Modi auszuwählen ist es teilweise nötig meherer Bytes zu übertragen.
Beispiel: Lichtfarbe + Blinkfrequenz im Stroboskopmodus.
Zu diesem Zweck habe ich mich in die RN Artikel zu den Thema eingelesen und auch einen funktionsfähigen Code geschrieben bzw. umgeschrieben:
TWI Slave:
TWI Master:Code:' Wandfackel Bacom $regfile = "m16def.dat" ' the used chip $crystal = 8000000 ' frequency used ' $baud = 9600 ' keine baud rate angeben ! Config Timer2 = Timer , Prescale = 1024 Config Timer1 = Pwm , Pwm = 8 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down , Prescale = 64 'Die Timer starten On Timer2 Timer_ir Enable Interrupts Enable Timer1 Enable Timer2 Start Timer1 Start Timer2 Timer2 = 247 Dim Temp As Byte Dim Twi_control As Byte ' Controlregister lokale kopie Dim Twi_status As Byte Dim Twi_data As Byte Dim Count As Byte ' Testwert, jedes mal +1 Dim Timer_preload As Byte Dim Control As Byte ' Flag, bestimmt die aktuelle Aktion Dim Color_management As Byte Red Alias Pwm1a Green Alias Pwm1a Blue Alias Pwm1a '############################################################################### 'Abschnitt linear Fader Dim Linfade_count As Byte Dim Linfade_waitms As Byte Dim Linfade_counter As Byte 'Default Settings Linfade_count = 255 ' VCC/255 Helligkeitsstufen Linfade_waitms = 5 'Wartet nach jeder Helligkeitsstufe 5 ms 'Abschnitt Zufallsfader Declare Sub Cycle(farbe_start As Byte , Farbe_end As Byte) Dim I As Byte 'Zaehlvariable Dim Indfade_area As Byte 'Zaehlvariable Dim Indfade_waitms As Byte 'Warteschleife Dim Farbe_out As Byte Dim Indfade_begin As Byte 'Anfangsfarbe Dim Indfade_end As Byte 'endfarbe 'Default Settings Indfade_area = 255 ' Anzahl der PWM Abstufungen da 8 bit nur 255 Abstufungen mglich Indfade_waitms = 5 'Pause zwischen den einzelnen Schritten (in mS) 'Abschnitt Stroboskop Dim Strobo_ontime As Byte Dim Strobo_offtime As Byte Dim Strobo_helligkeit As Byte 'Default Settings Strobo_helligkeit = 255 Strobo_ontime = 50 Strobo_offtime = 100 'Dimmen Dim Dim_helligkeit As Byte 'Default Settings Dim_helligkeit = 126 '############################################################################### Declare Sub Twi_init_slave ' Werte zurcksetzen Count = 0 Twi_data = 0 Call Twi_init_slave ' TWI aktivieren Timer_preload = 247 Color_management = 1 ' Hauptschleife Do Select Case Control 'Fader aktivieren: aus-->an-->aus-->an usw. ' Linearfader Case 1: '255: 100 % For Linfade_counter = 0 To Linfade_count Step 1 '0 : 0 % Select Case Color_management Case 1 : Red = Linfade_counter Case 2 : Green = Linfade_counter Case 3 : Blue = Linfade_counter End Select Waitms Linfade_waitms Next For Linfade_counter = Linfade_count To 0 Step -1 Select Case Color_management Case 1 : Red = Linfade_counter Case 2 : Green = Linfade_counter Case 3 : Blue = Linfade_counter End Select Waitms Linfade_waitms Next ' Zufallsfader Case 2: Indfade_begin = Indfade_end 'Startfarbe ist immer die alte Zielfarbe Indfade_end = Rnd(indfade_area) 'Zielfarbe ist immer Zufall For I = 0 To Indfade_area Call Cycle(indfade_begin , Indfade_end) Select Case Color_management Case 1 : Red = Farbe_out Case 2 : Green = Farbe_out Case 3 : Blue = Farbe_out End Select Waitms Indfade_waitms Next 'Stroboskop Case 3: Select Case Color_management Case 1 : Red = 0 Case 2 : Green = 0 Case 3 : Blue = 0 End Select Waitms Strobo_ontime Select Case Color_management Case 1 : Red = Strobo_helligkeit Case 2 : Green = Strobo_helligkeit Case 3 : Blue = Strobo_helligkeit End Select Waitms Strobo_offtime 'Anschalten Case 4: Select Case Color_management Case 1 : Red = 0 Case 2 : Green = 0 Case 3 : Blue = 0 End Select 'Ausschalten Case 5: Select Case Color_management Case 1 : Red = 255 Case 2 : Green = 255 Case 3 : Blue = 255 End Select 'Helligkeit Dimmen Case 6: Select Case Color_management Case 1 : Red = Dim_helligkeit Case 2 : Green = Dim_helligkeit Case 3 : Blue = Dim_helligkeit End Select End Select Loop End ' Unterprogramme ' TWI als slave aktivieren Sub Twi_init_slave Twsr = 0 ' status und Prescaler auf 0 Twdr = &HFF ' default Twar = 11 ' Slaveadresse setzen Twcr = &B01000100 ' TWI aktivieren, ACK einschalten End Sub Timer_ir: Timer1 = Timer_preload ' schauen ob TWINT gesetzt ist Twi_control = Twcr And &H80 ' Bit7 von Controlregister 10000000 If Twi_control = &H80 Then '10000000 Twi_status = Twsr And &HF8 ' Status /11111000 ' wurde ein Byte geschickt If Twi_status = &H80 Or Twi_status = &H88 Then '10000000 // 10001000 Twi_data = Twdr ' neue Daten merken If Twi_data = 1 Then Control = 2 Twi_data = 0 End If If Twi_data = 4 Then Control = 5 Twi_data = 0 End If End If ' TWINT muss immer gelscht werden, damit es auf dem Bus weiter geht Twcr = &B11000100 ' TWINT lschen, mit ACK End If Return 'Farbverlauf Sub Cycle(farbe_start As Byte , Farbe_end As Bit Byte) Local Temp1 As Single Local Temp2 As Single Temp1 = I / Indfade_area Temp2 = Temp1 Temp1 = 1 - Temp1 Temp1 = Temp1 * Farbe_start Temp2 = Temp2 * Farbe_end Farbe_out = Temp1 + Temp2 End Sub
Dies funktioniert bereits wunderbar, dennoch ein paar Fragen.Code:$regfile = "M32def.dat" ' the used chip $crystal = 8000000 ' frequency used $baud = 9600 ' baud rate 'I2C Read and Write Declare Function Twi_read_byte(byval Slave As Byte) As Byte Declare Sub Twi_send_byte(byval Slave As Byte , Zeichen As Byte) 'Twi Variablen Dim Twi_control As Byte ' Controlregister lokale kopie Dim Twi_status As Byte Dim Twi_data As Byte 'Variablen fr Main loop Dim B As Byte ' Zeichen von UART Dim X As Byte Dim Error As Byte ' Fehlermerker Dim F As Byte Dim Id As Byte Dim Action As Byte Dim I2csent As Byte Dim Flag As Byte ' TWI Init Twcr = &B00000100 ' erstmal nur TWI aktivieren Twsr = 0 ' Status und Prescaler Register Twbr = 32 ' Bit Rate Register, 100kHz '############################################################################## '##################### Main Loop ############################################## '############################################################################## Do ' Eingang RS232 B = Inkey() If B = 49 Then Print 99 End If If B = 50 Then Action = 1 Call Twi_send_byte(11 , Action) End If If B = 51 Then Action = 11 Call Twi_send_byte(11 , Action) End If If B = 52 Then Action = 12 Call Twi_send_byte(11 , Action) End If If B = 53 Then Action = 13 Call Twi_send_byte(11 , Action) End If Loop End '############################################################################## '##################### Twi send_byte ########################################## '############################################################################## ' sendet ein Byte und schliesst die bertragung ab Sub Twi_send_byte(byval Slave As Byte , Zeichen As Byte) Error = 0 ' Fehler zurcksetzen ' Startbedingung Twcr = &B10100100 ' TWINT ' warten bis TWINT gesetzt ist Gosub Twi_wait_int '################# Slave Adresse Senden ######################################## ' wenn Zugriff auf den Bus erlaubt, Slaveadresse ausgeben If Twi_status = &H08 Or Twi_status = &H10 Then Twdr = Slave And &HFE ' slave adresse + Write Twcr = &B10000100 ' TWINT lschen, Byte senden ' warten bis TWINT gesetzt ist Gosub Twi_wait_int '##################### Daten Senden ############################################ ' Slave hat sich gemeldet If Twi_status = &H18 Or Twi_status = &H20 Then Twdr = 1 ' Daten Twcr = &B10000100 ' TWINT lschen, Byte senden ' warten bis TWINT gesetzt ist Gosub Twi_wait_int ' Zeichen wurden gesendet If Twi_status = &H28 Or Twi_status = &H30 Then Error = 0 Flag = 1 ' kein Fehler Else Error = Twi_status ' Fehler End If Else ' kein slave Error = Twi_status ' Fehler End If If Flag = 1 Then 'falls daten erfolgreich gesendet Twdr = 4 ' Daten Twcr = &B10000100 ' TWINT lschen, Byte senden ' Wurde das erste Byte erfolgreich bertragen Gosub Twi_wait_int ' Zeichen wurden gesendet If Twi_status = &H28 Or Twi_status = &H30 Then Error = 0 ' kein Fehler Else Error = Twi_status ' Fehler End If End If '############################################################################### ' STOPbedingung kommt hier immer im Ablauf, egal welcher Status Twcr = &B10010100 ' TWINT lschen, STOP senden ' nach einem STOP wird TWINT nicht mehr gesetzt, ' man darf/kann also nicht darauf warten ! '############################################################################### Else ' Bus belegt, wird er wieder freigegeben Twcr = &B10000100 ' TWINT lschen, Bus freigeben Error = Twi_status ' Fehler End If End Sub '############################################################################## '##################### Twi init ############################################### '############################################################################## Twi_wait_int: Do Twi_control = Twcr And &H80 Loop Until Twi_control = &H80 Twi_status = Twsr And &HF8 ' status ' status nur zu Debugzwecken ausgeben, weil Bus sehr langsam wird ! ' Print "Err " ; Hex(twi_status) Return
1. In den RN-Artikel wird der Inhalt des Status Registers eingelesen (TWSR) beziehungsweise die Bits 3-7. Mich würde interessieren, ob es irgendwo eine Aufstellung gibt, welche Bedeutung die einzelne Konstellation hat.
like: &H28 oder &H30 --> Zeichen wurde erfolgreich gesendet
Im Datenblatt des Atmega 32 habe ich leider keine Erklärung gefunden
Hat da evtl. jemand einen Tipp?
2. Bis beide Bytes bei meinem Beispiel gesendet wurden, vergehen etwa 1 Sekunde.
Mir ist bewusst, dass die Waitroutinen in der Main Schleife und der Aufruf der TWI Abfrage über den Timer (im ms-Takt) den Code ein wenig ausbremsen. Aber 1 Sekunde? Dauert es wirklich so lange bis der Slave sein Ack sendet?
3. Das TWINT Bit im Control Register (TWCR) wird ja gesetzt, wenn die Aktion "z.B. ein Byte senden" erfolgreich ausgeführt wurde. Setzt dies auch voraus, dass der Slave sein Ack gegeben hat. Ja oder???
Falls mir einer bei einen meiner Fragestellungen helfen könnte wäre ich ihm sehr dankbar.
Ich möchte hiermit ebenfalls den Autoren der RN-Artikel meinen herzlichen Dank aussprechen: Super Arbeit =D>
Grüße + fröhliche Weihnachten
hdtvfreak







Zitieren

Lesezeichen