www.mikrocontroller.net

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


Autor: Markus _neu (markush)
Datum:

Bewertung
0 lesenswert
nicht 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:
#define  xRC5_IN    PIND
#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

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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
#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.

Autor: Markus _neu (markush)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Markus _neu (markush)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Jens Ziegler (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Jens Ziegler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kann man ne Fernbedienung + µC für sowas missbrauchen?

Autor: neuer (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Markus _neu (markush)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Leutz,

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

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

Autor: Markus _neu (markush)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da niemand widerspricht geh ich mal davon aus dasalles richtig ist :).

Jetzt kommt's aber dicke:
if( (rc5_bit ^ xRC5_IN) & 1<<xRC5 )    {    // change detect
    rc5_bit = ~rc5_bit;        // 0x00 -> 0xFF -> 0x00

    if( rc5_time < PULSE_MIN )      // to short
      tmp = 0;

    if( !tmp || rc5_time > PULSE_1_2 ){    // start or long pulse time
      if( !(tmp & 0x4000) )      // not to many bits
        tmp <<= 1;        // shift
      if( !(rc5_bit & 1<<xRC5) )    // inverted bit
        tmp |= 1;        // insert new bit
      rc5_time = 0;        // count next pulse time
                    }
                      }

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

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Markus _neu (markush)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank für deine Ausführungen, is mir jetzt endlich klar.

Mal den Rest anschauen...

Markus

Autor: Lutz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich habe den code umgeschrieben um die ausgabe auf dem lcd zu machen:

i ist vom typ uint
      lcd_putc(( i >> 11 & 1) + '0');  
      lcd_putc(' ');
      itoa( i >> 6 & 0x1F, s, 10);      // Device address 
      lcd_puts( s );
      lcd_putc(' ');
      itoa((i & 0x3F) | (~i >> 7 & 0x40), s, 10);  // Key Code
      lcd_puts( s );
      lcd_puts( "          " );
      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

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

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

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.





Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Karl,

stimmt,

(~i >> 6 & 0x40)

muß es heißen.


Peter

Autor: lutz (Gast)
Datum:

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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).

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.