Hallo
Es ist nicht einfach, Bascom wehrt sich gegen die Verwendung des tiny13.
Bei der letzen Version des Programms war ein falscher Interrupt in der Sprungtabelle eingetragen. Das war ja mein erster Verdacht und es hatte sich bestätigt. Die Sprungtabelle des tiny13 sieht so aus:
Address Labels Code Comments
0x0000 rjmp RESET ; Reset Handler
0x0001 rjmp EXT_INT0 ; IRQ0 Handler
0x0002 rjmp PCINT0 ; PCINT0 Handler
0x0003 rjmp TIM0_OVF ; Timer0 Overflow Handler
0x0004 rjmp EE_RDY ; EEPROM Ready Handler
0x0005 rjmp ANA_COMP ; Analog Comparator Handler
0x0006 rjmp TIM0_COMPA ; Timer0 CompareA Handler
0x0007 rjmp TIM0_COMPB ; Timer0 CompareB Handler
0x0008 rjmp WATCHDOG ; Watchdog Interrupt Handler
0x0009 rjmp ADC ; ADC Conversion Handler
Mein erster Versuch war: "On Timer0 Rc5_isr" und erzeugte diese Tabelle:
Code:
L0000:
rjmp __start ; L000A
; ----------- jump on last line
reti
;----------------------*
; pc=0x2(0x4)
;
reti
;----------------------*
; pc=0x3(0x6)
;
rjmp L00B0
; ----------- jump on last line
reti
;----------------------*
; pc=0x5(0xA)
;
reti
;----------------------*
; pc=0x6(0xC)
;
reti
;----------------------*
; pc=0x7(0xE)
;
reti
;----------------------*
; pc=0x8(0x10)
;
reti
;----------------------*
; pc=0x9(0x12)
;
reti
;----------------------*
; pc=0xA(0x14)
;
__start::
Es wurde ein OverFlow-Sprung eingetragen. Um das zu überprüfen habe ich mir einen Disassembler besorgt (ReAVR) und das hex-File untersucht.
Nun verwende ich folgenden Code: "On Oc0a Rc5_isr" und alles ist gut:
Code:
L0000:
rjmp __start ; L000A
; ----------- jump on last line
reti
;----------------------*
; pc=0x2(0x4)
;
reti
;----------------------*
; pc=0x3(0x6)
;
reti
;----------------------*
; pc=0x4(0x8)
;
reti
;----------------------*
; pc=0x5(0xA)
;
reti
;----------------------*
; pc=0x6(0xC)
;
rjmp L00B0
; ----------- jump on last line
reti
;----------------------*
; pc=0x8(0x10)
;
reti
;----------------------*
; pc=0x9(0x12)
;
reti
;----------------------*
; pc=0xA(0x14)
;
__start::
Jetzt war zwar der richtige Interrupt eingetragen, aber meine ISR wurde immer noch nicht aufgerufen. Das lag daran, dass der falsche Timerinterrupt erlaubt wurde. Aus "Enable Timer0" wurde deshalb "Enable Oc0a" und schon funzt auch die ISR.
Um das ganze testen zu können habe ich mir inzwischen eine kleine Testschaltung auf einem IC-Sockel zusammengebastelt:
Bild hier
Als Empfänger, es gibt leider nicht mehr viele Geräte die RC5 verstehen, habe ich meinen RP6 verwendet. Den Code habe ich aus den Beispielen der RP6-Doku und damit erzeugt mein tiny13 nun folgenen Output:
Please make sure that your IR Remote Control really transmits RC5 code!
Toggle Bit:1 | Device Address:8 | Key Code:2
Toggle Bit:1 | Device Address:8 | Key Code:2
Toggle Bit:0 | Device Address:0 | Key Code:0
Toggle Bit:0 | Device Address:26 | Key Code:6
Toggle Bit:0 | Device Address:3 | Key Code:0
Toggle Bit:0 | Device Address:26 | Key Code:6
Toggle Bit:0 | Device Address:3 | Key Code:0
Toggle Bit:0 | Device Address:26 | Key Code:6
Toggle Bit:0 | Device Address:3 | Key Code:0
Toggle Bit:0 | Device Address:26 | Key Code:6
Toggle Bit:0 | Device Address:3 | Key Code:0
Toggle Bit:0 | Device Address:26 | Key Code:6
Toggle Bit:0 | Device Address:3 | Key Code:0
Toggle Bit:0 | Device Address:26 | Key Code:6
Toggle Bit:0 | Device Address:3 | Key Code:0
Das 8/2 ist meine Testfernbedienung, alle anderen Codes hatte der tiny13 gesendet. Ist zwar noch nicht das Erwartete, aber ich bin wohl auf dem richtigen Weg. Der große Fehler ist noch der Wert für das OCR0-Register. Um bei meinen Tests mit einer normalen LED etwas erkennen zu können, hatte ich das alles erst mit Presaler=1024 und OCR0=255 probiert. Man sieht dann sogar die einzelnen Bits. In "Echtzeit" mit IR-LED und Prescaller=1 hatte ich versehentlich das OCR0 nicht geändert und deshalb die unerwarteten Werte gesendet. Blöderweise hängt sich das Programm aber mit dem richtigen Wert (133) auf weil vermutlich die ISR zu lange ist. Aber das sollte auch noch machbar sein...
Im Simulator blieb ich übrigens immer bei den Wait-Befehlen stecken. Irgendwie funzt das nicht, aber ich habe noch keine Zeit investiert um mich mit der Funktion des Simulators vertraut zu machen.
Hier noch der aktuelle Code:
Code:
'RC5-Code senden mit ATtiny13 (erster ernsthafter Versuch mit Bascom) 16.12.07 mic'
'Achtung! Das ist ein eher theoretischer Code den ich noch nicht getestet habe!'
'Es sollten im 0,5 Sekundentakt die Werte 0 bis 31 als Addresse und Kommando'
'mit Togglebit=0 gesendet werden. Ob das so funktioniert muss ich noch testen'
'Die IR-LED wird mit Widerstand(!) zwischen Pin5(PB0, OC0A) und GND angeschlossen '
'Trägerfrequenz = 36kHz(Puls/Pause 1:1), Bitlänge = Trägerfrequenz/64'
'Code basierden auf den Angaben von: http://www.sbprojects.com/knowledge/ir/rc5.htm'
'Einstellungen --------------------------------------------------------------------'
'Wir verwenden einen tiny13'
$regfile = "ATtiny13.dat"
'der mit internen 9,6MHZ getaktet wird (Fuse Takt/8 nicht gesetzt!)'
$crystal = 9600000
'Weitere, von mir noch nicht geprüfte Compileranweisungen:'
$hwstack = 32
$swstack = 8
'Hier musste ich von 16 auf 8 ändern,ich habe keine Ahnung, was das bewirkt'
'Mit 16 erhalte ich eine Fehlermeldung:'
'Out of SRAM-Space bei Dim Rc5_bit_gesetzt As Word'
$framesize = 8
'Dims und Declears ----------------------------------------------------------------'
'Der zu sendende RC5-Code als 16bit-Wert'
Dim Rc5_code As Word
'Bitmaske für das zu sendende Bit aus RC-Code'
Dim Rc5_bitmaske As Word
'Teiler des Trägertaktes und Kennung des Halbbits'
'128-65 bedeutet erstes Manchester-Halbbit, 64-1 bedeutet zweites Manchester-Halbbit'
'0 bedeutet komplettes Bit gesendet!'
Dim Rc5_halbbit As Byte
'die zu sendende RC5-Adresse (5 Bits, 0-31)'
Dim Rc5_adresse As Byte
'das zu sendende RC5-Kommando (6 Bits, 0-63)'
Dim Rc5_kommando As Byte
'größer 0 bedeutet aktuelles zu sendende Bit ist gesetzt'
Dim Rc5_bit_gesetzt As Word
'Zähler für das Demo'
Dim Count As Byte
'Startblinken'
Config Portb.0 = Output
Portb.0 = 1
Wait 1
Portb.0 = 0
Wait 1
'Die Sendesubroutine deklarieren'
Declare Sub Rc5_send(byval Address As Byte , Byval Command As Byte , Byval Tog As Byte)
'Initialisierung ------------------------------------------------------------------'
'Timer0 auf CTC-Mode mit OC0A-Toggeln und OCR0A löschen nach Match bei perscale=1'
Config Timer0 = Timer , Compare A = Toggle , Prescale = 1 , Clear Timer = 1
'MatchCompareRegister setzen: 133 für 36kHz oder 126 für 38kHz'
'Anmerkung für Harry: Ob das Bittiming bei 38kHz funktioniert weiß ich nicht,'
'aber ein 36kHz-LSoP kostet nur ca. 1,xx Euro + Versandkosten im Onlineversand'
Ocr0a = 255
'ISR für Timer0 bei OutputCompareA definieren'
On Oc0a Rc5_isr
'MatchCompare Interrupt erlauben'
Enable Oc0a
'Interrupts generell erlauben'
Enable Interrupts
'Es wird noch wird nicht gesendet'
Rc5_bitmaske = 0
'Hauptprogramm --------------------------------------------------------------'
Do
For Count = 0 To 31
Call Rc5_send(count , Count , 0)
Waitms 200
Next
Loop
'Sub und ISR ---------------------------------------------------------------------'
'die eigentliche Sendefunktion'
Sub Rc5_send(address As Byte , Command As Byte , Tog As Bit)
'14 bits RC5-Code zusammensetzen in der 16 Bit Variablen Rc5_code'
'Bitnummer: 1111110000000000'
' 5432109876543210'
'Funktion: --sstaaaaacccccc'
'2 Startbits setzen'
Rc5_code = &B11
'Bitmuster nach links weiterschieben und Platz für die nächsten Bits schaffen'
Shift Rc5_code , Left , 1
'das Toggle-Bit setzen wenn gewünscht'
If Tog <> 0 Then
Set Rc5_code.0
End If
'address hat 5 gültige Bits'
Shift Rc5_code , Left , 5
'überflüssige Addressbits ausblenden'
Address = Address And &B11111
'und Address-Bits in Rc5_code setzen'
Rc5_code = Rc5_code Or Address
'command hat 6 gültige Bits'
Shift Rc5_code , Left , 6
'überflüssige Commandbits ausblenden'
Command = Command And &B111111
'und Kommando-Bits in Rc5_code setzen'
Rc5_code = Rc5_code Or Command
'Bitmaske auf bit13 (erstes von 14 RC5-Bits) setzen
'Bitnummer: 1111110000000000'
' 5432109876543210'
'Funktion: --sstaaaaacccccc'
'Maske: 0010000000000000'
Rc5_bitmaske = &B0010000000000000
'Start der Übertragung mit dem ersten Halbbit'
Rc5_halbbit = 64
'Ab hier übernimmt die ISR die Kontrolle. Wir warten, bis alle Bits gesendet sind'
Do
Wait 1
Loop Until Rc5_bitmaske = 0
'LED ausschalten'
Config Portb.0 = Input
'Fertig'
End Sub
'Ab hier folgt die ISR'
Rc5_isr:
'Wenn wir senden wollen'
If Rc5_bitmaske > 0 Then
'ermitteln wir den Status des aktuellen Bits'
Rc5_bit_gesetzt = Rc5_code And Rc5_bitmaske
'und wenn wir beim Start des ersten Halbbits sind,'
If Rc5_halbbit = 64 Then
'geben wir das erste Halbbit invertiert aus (Manchestercodierung?)
If Rc5_bit_gesetzt > 0 Then
Config Portb.0 = Input
Else
Config Portb.0 = Output
End If
'ende erstes Halbbit'
End If
'Beim zweiten Halbbit müssen wir nun den gewünschten Bitstatus ausgeben'
If Rc5_halbbit = 32 Then
If Rc5_bit_gesetzt > 0 Then
Config Portb.0 = Output
Else
Config Portb.0 = Input
End If
'ende zweites Halbbit'
End If
'Bitzeit ist Trägerfrequenz/64, also wir zählen den Bittimer runter'
Rc5_halbbit = Rc5_halbbit - 1
'Bei RC5_halbbit = 0 ist das aktuelle Bit gesendet, wir senden nun das nächste Bit'
If Rc5_halbbit = 0 Then
'und laden den Bittimer mit dem Startwert für erstes Halbbit.'
Rc5_halbbit = 64
'Dann setzen wir die Bitmaske auf das nächste zu sendende Bit'
Rc5_bitmaske = Rc5_bitmaske / 2
'Rc5_bitmaske = 0 beim nächsten Aufruf der ISR bedeutet,'
'alle Bits sind gesendet, also sind wir fertig'
'nächstes Bit'
End If
'und wiederholen 14 mal'
'Ende wenn rc5_bitmaske >0'
End If
Return
Gruß
mic
Lesezeichen