Forum: Compiler & IDEs Timing RC5 decodieren nach Peter Dannegger


von michael (Gast)


Lesenswert?

Guten Tag,
ja ich habe die Suche benutzt.
Jedoch habe ich immer noch ein kleines Verständnisproblem.

Ich benutze:

ATiny45
WinAVR / AVR Studio 6
Fuse eingestellt INTRCOSC_4MHZ_6CK_14CK_64MS
Makefile:          F_CPU =  4000000  / OPT = s
In der Souce:
1
C-Code
2
#ifndef F_CPU
3
#define F_CPU 4000000UL
4
#endif
5
6
#define timer0_start TCCR0B = 0x01 //keinen teiler 80 alle 10µs
7
#define timer0_stopp TCCR0B = 0x00
8
#define timer0  TCNT0
9
10
#define timer1_start TCCR1 = 0x03 //64
11
#define timer1_stopp TCCR1 = 0x00
12
#define timer1  TCNT1
13
14
#define RC5TIME   1.778e-3    // 1.778msec
15
#define PULSE_MIN  (uchar)(XTAL / 512 * RC5TIME * 0.4 + 0.5)
16
#define PULSE_1_2  (uchar)(XTAL / 512 * RC5TIME * 0.8 + 0.5)
17
#define PULSE_MAX  (uchar)(XTAL / 512 * RC5TIME * 1.2 + 0.5)
18
//min = 889µs/26 T/aufrufinterwall
19
20
21
22
#include <avr/io.h>
23
#include <stdint.h>
24
#include <avr/interrupt.h>
25
#include <util/delay.h>
26
#include <stdbool.h>
27
#include <avr/interrupt.h>
28
#include <stdlib.h>
29
30
31
#define uchar unsigned char
32
#define uint unsigned int
33
34
#define  xRC5_IN    PINB
35
#define  xRC5    PB2    // IR input low active
36
37
#define  XTAL    11.0592e6
38
39
uchar  rc5_bit;        // bit value
40
uchar  rc5_time;        // count bit time
41
uint  rc5_tmp;        // shift bits in
42
volatile uint rc5_data;        // store result
43
44
SIGNAL (SIG_OVERFLOW0)
45
{
46
PORTB |= (1<<PB4) ; // set
47
  //volatile uint tmp = rc5_tmp;        // for faster access
48
49
  TCNT0 = -2;          // 2 * 256 = 512 cycle
50
51
  if( ++rc5_time > PULSE_MAX ){      // count pulse time
52
    if( !(rc5_data & 0x4000) && rc5_data & 0x2000 )  // only if 14 bits received
53
    rc5_data = rc5_data;
54
    rc5_data = 0;
55
  }
56
57
  if( (rc5_bit ^ xRC5_IN) & 1<<xRC5 ){    // change detect
58
    rc5_bit = ~rc5_bit;        // 0x00 -> 0xFF -> 0x00
59
60
    if( rc5_time < PULSE_MIN )      // to short
61
    rc5_data = 0;
62
63
    if( !rc5_data || rc5_time > PULSE_1_2 ){    // start or long pulse time
64
      if( !(rc5_data & 0x4000) )      // not to many bits
65
      rc5_data <<= 1;        // shift
66
      if( !(rc5_bit & 1<<xRC5) )    // inverted bit
67
      rc5_data |= 1;        // insert new bit
68
      rc5_time = 0;        // count next pulse time
69
    }
70
  }
71
72
  rc5_tmp = rc5_data;
73
PORTB &= ~(1<<PB4); //reset
74
}
75
int main(void)
76
{
77
  DDRB = 0b111011; //Schieberegisterports als Ausgang PB2 di
78
        PORTB = 0b000100; // Pull up pb2 ein
79
        TCCR0B = 1<<CS02;      //divide by 256
80
        TIMSK = 1<<TOIE0;      //enable timer interrupt
81
        sei();
82
}
83
  while(1)
84
  {
85
          asm("nop");
86
        }

Nun habe ich mit meinem Oszi PB4 untersucht und PB2.

Alle 280µs wird PB4, für 20µs high.
Eigentlich sollte er aber doch alle 16,384 sek aufgerufen werden?
Dies ist aber doch viel zu lang!

Wie dem auch sei.
Anschließend habe ich den Teiler auf 1 gestellt.
Nun wir die ISR alle 26µs aufgerufen.

Ich vermude das nun diese
#define PULSE_MIN  (uchar)(XTAL / 512  RC5TIME  0.4 + 0.5)
#define PULSE_1_2  (uchar)(XTAL / 512  RC5TIME  0.8 + 0.5)
#define PULSE_MAX  (uchar)(XTAL / 512  RC5TIME  1.2 + 0.5)
Werte nicht mehr stimmen.

Interpretiere ich das so richtig:?
#define PULSE_MIN  sollte in etwa 889µs sein
#define PULSE_1_2  sollte in etwa 1778µs sein
#define PULSE_MAX  ???? 24,889ms

Nun habe ich versucht diese Werte anzupassen.

Zeit : Aufrufinterwall

z.B.:
PULSE_MIN = 889 : 2 = 34

Das ausgelesene Ergebnis ist immer noch 0. :-(

Die ISR erkennt die Flankenwechsel.
Wenn ich rc5_bit an PB4 ausgebe, so entspricht dies genau dem PB2 
Signal.

Zitat:"Danach muß man nur im Bitabstand weiter abtasten und voila, nach 
14 Bitzeiten hat man alle Bits.
Damit es nun dabei nicht zu Zeitverschiebungen aufgrund zu hoher 
Toleranzen kommt, wird bei jeder Flanke neu synchronisiert. Um die 
Hilfsflanken auszublenden, werden nur Flanken, die nach 0,8 ... 1,2 
Bitzeiten kommen ausgewertet."

Was ist mein Fehler.
Freue mich über jeden Tipp.

Vielen Dank

von michael (Gast)


Lesenswert?

Noch eine Anmerkung.
Ich habe das bis jetzt so verstanden:

Die Routine SIGNAL (SIG_OVERFLOW0) wird zyklisch aufgerufen.

Hat sich der Wert von PinB2 verändert.
Wird als erstes geprüft ob dies zu schnell geschehen ist.
Also kleiner 889µs war.
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
    rc5_data = 0;


Als nächstes wird geprüft ob es ein langer Puls war.
Also länger als 1778µs oder schon Daten erfasst wurden.
Also eine Zahl>0 in rc5_data steht.
Ist eins von beidem der Fall und im höchstwertigen Bit steht keine 1,
werden alle Bits in rc5_data um eine Stelle nach links geschoben.
Nun wird geprüft ob PINB2 gerade 0 ist.
Ist dies der Fall wird eine ein hinzugefügt, sonst nicht.
Das heist eine 0 bleibt stehen.
1
    if( !rc5_data || rc5_time > PULSE_1_2 ){    // start or long pulse time
2
      if( !(rc5_data & 0x4000) )      // not to many bits
3
      rc5_data <<= 1;        // shift
4
      if( !(rc5_bit & 1<<xRC5) )    // inverted bit
5
      rc5_data |= 1;        // insert new bit
6
      rc5_time = 0;        // count next pulse time
7
    }

Jedoch muss ich dazu relativ genau die passende Stelle treffen.

In irgendeiner Versuch habe ich mal 1010101010101010101 und soweiter 
rausbekommen. Also habe ich jeden Puls gespeichert. Was ja aber falsch 
ist.

von Stefan E. (sternst)


Lesenswert?

michael schrieb:
> Makefile:          F_CPU =  4000000  / OPT = s

michael schrieb:
> #define  XTAL    11.0592e6

von michael (Gast)


Lesenswert?

Danke.

Zumindes steht jetzt schon mal was in rc5 data.
Halt leider nur 1 zen. :(

von michael (Gast)


Lesenswert?

Hallo,

wenn ich für #define  XTAL    11.0592e6 auf 0.8592e6 ändere,

 Scheint es zu funktionieren.

Dann läuft der AVR aber doch viel zu langsam!!

von Christian B. (luckyfu)


Lesenswert?

dein  AVR läuft mit 4MHz, der neue Wert ist somit auch falsch.

von michael (Gast)


Lesenswert?

bei diesen Code ist ein Pulse 3,6µs lang.

1\(3,6e-6 = 0,277777 Mhz
1
while(1)
2
{
3
asm("nop");
4
PORTB |= (1<<PB4) ; // set
5
asm("nop");
6
PORTB &= ~(1<<PB4); //reset
7
}

von Stefan E. (sternst)


Lesenswert?

CKDIV8-Fuse deaktivieren.

von michael (Gast)


Lesenswert?

Danke.

Das entfernen das hackens macht aber irgentwie keinen Unterschied.


Ich Programmiere mit JTAGICE3 und AVR STUDIO 6.

An sich scheint es aber zu funktioren. Da ich nach setzen von
RSTDISBL ihn nicht mehr Programieren konnte.

Warum ist eigentlich der Orginalwert

#define  XTAL    11.0592e6

Wo doch in der Anleitung etwas von 4Mhz steht.

Und warum ist die Zahl nicht klatt?

Bei 4 Mhz muss ich doch 4e6 reinschreiben. Oder nich?

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

michael schrieb:

> An sich scheint es aber zu funktioren. Da ich nach setzen von
> RSTDISBL ihn nicht mehr Programieren konnte.

RSTDISBL ist böse. Damit kann der Programmer nun kein RESET mehr 
durchführen und ihn damit auch nicht mehr programmieren. Einzige 
Möglichkeit, ihn wiederzuerwecken wäre HV-Programmierung.

> Warum ist eigentlich der Orginalwert
>
> #define  XTAL    11.0592e6
>
> Wo doch in der Anleitung etwas von 4Mhz steht.

Der Source von Peter ist schon zienlich alt. Bei neueren 
Entwicklungsumgebungen wird F_CPU verwendet. Ersetze daher alle 
Vorkommnisse von XTAL durch F_CPU.

> Und warum ist die Zahl nicht klatt?

Nicht glatt? Es gibt auch Quarze mit "krummen" Werten ;-)

> Bei 4 Mhz muss ich doch 4e6 reinschreiben. Oder nich?

Ja.

Bist Du überhaupt sicher, dass das eine RC5-Fernbedienung ist? Das ist 
ein uraltes Protokoll und wird heutzutage eigentlich gar nicht mehr 
verwendet. Bist Du Dir unsicher, solltest Du Dir mal IRMP anschauen.

Gruß,

Frank

von michael (Gast)


Lesenswert?

Vielen dank für deinen Beitrag!

Ich hab mich schon gewundert das die Pulse nicht exakt den längen von 
RC5 entsprechen.

Auch lief mein Controller nicht mit 8Mhz.

Ursache:
Fuse eingestellt INTRCOSC_4MHZ_6CK_14CK_64MS

Richtig ist:
Fuse eingestellt INTRCOSC_4MHZ_6CK_14CK_0MS

Ich schau mir dann gleich mal  IRMP an.

Nochmals Danke.

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.