Forum: Compiler & IDEs Fragen zu Peter Dannegger's RC5 Beispiel


von Markus _. (markush)


Lesenswert?

Hi Allz,

da ich momentan wieder mehr Zeit habe mich den µC zu widmen versuche ich 
mein lange rausgeschobenes IR-Projekt fertig zu bekommen.

Ich habe genannten Code aus der Codesammlung genommen und entsprechend 
angepasst. Rausgekommen ist ein IR-Einschalter für PC's. Man kann eine 
Taste in einem 2313 programmieren, die im eeprom abgespeichert wird, 
welche bei Knopfdruck dann den PC einschaltet. So weit so gut.

Nun hab ich zwei Probleme:

1.) Von der RC5.C Routine hab ich relativ wenig bis nichts verstanden.
2.) Ich möchte es universeller machen so daß auch verschiendene IR-Codes 
benutzt werden können.

Generell verstehe ich nicht so recht wie die empfangen Codes überhaupt 
in den µC "kommen". Definiert ist:
1
#define  xRC5_IN    PIND
2
#define  xRC5    PD2      // IR input low active

Mit dem ersten define wird festgelegt das xRC5_IN die Eingangspins des 
Port D "anspricht". Ist dadurch automatisch festgelegt das alle Pins 
dieses Ports als Eingänge arbeiten?
Zum anderen ist xRC5 der Datenport an dem die IR-Diode dranhängt. Nur 
hier kommen ja wirklich Daten in den µC, sprich hier kommt das 
demodulierte Signal des IR-Empfänger als Rechteck Impuls an, oder?

Das war's mal zum Einstieg, sonst wird das ein recht langer Monolog und 
keiner liest das ;).

Hoffe ich frage nicht zu viel Grundsätzliches, aber ich hab wirklich 
viel gesucht und nicht wirklich eine Antwort auf meine Fragen bekommen.

Gruß und good Night, Markus

von johnny.m (Gast)


Lesenswert?

> Ist dadurch automatisch festgelegt das alle Pins dieses Ports als Eingänge
> arbeiten?

Mit einem #define wird nur eine Textersetzung definiert. Das hat aber 
auch gar nichts mit irgendwelchen Einstellungen zu tun. Wenn da etwas 
wie
1
#define xRC5_IN PIND
steht, bedeutet das nur, dass an jeder Stelle, an der der Ausdruck 
"xRC5_IN" im Programmcode auftaucht, dieser durch "PIND" ersetzt wird 
(wobei "PIND" wiederum in der Headerdatei als 
Special-Function-I/O-Register definiert ist und durch seine Adresse im 
I/O-Space ersetzt wird...). Den Port als Eingang konfigurieren geht über 
die Register DDRD und PORTD.

von Markus _. (markush)


Lesenswert?

johnny.m wrote:
> Den Port als Eingang konfigurieren geht über
> die Register DDRD und PORTD.


Hi johnny.m,

diese grundlegenden Sachen wie man Ports als Aus- bzw. Eingang 
konfiguriert sind mir schon klar. Nur in diesem Beispiel wird der PortD 
eben nicht so konfiguriert! Das Codebeispiel ist hier zu finden: 
Beitrag "Fernbedien RC5 Empfänger".
Das funktioniert wie gesagt perfekt. Der PortB wird auch konfiguriert da 
im Beispiel LED's angesteuert werden. Aber der Eingang an PortD wird 
nirgends konfiguriert?!?

Wieso geht das dann?



Markus

von johnny.m (Gast)


Lesenswert?

> Nur in diesem Beispiel wird der PortD eben nicht so konfiguriert!
Er wird gar nicht explizit konfiguriert, wenn ich mich nicht verguckt 
habe. Also sind die Register DDRD und PORTD mit den default-Reset-Werten 
"0x00" belegt. Das bedeutet Port D ist als Eingang ohne Pull-Ups 
konfiguriert.

von Markus _. (markush)


Lesenswert?

johnny.m wrote:
>> Nur in diesem Beispiel wird der PortD eben nicht so konfiguriert!
> Er wird gar nicht explizit konfiguriert, wenn ich mich nicht verguckt
> habe. Also sind die Register DDRD und PORTD mit den default-Reset-Werten
> "0x00" belegt. Das bedeutet Port D ist als Eingang ohne Pull-Ups
> konfiguriert.

Sehr interessant! Das wußte ich bisher nicht, ist aber im Nachhinein 
logisch (wie meistens).

Danke!

Markus

von Jens Ziegler (Gast)


Lesenswert?

Hallo miteinander. Hat vielleicht jemand ein Programm zum Senden per RC5 
geschrieben? Oder gar eine Platine? Ich hab leider noch (fast) nichts 
dazu gefunden.

von Jens Ziegler (Gast)


Lesenswert?

Kann man ne Fernbedienung + µC für sowas missbrauchen?

von neuer (Gast)


Lesenswert?

Mit FastAvr-Basic.
Ich benutze die AdressBit und die Command-Bit zusammen, um mindestens 1 
Byte zu übertragen.

$Device= m16
$Stack = 32
$Clock = 8
$Timer1=Timer, Prescale=1, CompareA=Toggle, Clear

Dim ToggleBit As Bit
Dim Adr As Byte, Command As Byte
Dim wert As Byte, wert1 As Byte , wert2 As Byte, zaehler As Byte

Declare Sub RC5out(adr As Byte, command As Byte)
Declare Sub BitLow()
Declare Sub BitHigh()

Const Delay=89

Set DDRD.5
Compare1A=101
Start Timer1

Adr=0

Do
For zaehler= 60 To 178
    wert= zaehler
    wert1=Shift(Right,6, wert)
    wert2=&b00111111 & wert
  RC5out(wert1,wert2)
  WaitMs 255
Next
Loop

Sub RC5out(adr As Byte, command As Byte)

Local i As Byte

BitHigh()
BitHigh()
If ToggleBit Then
  BitHigh()
Else
  BitLow()
End If
For i=0 To 4
  If adr.4 Then
    BitHigh()
  Else
    BitLow()
  End If
  Shift(Left,1,adr)
Next
For i=0 To 5
  If command.5 Then
    BitHigh()
  Else
    BitLow()
  End If
  Shift(Left,1,command)
Next
$Timer1=Timer, CompareA=Reset
End Sub

Sub BitLow()
$Timer1=Timer, CompareA=Toggle
WaitUs Delay
$Timer1=Timer, CompareA=Reset
WaitUs Delay
End Sub

Sub BitHigh()
WaitUs Delay
$Timer1=Timer, CompareA=Toggle
WaitUs Delay
$Timer1=Timer, CompareA=Reset
End Sub

von Markus _. (markush)


Lesenswert?

Hi Leutz,

möchte mal den ersten Block aus der genannten Routine durchkauen. In der 
Interruptroutine wird zuerst folgendes geprüft:
1
if( ++rc5_time > PULSE_MAX ){      // count pulse time
2
    if( !(tmp & 0x4000) && tmp & 0x2000 )  // only if 14 bits received
3
      rc5_data = tmp;
4
    tmp = 0;
5
                }

Der erste if-Ausdruck (++rc5_time > PULSE_MAX) prüft bei jedem Durchlauf 
ob eben diese Bedingung erfüllt ist, zählt dabei aber jedesmal rc5_time 
hoch.
1. Richtig?
Wenn nun das 15. Bit (0x4000) nicht gesetzt ist und das 14. Bit schon 
dann wurden insgesamt 14 Bits empfangen und der rc5_data Variablen 
übergeben.
2. Richtig?

Markus

von Markus _. (markush)


Lesenswert?

Da niemand widerspricht geh ich mal davon aus dasalles richtig ist :).

Jetzt kommt's aber dicke:
1
if( (rc5_bit ^ xRC5_IN) & 1<<xRC5 )    {    // change detect
2
    rc5_bit = ~rc5_bit;        // 0x00 -> 0xFF -> 0x00
3
4
    if( rc5_time < PULSE_MIN )      // to short
5
      tmp = 0;
6
7
    if( !tmp || rc5_time > PULSE_1_2 ){    // start or long pulse time
8
      if( !(tmp & 0x4000) )      // not to many bits
9
        tmp <<= 1;        // shift
10
      if( !(rc5_bit & 1<<xRC5) )    // inverted bit
11
        tmp |= 1;        // insert new bit
12
      rc5_time = 0;        // count next pulse time
13
                    }
14
                      }

Hier versteh ich schon mal die erste Zeile nicht. rc5_bit ist ja 
deklariert als "uchar rc5_bit". xRC5_IN stellt den gesamt Port D (also 
8bit) dar. Dieser wird bitweise XOR verknüpft mit eben rc5_bit. Und was 
hats dann mit dem "& 1<<xRC5" auf sich?
Bitte mal um Erklärung des Ausdrucks, steht irgendwie auf der Leitung...

Markus

von johnny.m (Gast)


Lesenswert?

Es soll der Zustand eines Portpins (xRC5) abgefragt werden. Das ganze 
ist für das Programm aber nur dann von Interesse, wenn sich der Zustand 
des Pins im Vergleich zum vorhergehenden geändert hat. Daher die 
(bitweise) EXOR-Verknüpfung, die nur dann eine "1" ergibt, wenn die 
Ausgangswerte unterschiedlich sind. Da bei der EXOR-Verknüpfung der 
komplette Port eingelesen wird, jedoch für die Auswertung nur das eine 
Bit xRC5 von Bedeutung ist, wird dieses mit einer bitweisen 
UND-Verknüpfung maskiert, so dass alle anderen Bits als "0" gelesen 
werden. Der Ausdruck in der Klammer der if-Anweisung ist also nur dann 
wahr, wenn das Bit xRC5 in xRC5_in (also der Pin 2 in PIND) sich 
gegenüber dem in rc5_bit gesicherten vorherigen Zustand geändert hat, 
wobei durch das EXOR (und das anschließende toggeln von rc5_bit) die 
Richtung der Änderung (Low->High oder High->Low) keine Rolle spielt.

von Markus _. (markush)


Lesenswert?

Vielen Dank für deine Ausführungen, is mir jetzt endlich klar.

Mal den Rest anschauen...

Markus

von Lutz (Gast)


Lesenswert?

ich habe den code umgeschrieben um die ausgabe auf dem lcd zu machen:

i ist vom typ uint
1
      lcd_putc(( i >> 11 & 1) + '0');  
2
      lcd_putc(' ');
3
      itoa( i >> 6 & 0x1F, s, 10);      // Device address 
4
      lcd_puts( s );
5
      lcd_putc(' ');
6
      itoa((i & 0x3F) | (~i >> 7 & 0x40), s, 10);  // Key Code
7
      lcd_puts( s );
8
      lcd_puts( "          " );
9
      lcd_gotoxy(0, 1);
kann mir mal bitte jemand die Selektion der einzelnen Device bzw. Key 
Code Adressen mittels der oben beschriebenen "Masken" erklären
angenommen i ist 1
dann ist doch z.b: i & 0x3F
 00000001
&00111111
---------
 00000001
also wie das mit dem UND bzw. ODER funktioniert versteh ich glaub ich, 
aber das mit dem "schieben" ist mir noch unklar

von Peter D. (peda)


Lesenswert?

Hier ist die Bitfolge des RC5 beschrieben:

http://www.sprut.de/electronic/ir/rc5.htm#2


Für C-Operatoren bemühe bitte ein C-Buch oder Google.


Peter

von Karl H. (kbuchegg)


Lesenswert?

@Peter:
Sieh dir das mal durch. Ich denke das ist ein Fehler drinn

@Lutz:
Weil da eine etwas 'trickreiche' Code Sequenz drinnen ist,
mach ich dir das mal.

>
1
>       lcd_putc(( i >> 11 & 1) + '0');
2
>       lcd_putc(' ');
3
>       itoa( i >> 6 & 0x1F, s, 10);      // Device address
4
>       lcd_puts( s );
5
>       lcd_putc(' ');
6
>       itoa((i & 0x3F) | (~i >> 7 & 0x40), s, 10);  // Key Code
7
>       lcd_puts( s );
8
>       lcd_puts( "          " );
9
>       lcd_gotoxy(0, 1);
10
>

Das Format ist

 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
 | 1 |-C6| T | A4| A3| A2| A1| A0| C5| C4| C3| C2| C1| C0|
 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+

 C0 bis C5 PLUS -C6 ergeben das Kommando
 A0 bis A4          ergeben die Adresse


(Ich borg mir von Sprut die Notation aus, dass ein - vor einem
Bit ein invertiertes Bit bedeutet)

>       lcd_putc(( i >> 11 & 1) + '0');

Das verschiebt die Bitsequenz um 11 Stellen nach rechts

 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |-C6| T |
 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+

danach wird mit einer 1 geundet (und somit werden alle Bits
ausser dem Bit 0b00000000000001 zu 0

 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | T |
 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+

anschliessend wird noch '0' addiert. War T eine binäre 0,
dann kommt bei der Addition '0' heraus, war T 1 dann ergibt
die Addition '1'. -> Ausgabe aufs Display

>       itoa( i >> 6 & 0x1F, s, 10);      // Device address

Wieder: Die original empfangene Bitsequenz um 6 Stellen nach
rechts verschieben

 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |-C6| T | A4| A3| A2| A1| A0|
 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+

danach mit 0x1F verunden

 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |-C6| T | A4| A3| A2| A1| A0|
 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
&  0   0   0   0   0   0   0   0   0   1   1   1   1   1
 ---------------------------------------------------------
 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | A4| A3| A2| A1| A0|
 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+

und die Adresse steht fertig da zur Ausgabe (vorher die
Binärzahl noch mittels itoa in einen String verwandeln)

>       itoa((i & 0x3F) | (~i >> 7 & 0x40), s, 10);  // Key Code

Jetzt kommt der 'tricky' Teil

Fang wieder beim Original an:

 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
 | 1 |-C6| T | A4| A3| A2| A1| A0| C5| C4| C3| C2| C1| C0|
 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+

mit 0x3F verunden

 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
 | 1 |-C6| T | A4| A3| A2| A1| A0| C5| C4| C3| C2| C1| C0|
 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
&  0   0   0   0   0   0   0   0   1   1   1   1   1   1
----------------------------------------------------------
 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | C5| C4| C3| C2| C1| C0|
 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+

Dieses Ergebnis wird mit 'etwas' verodert. Was ist dieses
'etwas'

(~i >> 7 & 0x40),

Also, wieder i hernehmen

 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
 | 1 |-C6| T | A4| A3| A2| A1| A0| C5| C4| C3| C2| C1| C0|
 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+

und mal alle Bits umdrehen (für die Tilde ~)

 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
 | 0 | C6|-T |-A4|-A3|-A2|-A1|-A0|-C5|-C4|-C3|-C2|-C1|-C0|
 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+

danach um 7 Stellen nach rechts schieben:

 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | C6|-T |-A4|-A3|-A2|-A1|
 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+

jetzt mit 0x40 verunden

 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | C6|-T |-A4|-A3|-A2|-A1|
 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
&  0   0   0   0   0   0   0   1   0   0   0   0   0   0
----------------------------------------------------------
 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+

Damit ist der rechte Ausdruck vom | berechnet und die beiden
Teilausdrücke können zusammenge-oder-t werden

 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | C5| C4| C3| C2| C1| C0|
 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
-----------------------------------------------------------
 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+
 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | C5| C4| C3| C2| C1| C0|
 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+

Tja. Und jetzt sieht man, das C6 um 1 Stelle zu weit nach
rechts geschoben wurde (wenn ich mich nicht vertan habe).

Eigentlich sollte C6 an Position 0x40 zu liegen kommen.
Dazu muss die Bitsequenz aber nur um 6 Stellen nach
rechts verschoben werden.

Peter: Kannst du das nochmal kontrollieren?
Hab ich einen Fehler gemacht oder hast du dich verhaut?
Ich denke deas müsste
  (~i >> 6 & 0x40),
lauten.





von Peter D. (peda)


Lesenswert?

@Karl,

stimmt,

(~i >> 6 & 0x40)

muß es heißen.


Peter

von lutz (Gast)


Lesenswert?

klasse, danke, aber warum wir bei T eine '0' addiert

von Karl H. (kbuchegg)


Lesenswert?

Damit auf der Ausgabe auch eine '0' oder eine '1' erscheint.


Damit das LCD eine 0 hinmalt, muss man ihm das Zeichen '0'
schicken. Du hast aber nur eine Ziffer. Also muss man diese
Ziffer in das korrespondierende Zeichen verwandeln (ASCII
Code studieren).

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.