Bascom NEC Code senden

Bau das mal bitte noch um
...Für die direkte Adressierung scheint man auch {Variablenname} verwenden zu können - ließe sich am Ende beim reinitialisieren des Bitzählers auf 39 verwenden. Also statt der beiden Zeilen SUBI und ST(ore) könnte man schreiben:
STS {Bitzaehler} , R16
...

Zum Simulator: zumindest bei dem vom AVRStudio kann man ihn den Code bis zu einer platzierbaren Cursorposition ausführen lassen - hier bietet sich der Einsprung in die OC-ISR an (=fallende Flanke am Pin). Für die steigende müßtest Du den IC-Interrupt, oder den TOV aktivieren, und in der ISR dann ein NOP einbauen.
Beim AVRStudio-Simulator kann man außer den Takten auch die verstrichene Zeit mitverfolgen und den Zähler bei Bedarf zurücksetzen...
 
hab einfach an die stelle
STS{bitzaheler}.. nen brakpoint gesetzt,.

dann machts bei nem prescaler von 8, TCCR1B =26 nen Zyklus von 351ms
dann machts bei nem prescaler von 1, TCCR1B =25 nen Zyklus von 44ms

bei unveränderter zeichenkette
wenn ich nun adress und Zeichenkette komplett auf 0/1 setze, brauch ich auch nur 44ms
egal was für ne zeichenkeztte ich einsetz, 44ms.
 
hinter dem label "AdresseStimmt:", und vor dem "lsl r16" fehlt ein:
"LD R16, X", und der PWM-Pin muß als Ausgang festgelegt werden - aber das wars noch nicht... Auf alle Fälle gibts noch ein Problem mit der Pause. Solange TCNT=1 ist, liegt der PWM-Pin auch auf High (durch den Überlauf wird er High, das CompareMatch, das ihn low setzt, wird erst bei TCNT=1 wirksam)

Wir könnten den Pin solange als normalen I/O verwenden, und entweder den IC-Interrupt verwenden (und den OC-Interrupt konstant bei 562,5µs lassen) um den Pegel umzuschalten, oder trotzdem nur einen IRQ verwenden...
Ich denk noch drüber nach...
 
So, habs mal folgendermaßen abgeändert:
-Fehler korrigiert: PortB.3 ist jetzt Ausgang (lo zum Start) und normaler I/O (COM1A=0, TCCR1A=2)
-nach dem NEC-Init und dem festlegen der zu sendenden Daten wird der Timer gestartet (TCCR1B=25), und PORTB3 auf hi gesetzt (SBI)
-nach dem 4ten IRQ wird PORTB3 lo (CBI)
-nach dem 5ten IRQ wird OCR1A auf 4499 (562,5µs) gesetzt, diese Änderung sollte aber erst nach dem nächsten Timerüberlauf wirksam werden:
Datenblatt S.97 schrieb:
The OCR1A Compare Register will then be updated with the value in the Buffer Register at the next timer clock cycle the TCNT1 matches TOP. The update is done at the same timer clock cycle as the TCNT1 is cleared and the TOV1 flag is set.
TCNT1 ist in diesem Moment bereits wieder 28.
Außerdem wird TCCR1A (von 2) auf 130 gesetzt -> PWM mit fallender Flanke beim OC-Match, steigender beim TOV. Derzeit sollte der Pin bei Gnd bleiben, oder?
-nach dem 7ten IRQ sollte dann die Verarbeitung der zu ssendenden Bits erfolgen (ICR Manipulieren)
usw

Leider scheint das laut Bascom-Simulator nicht ganz zu stimmen - hier trotzdem mal der
Code:
$crystal = 8000000
$regfile = "attiny2313.dat"
$hwstack = 20                                               ' default use 32 for the hardware stack
$swstack = 20                                               'default use 10 for the SW stack
$framesize = 10                                             'default use 40 for the frame space
$baud = 19200
$sim

Radio_out Alias Portb.0
'****Interruptvektoren****
On Oc1a Oc1a_isr Nosave
'Variablen
Dim Bitzaehler As Byte
Dim Adress As Byte
Dim Kommando As Byte
'****NEC init****
Tccr1a = 2                                                  'für normale I/O und WGM=14
Ocr1a = 17999
Icr1 = 17999
Ddrb.3 = 1                                                  'PortB.3 (OC1A) ist Ausgang
Bitzaehler = 39
'****Interrupts freigeben****
Enable Oc1a
Enable Interrupts

'****zu sendende Daten****
Adress = &B10011101
Kommando = &B00101000

'****senden starten****
Tccr1b = 25                                                 'Startburst wahrscheinlich Takt zu lang
SBI PORTB, PORTB3                                           'ggf TCNT vorladen (auch in ISR)

'******Hauptschleife******
Do
  'leer
Loop

'*****Interrupt Service Routinen****
Oc1a_isr:
      $asm                                                  'Assemblerblockanfang
      PUSH XH
      PUSH XL
      PUSH R16
      IN R16, SREG
      PUSH R16                                              'Register und SREG gesichert
      Loadadr Bitzaehler , X                                'X Enthält Bitzaehler -speicheradresse
      LD R16, X                                             'R16=Bitzähler
      DEC R16                                               'R16 dekrementiert
      ST X+, R16                                            'Bitzähler zurückgespeichert, X enthält Adress-Adresse
      BREQ naechstesVorbereiten                             'final wurde gesendet, Sprung (nächstes vorbereiten)
      CPI R16, 35                                           'Z=1 <==> Bitzaehler (jetzt)= 35
      BREQ burstAbschalten                                  'dann springe burstAbschalten
      cpi R16, 34                                           'Z=1<==>Bitzaehler=34
      BREQ pauseEnde                                        'dann -> Pause Ende
      CPI R16, 33                                           'C=1<==>Bitzaehler<33
      BRSH dasWars                                          '>=33->dasWars (0,35,34 wurden bereits behandelt, bleiben die 32 Bits)
      CPI R16, 17                                           'Carry bei den letzten 17 als einem Endburst (R16=0) plus 16  Bits(R16=16..1)
      BRCC AdresseStimmt                                    'sonst überspringe
      inc XL                                                'X =Kommandoadresse

   Adressestimmt:
      LD R16, X
      LSL R16                                               'einmal nach links schieben, MSB wandert ins Carry
      BRCS EinsSenden                                       'bei 1 springe, bei 0 bleibe
      INC R16                                               'links wurde ne 0 rausgeschoben, deswegen wird die 0 hinten zur 1 invertiert
      ST X, R16                                             'Byte zurückgespeichert
      LDI R16, hbyte(8999)
      Out Icr1h , R16
      LDI R16, lbyte(8999)
      Out Icr1l , R16                                       'Icr Angepaßt
      RJMP dasWars                                          'Fall 0 erledigt

   Einssenden:
      ST X, R16                                             'die hinten eingeschobene 0 ist bereits invers zur 1 - Byte zurückgespeichert
      LDI R16, hbyte(17999 )
      Out Icr1h , R16
      LDI R16, lbyte(17999 )
      Out Icr1l , R16                                       'Icr Angepaßt
      RJMP dasWars                                          'Fall 1 erledigt

   Pauseende:
      LDI R16, hbyte(4499)
      Out Ocr1ah , R16
      LDI R16, lbyte(4499)                                  'Ocr Vieder Auf 562,5µs
      Out Ocr1al , R16                                      'wird erst nach dem nächsten TOV aktiv
      LDI R16, 130
      Out Tccr1a , R16                                      'B3 wird PWM (lo->hi beim nächsten TOV)
      RJMP dasWars                                          '->dasWars

   Burstabschalten:
      CBI PORTB, PORTB3                                     'B3 -> lo
      RJMP dasWars                                          '->dasWars

   Naechstesvorbereiten:
      LDI R16 , 24
      Out Tccr1b , R16                                      'Timer Steht
      LDI R16, hbyte(17999)
      Out Ocr1ah , R16
      Out Icr1h , R16
      LDI R16, lbyte(17999)
      Out Ocr1al , R16
      Out Icr1l , R16                                       'Ocr1a Und Icr1 Für Nächsten Start Vorbereitet
      LDI R16, 39
      STS {Bitzaehler},R16                                  'Bitzäehler reinitialisiert (39)
      LDI R16,0
      Out Tcnt1h , R16
      Out Tcnt1l , R16                                      'Timer = 0 (Reload, ggf anpassen)
      LDI R16, 2
      Out Tccr1a , R16                                      'B3 ist wieder I/O

   Daswars:
      POP R16
      Out Sreg , R16
      POP R16
      POP XL
      POP XH                                                'SREG und Register (R16, XH, XL) wiederhergestellt
$end Asm
Return
Hab das mal durch den Simulator gejagt, und nach dem setzen von PortB.3 die Clock resettet (Cycles=0). Dann wird IRQ (das PUSH) erreicht bei:
- 2,2505ms (und bis auf das DEC nix)
- 4,50075ms (nix)
- 6,751ms (nix)
- 9,00125ms hier wird, wie zu erwarten PORTB von 8 auf 0 dez gesetzt (also B3 gelöscht), wirksam bei 9,003625
-11,25125ms hier wird OCR1A=4499, und TCCR1A=130

soweit stimmts also - aus irgeneinem Grund erfolgt aber schon jetzt der nächste IRQ bei
-11,814ms Das OCR1A scheint also schon zu greifen
Warum???
Und noch verwirrender: Die nächsten IRQs kommen jetzt bei
-12,377ms
-12,939ms
-13,5022ms
-14,065ms
-...
also ca alle 562µs passend zu OCR1A - aber der Timer sollte bis ICR1=17999 laufen. ICR IST 17999 (zumindest bis die erste 0 geschoben wurde), TCCR1A IST 130, TCCR1B IST 25...
ICR erhält schon die richtigen werte (8999 bzw 17999).

Ist das jetzt ein Bug des Simulators (Bascom Vollversion 2.0.7.3.001), oder seh ich den Wald vor lauter Bäumen nicht?
Kann das vielleicht mal wer mit'nem LA/Oszi und 'nem Tiny2313 etc in Hardware testen?
 
hab auch nur die 2.0.7.1 version, kanns also auch nich direkt testen,.

sollte nach einem durchlauf normal,nmicht in adress bzw in XL die negierte adress stehen?!
 
Nein...
in X (also beide 8-bit-Register)wird bei jedem(!) IRQ erstmal die Adresse von Bitzaehler geladen, um eben diesen in's Rechenregister (16) laden zu können, nach dem DEC wird der (ekrementierte) Bitzähler wieder zurückgespeichert. Gleichzeitig wird X im eins erhöht (postincrement, das "+") - jetzt ist X also die Adresse des Adressbytes im Speicher. Falls ein Bit aus dem Kommandobyte zu senden ist, wird X nochmals incrementiert (vor dem Label Adresse stimmt - hier wäre allerdings ein ADIW besser - wenn nämlich XL dabei überläuft (also Adress und Komando unterschiedliche XH haben), wirkt sich das INC (der Überlauf) nicht auf XH aus Add Immediate to Word logischerweise schon).
Da wir in dieser Version zum Reload des Bitzählers am Ende "STS" verwenden, bleibt es eigentlich dabei, aber XL (sowie auch XH, R16 und das SREG) werden am Ende einer jeden (!) ISR wieder auf den Zustand zurückgesetzt, den sie vor Eintritt in die ISR hatten (Push rettet sie auf den Stack, Pop holt sie wieder zurück.

Adress und Komando sollten je 2 mal gesendet werden, und dabei je invertiert. Also:
-Zuerst die 4*2,25ms high Pegel
-dann 2,25ms lo Pegel (während der ISR läuft der Timer weiter, irgendwann wird OCR1A auf die 562,5µs eingestellt, und das PWM-Verhalten neu festgelegt. OCR1A sollte(!) aber erst nach dem nächsten Überlauf aktualisiert werden - dieser sollte(!) erst bei 17999 Takten (nach dem Eintritt in diese ISR) stattfinden, also nach weiteren
-2,25ms (Pause zu Ende), durch den Überlauf sollte jetzt der Pin high gehen (so hatten wir ja den PWM (CompareOutputMode) festgelegt, außerdem sollte erst jetzt(!) OC1A aus dem Pufferregister geladen werden
-nach 562,5µs geht der PWM-Pin wieder lo, außerdem wird in der ISR jetzt ggf der Überlaufpunkt manipuliert (sofort wirksam - ICR). Das ist das erste Adressbit. es wird invertiert "hinten eingeschoben" (bzw addiert).
-nach weiteren 7 Bits ist also das Adressbit (einmal) gesendet, in der Speicherzelle steht jetzt die invertierte Adresse.
-diese senden wir jetzt nochmal, also weitere 8 IRQs. Danach befindet sich also eine Invertierte invertierte Adresse in der Speicherzelle.
-Dasselbe mit dem 8-Bit-Kommando.
deswegen startet der Bitzähler mit 39. 39 dekrements bis 0. 4 für den Start-Burst, 2 für die Pause, 8 für die Adresse, 8 für die invertierte Adresse, 8für das Kommando, 8 für das invertierte Kommando, einer für das final, (wo das senden des nächsten Paketes vorbereitet wird, und der Ausgang auf dauerhaft lo gelegt wird).

Der Timer läuft immer im FastPWM bis ICR (oder gar nicht - Prescaler=0). Ob einer der OC-Pins überhaupt verwendet wird, oder ob überhaupt je ein OC-Match stattfindet, der Timer läuft immer beim IC-Match über (bzw einen Timer-Takt später). ICR ist entweder 17999 oder 8999, OCR1A konstant bei 4499, der OCR1A-IRQ KANN ALSO EIGENTLICH GAR NICHT ALLE 562,5ms erfolgen...

Die einzige Erklärung, die ich jetzt habe ist, daß der Simulator (fälschlicherweise) statt des Überlaufes bei ICR einen Überlauf bei OC1A simuliert...
ggf werd ich das morgen mal durch den Simulator vom Studio jagen...
ansonsten

Diiiiiiiinooooooo....
 
Dann bau mal vor den Kommentar "senden starten" noch 'ne kurze Warte-Instruktion mit ein...

Ich bin ja sowas von gespannt...

Edit:
Ist das jetzt ein Bug des Simulators (Bascom Vollversion 2.0.7.3.001), oder seh ich den Wald vor lauter Bäumen nicht?
Scheint wohl eher ein Feature zu sein...
Bascom Online Hilfe zu "Simulate" schrieb:
 
Irgendwie hat mein guter alter CoreDuo (Satellite) massive Probleme mit dem aktuellen Visual Studio...
Sobald man da irgendwas klickt, im Simulator, sscheint der Rechner für ein paar Minuten zu schlafen...
Hab aber trotzdem mal angefangen - Die ersten Interrupts fallen (nach dem Starten des Timers die Uhr zurückgesetzt) bei (ms):
2,26088
4,51075
6,76088
9,01075 -> bisher je 2,25ms mit high-Pegel=Startburst
11,26088 -> 2,25ms mit lo-Pegel, erste Hälfte Pause, hier wird COM und OCR1A geändert, jetzt wirds spannend
14,06325 -> weitere 2,25ms-562µs, also die 2e hälfte und die Zeit bis OCR1A -> scheint zu stimmen
16,31338 -> nochmal 2,25ms wäre jetzt eine "1" - allerdings ist die mMn zu viel -> nochmal nachdenken
18,56338 -> 2,25ms = "1"
19,68838 -> 1,125ms="0"
20,81338 -> 1,125ms="0"
23,06338 -> 2,25ms="1"
25,31338 -> 2,25ms="1"
27,56338 ->2,25ms="1"
28,68838 ->1,125ms="0"
30,93838 -> 2,25ms="1" (wenn mann die erste 1 wegläßt, ist das die Adresse)
32,06338 ->1,125ms="0" (ok, erstes invertiertes Adressbit)
(in viereinhalb Stunden fährt mein Bus zur Arbeit - das schaff ich nicht mehr...)
34,31338 -> 2,25ms="1" stimmt auch
36,56338 -> 2,25ms="1" ok

Ok, zumindest die Überläufe scheinen doch zu stimmen, die eine 1 muß ich nochmal überdenken, ansonsten sollte es stimmen.
Brenn das mal in einen Tiny, und horch den OC1A-Pin mit'nem LA ab...

Edit: einen hab ich jetzt noch:
37,68838 -> 1,125ms="0", stimmt auch
 
soooo ;)


sieht doch ganz ok aus, aber hab gemerkt, das der tiny ja mit der internen freq 20mhz hat :confused:
Adress = &B10011101
Kommando = &B00101000
EDIT: es faellt auf, das beim Kommandobyte eine 1 zuviel ist,.
sonst duerft es stimmen, wenn man sich die 1 wegdenk, und alles 1 stelle nach rechts schiebt,.

das Raster ist 10ms
 

Anhänge

  • Analyzer_0001_0012.gif
    Analyzer_0001_0012.gif
    5,7 KB · Aufrufe: 10
Der interne RC kann mit 8 oder 4MHz schwingen - default ist 8.
Außerde gibt es einen systemClockPrescaler, der (zur Laufzeit) mit unterschiedlichen Werten beladen werden kann. Dabei gibt es 2 mögliche Grundeinstellungen (defaultwerte): 1 oder 8. welcher der beiden verwendet wird, legt die CKDIV8-Fuse fest. Default läuft der Controller also mit 8MHz/8=1MHz.

Paßt der LA-Mitschnitt denn zu den beiden Bytes? muß ich nachher mal schauen - der Startburst und die Pause scheint ja auch zu fehlen, oder?
 
Hallo zusammen,
ich lese hier schon seit einiger Zeit sehr interessiert mit, bin mir aber nicht sicher, ob ich alles mitbekommen habe.
Was ich irgendwie vermisse ist die Erzeugung der Trägerfrequenz. Dino hatte da mal ganz zu Anfang nach gefragt, danach war nie wieder die Rede davon. Auf jeden Fall mir nicht bewusst.
Ich bin in ASM der totale Anfänger aber soviel erkenne ich doch, dass der Timer nicht mit 38KHz läuft. Auch auf dem letzten Bild war nichts davon zu sehen, aber ich weiß auch nicht, ob das das Ausgangssignal eines TSOPs war. Der würde die Trägerfrequenz ja wegfiltern.
Kommt das noch oder habt ihr euch doch für eine externe Erzeugung entschieden?

Gruß

Rolf
 
Trägerfrequenz?
davon stand im ersten Beitrag nichts... hmm...
Dann ist mir jetzt auch klar, was Dino meinte...
Jetzt soll das ganze also so aussehen, daß der Pin wenn er high sein soll, in Wirklichkeit mit 38kHz "flimmert"...
Ihr wißt schon, daß 38kHz 'ne total bescheuerte Frequenz ist... ich könnte auf 37,9147kHz kommen...
Wäre jetzt die Frage zu klären, ob Bonze dafür den zweiten Timer opfern will, und insbesondere auch einen dessen PWM-Pins (der andere wäre weiterhin verwendbar, allerdings nur mit ca 209 möglichen Schritten, und eben 37,9...kHz Frequenz.

es geht hier um sowas wier RC5, richtig? Also auch eine (IR)LED. dann könnte man die LED (ggf mit'ner Schottky in Reihe(?)) zwischen die beiden Timer PWMs hängen...

Bonze, wie gehts weiter?
 
Hallo,

es geht hier um sowas wier RC5, richtig? Also auch eine (IR)LED. dann könnte man die LED (ggf mit'ner Schottky in Reihe(?)) zwischen die beiden Timer PWMs hängen...
stimmt :p

Alles was irgendwie nach IR-Fernbedienung aussieht hat ne Trägerfrequenz. :D
Wenn die nicht ganz genau paßt dann ist es auch nicht so schlimm. Ich hab irgendwo schonmal gelesen das ein TSOP für 38kHz sogar 40kHz Trägerfrequenz empfängt. Dann zwar nicht mehr mit der vollen Empfindlichkeit, aber es soll noch gehen.

Man hat bei IR-Fernbedienungen also quasi eine Amplitudenmodulation der Trägerfrequenz mit 100% (voll oder garnix). Mit dieser Frequenz flimmert die IR-LED dann die Bits in die Gegend. Sonst wär das ja schlecht von Lichtquellen wie Leuchtstoffröhren (100Hz Flimmern) und diversem anderen zu unterscheiden.

Gruß
Dino
 
IR-Fernbedienung hat er aber genauso wenig erwähnt, wie die Trägerfrequenz. Mir war NEC bisher kein Begriff - ok, hätte ich 'nach suchen können. Egal jetzt auch. Also entweder "mein Weg" mit 2 Timern, oder "Dein Vorschlag", der mit nur einem Timer auskommt, aber deutlich mehr Rechenzeit braucht (IRQ alle 562,6µs)
Bonze, jag das mal bitte Durch Deinen LA (warum der 9ms-High-Pegel am Anfang fehlt, ist mir allerdings nicht klar)
Code:
$crystal = 8000000
$regfile = "attiny2313.dat"
$hwstack = 20                                               ' default use 32 for the hardware stack
$swstack = 20                                               'default use 10 for the SW stack
$framesize = 10                                             'default use 40 for the frame space
$baud = 19200
$sim

Radio_out Alias Portb.0
'****Interruptvektoren****
On Oc1a Oc1a_isr Nosave
'Variablen
Dim Bitzaehler As Byte
Dim Adress As Byte
Dim Kommando As Byte
'****NEC init****
Tccr1a = 2                                                  'für normale I/O und WGM=14
Ocr1a = 17999
Icr1 = 17999
Ddrb.3 = 1                                                  'PortB.3 (OC1A) ist Ausgang
Bitzaehler = 38
'****Interrupts freigeben****
Enable Oc1a
Enable Interrupts

'****zu sendende Daten****
Adress = &B10011101
Kommando = &B00101000

'****senden starten****
Tccr1b = 25                                                 'Startburst wahrscheinlich Takt zu lang
SBI PORTB, PORTB3                                           'ggf TCNT vorladen (auch in ISR)

'******Hauptschleife******
Do
  'leer
Loop

'*****Interrupt Service Routinen****
Oc1a_isr:
      $asm                                                  'Assemblerblockanfang
      PUSH XH
      PUSH XL
      PUSH R16
      IN R16, SREG
      PUSH R16                                              'Register und SREG gesichert
      Loadadr Bitzaehler , X                                'X Enthält Bitzaehler -speicheradresse
      LD R16, X                                             'R16=Bitzähler
      DEC R16                                               'R16 dekrementiert
      ST X+, R16                                            'Bitzähler zurückgespeichert, X enthält Adress-Adresse
      BREQ naechstesVorbereiten                             'final wurde gesendet, Sprung (nächstes vorbereiten)
      CPI R16, 34                                           'Z=1 <==> Bitzaehler (jetzt)= 34
      BREQ burstAbschalten                                  'dann springe burstAbschalten
      cpi R16, 33                                           'Z=1<==>Bitzaehler=33
      BREQ pauseEnde                                        'dann -> Pause Ende                                         
      BRSH dasWars                                          '>33->dasWars (0,33,34 wurden bereits behandelt, bleiben die 32 Bits)
      CPI R16, 17                                           'Carry bei den letzten 17 als einem Endburst (R16=0) plus 16  Bits(R16=16..1)
      BRCC AdresseStimmt                                    'sonst überspringe
      inc XL                                                'X =Kommandoadresse

   Adressestimmt:
      LD R16, X
      LSL R16                                               'einmal nach links schieben, MSB wandert ins Carry
      BRCS EinsSenden                                       'bei 1 springe, bei 0 bleibe
      INC R16                                               'links wurde ne 0 rausgeschoben, deswegen wird die 0 hinten zur 1 invertiert
      ST X, R16                                             'Byte zurückgespeichert
      LDI R16, hbyte(8999)
      Out Icr1h , R16
      LDI R16, lbyte(8999)
      Out Icr1l , R16                                       'Icr Angepaßt
      RJMP dasWars                                          'Fall 0 erledigt

   Einssenden:
      ST X, R16                                             'die hinten eingeschobene 0 ist bereits invers zur 1 - Byte zurückgespeichert
      LDI R16, hbyte(17999 )
      Out Icr1h , R16
      LDI R16, lbyte(17999 )
      Out Icr1l , R16                                       'Icr Angepaßt
      RJMP dasWars                                          'Fall 1 erledigt

   Pauseende:
      LDI R16, hbyte(4499)
      Out Ocr1ah , R16
      LDI R16, lbyte(4499)                                  'Ocr wieder Auf 562,5µs
      Out Ocr1al , R16                                      'wird erst nach dem nächsten TOV aktiv
      LDI R16, 130
      Out Tccr1a , R16                                      'B3 wird PWM (lo->hi beim nächsten TOV)
      RJMP dasWars                                          '->dasWars

   Burstabschalten:
      CBI PORTB, PORTB3                                     'B3 -> lo
      RJMP dasWars                                          '->dasWars

   Naechstesvorbereiten:
      LDI R16 , 24
      Out Tccr1b , R16                                      'Timer Steht
      LDI R16, hbyte(17999)
      Out Ocr1ah , R16
      Out Icr1h , R16
      LDI R16, lbyte(17999)
      Out Ocr1al , R16
      Out Icr1l , R16                                       'Ocr1a Und Icr1 Für Nächsten Start Vorbereitet
      LDI R16, 38
      STS {Bitzaehler},R16                                  'Bitzäehler reinitialisiert (38)
      LDI R16,0
      Out Tcnt1h , R16
      Out Tcnt1l , R16                                      'Timer = 0 (Reload, ggf anpassen)
      LDI R16, 2
      Out Tccr1a , R16                                      'B3 ist wieder I/O

   Daswars:
      POP R16
      Out Sreg , R16
      POP R16
      POP XL
      POP XH                                                'SREG und Register (R16, XH, XL) wiederhergestellt
$end Asm
Return
Jetzt sollte(!) die überzählige 1 weg sein
 
Also auch eine (IR)LED. dann könnte man die LED (ggf mit'ner Schottky in Reihe(?)) zwischen die beiden Timer PWMs hängen...
Klar ginge das, aber dann wird es recht aufwendig, den gepulsten Strom über die max 20mA oder so zu bringen, die die Pins des Controllers aushalten.
Ich würde das eher so machen, dass ein 8-bit Timer im CTC Modus durchläuft, um die 38KHz zu erzeugen. Die 37,9 sind absolut ok. Wenn du mehrere KHz neben der Mittenfrequenz des Empfängers liegst, geht die Reichweite runter, mehr nicht.
Ein zweiter Timer schaltet den ersten dann ein und aus, um so die High- und Lowpegel der Bits zu erzeugen.
So kannst du einen Transistor an den OC-Ausgang hängen und die IR LED mit vielleicht 60mA pulsen.
Allerdings hättest du bei CTC 50% DutyCycle, was jetzt nicht den geforderten 25-30 % entspricht. Folglich kannst du mit den Strömen auch nicht so hoch gehen. Besser wäre da noch der Fastpwm mit OCR und ICR, wie du es für die Bits gemacht hast. Da könntest du beliebige DC einstellen. Nur haben die wenigsten Controller einen 8-bit Timer mit Fastpwm.

Gruß

Rolf
 
Hmm... IR-LEDs nehmen gern bis zu 50mA, oder?
Was soll denn Timer an-/abschalten heißen? Anhalten über den Prescaler? Dann stimmt dessen Timing doch nicht mehr... nein dann sollte man eher das DDR umschalten. Bei lo von OC1A hast Du dann also den Pullup oder Tristate auf Basis/Gate, bei Hi die geforderten Vcc oder Gnd. Basis/Gate ist also mit einem geeigneten R auf Gnd zu ziehen, ggf sollte man den Pullup auch noch abschalten (PUD)?
Das mit dem Frequenzkorrektem FasPWM war mir schon klar - Timer0 hat aber (hier) kein ICR - folglich müssen wir für die Reichweite OC0A, und für den geforderten DC (<>50%) OC0B nehmen.
Dann wäre in der TOV0-ISR das Datenrichtungsbit von OC1A zu setzen, in der OC0B-ISR zu löschen. Beides Immediate - wären also keine Register zu retten. ((IRQ->IVT->ISR-Label)SBI/CBI Reti).

Alternativ könnte man die beiden Timer doch aber auch 2 komplementäre Transistoren/Mosfets schalten lassen, zwischen denen die LED(s) hängt/en, oder?

Moment: wo werden 25-30 DC gefordert? Bei der 38kHz-NEC-Trägerfrequenz?
 
Ne traegerfrequenz brauch ich nich.. Will die schaltung anstatt nen tsop einsetzen

Hallo Bonze,
der TSOP ist ein IR Empfänger Chip, du willst hier aber wohl senden. Wenn du auf der Empfängerseite einen Standard IR Empfänger einsetzen willst oder schon installiert hast, musst du eine Trägerfrequenz benutzen.

Hmm... IR-LEDs nehmen gern bis zu 50mA, oder?
Was soll denn Timer an-/abschalten heißen? Anhalten über den Prescaler? Dann stimmt dessen Timing doch nicht mehr... nein dann sollte man eher das DDR umschalten.
Meinst du, wenn du das DDR umschaltest, dass dann das Timing stimmt? Meine favorisierte Art wäre, die COMxx Bits von Toggle auf Set/Clear umzuschalten, je nachdem, wie der Ausgang beschaltet ist.
Egal wie, der Timer wird immer irgendwo zwischendrin hängen und ich glaube es lohnt nicht den Aufwand, das zu verhindern.

Dann wäre in der TOV0-ISR das Datenrichtungsbit von OC1A zu setzen, in der OC0B-ISR zu löschen.
Ich bin mir nicht sicher, ob ich die Funktion deiner Timer richtig verstehe. Ist Timer0 für die 38KHz zuständig oder Timer1?
Wenn Timer0, dann brauchst du doch keine TOV0-ISR und keine OC0B-ISR. Der läuft doch ständig durch.
Wenn Timer1, dann müsstest du deine ganzen Timings ändern, da Timer0 ja 8-bit ist und Werte wie 17999 nicht kann. Würde bedeuten, dass du auch noch den Prescaler umschalten müsstest, um 560µs und bis zu 100ms akkurat hinzubekommen.
Lass doch lieber dein Programm wie es ist, Timer0 erzeugt permanent die 38KHz und Timer1 schaltet den OC0 Pin in geeigneter Weise ein und aus.

Alternativ könnte man die beiden Timer doch aber auch 2 komplementäre Transistoren/Mosfets schalten lassen, zwischen denen die LED(s) hängt/en, oder?
Wie gesagt, mehr Schaltungsaufwand, keine funktionale Verbesserung, wenig Programm Vereinfachung.

Die Länge des gesamten NEC-Pakets variiert übrigens nicht zwischen 50 und 100ms. Es ist konstant 67,5ms lang und die Wiederholung nach weiteren 40ms dauert knapp 12ms.
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)