Forum: Compiler & IDEs Peter Dannegger's RC5 Beispiel


von gastfrager (Gast)


Lesenswert?

Hallo,

ich hätte ein paar Fragen zum RC5 Code Beispiel vom Peter Dannegger.
Und zwar ist dieses Beispiel für den Atmel Mega8 geschrieben soweit ich 
informiert bin.

1 Frage) Hat vielleicht jemand in diesem Forum diesen code auf einen 
AT90S8515 portiert? Ist das überhaupt möglich?

2) Abgesehen von den Biblothekenimporten müssen diese 5 Zeilen für den 
AT90S8515 angepasst werden
1
UBRRL = bauddivider;      //set baud rate
2
UBRRH = bauddivider >> 8;
3
UCSRA = 0;        //no U2X, MPCM
4
UCSRC = 1<<URSEL^1<<UCSZ1^1<<UCSZ0;  //8 Bit
5
UCSRB = 1<<RXEN^1<<TXEN;    //enable RX, TX

Also UBBRL und UBBRH müssen durch UBBR ersetzt werden.

Aber die UCSRA,UCSRB und UCSRC da bin ich ein bißchen ratlos. Denn die 
Entsprechungen davon beim AT90S8515 laut Spezifikation lauten USR und 
UCR, dennoch weiß ich nicht wie ich des genau modifizieren soll.

3) Ich verstehe nicht warum sich der Code aus RC5.C in Main.C 
wiederholt. Meiner Ansicht nach genügt es Main.C mit Main.h zu 
kompilieren und RC5.C wegen der Wiederholung aus dem Projekt 
rauszulassen. Liege ich hier falsch?


Ich habe gegoogelt und mir hier die threads zu rc5 durchgelesen aber so 
richtig geholfen hat mir nichts davon.
Bin für jeden Tipp dankbar.

Gruß

von Wolfgang Horn (Gast)


Lesenswert?

Hi, Gastfrager,

setze ich meinen Stundensatz an, dann kostet das Lesen einer Mail, das 
Heraussuchen in den Datenblättern zu den beiden Prozessoren und die 
Formulierung des Codes schon mehr, als ein Atmega8 bei ebay kostet.

Selbst dann könnten noch Unterschiede sein, die Dich ein zweites und 
drittes Mal fragen ließen, und wegen meiner ersten Antwort würde ich 
mich moralisch verpflichtet fühlen auch diese zu beantworten.


Die Prozessoren von AT90X und AtmegaX sind eine Familie, natürlich haben 
die Entwickler das Bewährte nicht zweimal entwickelt.

Wenn Du nicht nur bißchen rumspielen möchtest, sondern ein Projekt 
erfolgreich zu Ende führen mit dem Anspruch "ich hab's selber gemacht!", 
dann kommst Du um das Durchackern der Datenblätter sowieso nicht herum.

Eine wesentlioche Hilfe war mir der AtmanAVR-Compiler mit dem 
Code-Wizzard zum Einstellen der I/O-Register.
Hol Dir eine 30-Tage-Testversion bei wwww.atmanecl.com, erzeuge mit dem 
Code-Wizzard ein Skelett-Programm mit Nutzung der seriellen 
Schnittstelle für den Atmega 8 und dann dasselbe für den Prozessor 
Deiner Wahl - und Du siehst die Unterschiede.


Ciao
Wolfgang Horn

von Oliver (Gast)


Lesenswert?

>1 Frage) Hat vielleicht jemand in diesem Forum diesen code auf einen
>AT90S8515 portiert? Ist das überhaupt möglich?

Mit Sicherheit.

>2) Abgesehen von den Biblothekenimporten müssen diese 5 Zeilen für den
>AT90S8515 angepasst werden

Richtig. Extra dafür steht in den Kommentaren, was in den Zeilen 
passiert. Das ist eine ganz einfache Initialisierung der uart. Nimm das 
Datenblatt für deinen Prozessor, und finde raus, wie es da geht. Atmel 
hat normalerweise für alles Codebeispiele in den Datenblättern.

>3) Ich verstehe nicht warum sich der Code aus RC5.C in Main.C
>wiederholt. Meiner Ansicht nach genügt es Main.C mit Main.h zu
>kompilieren und RC5.C wegen der Wiederholung aus dem Projekt
>rauszulassen. Liege ich hier falsch?

In der Version, die ich kenne, wiederholt sich da nichts. Das einzige, 
was dich verwirren könnte, ist die Verwendung von signal.h statt 
interrupt.h.

Oliver

von gastfrager (Gast)


Lesenswert?

Hallo Wolfgang,

ich erwarte von niemandem das er meine Arbeit macht. Ich dachte 
vielleicht hat den Code schon jemand mal nach At90S8515 portiert.
Danke für deinen Tipp mit der Software.

Gruß

von gastfrager (Gast)


Lesenswert?

Hallo Oliver,

sorry dass ich nachhake aber es muß sein.

Die Version die ich vom Peters Code habe besteht aus Main.C, Main.h und 
RC5.C.
Und da
RC5.C
1
#include "main.h"
2
3
#define RC5TIME   1.778e-3    // 1.778msec
4
#define PULSE_MIN  (uchar)(XTAL / 512 * RC5TIME * 0.4 + 0.5)
5
#define PULSE_1_2  (uchar)(XTAL / 512 * RC5TIME * 0.8 + 0.5)
6
#define PULSE_MAX  (uchar)(XTAL / 512 * RC5TIME * 1.2 + 0.5)
7
8
9
uchar  rc5_bit;        // bit value
10
uchar  rc5_time;        // count bit time
11
uint  rc5_tmp;        // shift bits in
12
uint  rc5_data;        // store result
13
14
15
SIGNAL (SIG_OVERFLOW0)
16
{
17
  uint tmp = rc5_tmp;        // for faster access
18
19
  TCNT0 = -2;          // 2 * 256 = 512 cycle
20
21
  if( ++rc5_time > PULSE_MAX ){      // count pulse time
22
    if( !(tmp & 0x4000) && tmp & 0x2000 )  // only if 14 bits received
23
      rc5_data = tmp;
24
    tmp = 0;
25
  }
26
27
  if( (rc5_bit ^ xRC5_IN) & 1<<xRC5 ){    // change detect
28
    rc5_bit = ~rc5_bit;        // 0x00 -> 0xFF -> 0x00
29
30
    if( rc5_time < PULSE_MIN )      // to short
31
      tmp = 0;
32
33
    if( !tmp || rc5_time > PULSE_1_2 ){    // start or long pulse time
34
      if( !(tmp & 0x4000) )      // not to many bits
35
        tmp <<= 1;        // shift
36
      if( !(rc5_bit & 1<<xRC5) )    // inverted bit
37
        tmp |= 1;        // insert new bit
38
      rc5_time = 0;        // count next pulse time
39
    }
40
  }
41
42
  rc5_tmp = tmp;
43
}


mit dem Anfang von Main.c übereinstimmt
1
/************************************************************************/
2
/*                                                                      */
3
/*                      RC5 Remote Receiver                             */
4
/*                                                                      */
5
/*              Author: Peter Dannegger                                 */
6
/*                      danni@specs.de                                  */
7
/*                                                                      */
8
/************************************************************************/
9
#include "main.h"
10
11
#define RC5TIME   1.778e-3    // 1.778msec
12
#define PULSE_MIN  (uchar)(XTAL / 512 * RC5TIME * 0.4 + 0.5)
13
#define PULSE_1_2  (uchar)(XTAL / 512 * RC5TIME * 0.8 + 0.5)
14
#define PULSE_MAX  (uchar)(XTAL / 512 * RC5TIME * 1.2 + 0.5)
15
16
17
uchar  rc5_bit;        // bit value
18
uchar  rc5_time;        // count bit time
19
uint  rc5_tmp;        // shift bits in
20
uint  rc5_data;        // store result
21
22
23
SIGNAL (SIG_OVERFLOW0)
24
{
25
  uint tmp = rc5_tmp;        // for faster access
26
27
  TCNT0 = -2;          // 2 * 256 = 512 cycle
28
29
  if( ++rc5_time > PULSE_MAX ){      // count pulse time
30
    if( !(tmp & 0x4000) && tmp & 0x2000 )  // only if 14 bits received
31
      rc5_data = tmp;
32
    tmp = 0;
33
  }
34
35
  if( (rc5_bit ^ xRC5_IN) & 1<<xRC5 ){    // change detect
36
    rc5_bit = ~rc5_bit;        // 0x00 -> 0xFF -> 0x00
37
38
    if( rc5_time < PULSE_MIN )      // to short
39
      tmp = 0;
40
41
    if( !tmp || rc5_time > PULSE_1_2 ){    // start or long pulse time
42
      if( !(tmp & 0x4000) )      // not to many bits
43
        tmp <<= 1;        // shift
44
      if( !(rc5_bit & 1<<xRC5) )    // inverted bit
45
        tmp |= 1;        // insert new bit
46
      rc5_time = 0;        // count next pulse time
47
    }
48
  }
49
50
  rc5_tmp = tmp;
51
}
52
53
54
55
56
void putchar( char c )
57
{
58
  while( (UCSRA & 1<<UDRE) == 0 );
59
  UDR = c;
60
}
61
62
63
void puts( char *s )
64
{
65
  while( *s )
66
    putchar( *s++ );
67
}
68
69
70
int main( void )
71
{
72
  uint i;
73
  char s[30];
74
75
  TCCR0 = 1<<CS02;      //divide by 256
76
  TIMSK = 1<<TOIE0;      //enable timer interrupt
77
78
  UBRRL = bauddivider;      //set baud rate
79
  UBRRH = bauddivider >> 8;
80
  UCSRA = 0;        //no U2X, MPCM
81
  UCSRC = 1<<URSEL^1<<UCSZ1^1<<UCSZ0;  //8 Bit
82
  UCSRB = 1<<RXEN^1<<TXEN;    //enable RX, TX
83
84
  sei();
85
  puts( "RC5-Dekoder:\n\r" );
86
  for(;;){        // main loop
87
    cli();
88
    i = rc5_data;      // read two bytes from interrupt !
89
    rc5_data = 0;
90
    sei();
91
    if( i ){
92
      DDRB = i;        // LED output
93
      putchar(( i >> 11 & 1) + '0');  // Toggle Bit
94
      putchar(' ');
95
      itoa( i >> 6 & 0x1F, s, 10);  // Device address
96
      puts( s );
97
      putchar(' ');
98
      itoa((i & 0x3F) | (~i >> 7 & 0x40), s, 10); // Key Code
99
      puts( s );
100
      puts( "\n\r" );
101
    }
102
  }
103
}

kann ich RC5.c gleich rauslassen- oder habe ich da irgendwie ein Brett 
vorm kopf? Darauf bezieht sich meine Frage.

Gruß

von Oliver (Gast)


Lesenswert?

Du hast natürlich Recht. Da scheint es mehrere Versionen zu geben.

In der aus
Beitrag "Fernbedien RC5 Empfänger"

ist das nicht so.

Oliver

von Peter D. (peda)


Lesenswert?

gastfrager wrote:

> Die Version die ich vom Peters Code habe besteht aus Main.C, Main.h und
> RC5.C.
> Und da
> RC5.C

Würde mich aber stark wundern, wenn die alle aus dem selben Posting 
stammen.

Man kann natürlich nicht erwarten, daß man Code aus verschiedenen 
Postings ungesehen zusammenpappen kann.

Und bei Fragen immer die exakte URL zum Code mit angeben.
Die Glaskugeln bei den meisten Leuten hier sind nämlich in der Regel 
kaputt.


Peter

von gastfrager (Gast)


Lesenswert?

Hi,

jo tatsächlich.
Ich habe es von einer anderen Quelle. In dem Originalposting vom Peter 
ist alles richtig.

Danke

Gruß

von andrea ciuffoli (Gast)


Lesenswert?

t  code = 0;
    unsigned int  gIRdata = 0, data = 0, addr = 0;

    unsigned int bit_mask;

    if (!IR)
    {
  for (i = 0; i < TIME_MAX && !IR; i += TIME_STEP)
  {
      DelayUs(TIME_STEP);
  }
  if (i > TIME_MAX) return -1;
  if (i < TIME_MIN) return -1;

  OffTime = i;

  for (i = 0; i < TIME_MAX && IR; i += TIME_STEP)
  {
      DelayUs(TIME_STEP);
  }
  if (i > TIME_MAX) return -1;
  if (i < TIME_MIN) return -1;

  OnTime = i;


        j = (OffTime + OnTime * 2 + OffTime / 2);

        for (k = 0; k < j; k += TIME_STEP)
      DelayUs(TIME_STEP);


  //********************************************
  //* get address and data
  //********************************************
  for (i = 0; i < 12; i++)
  {
      if (i > 5)
      {
    if (IR)
    {
        code <<= 1;
    }
    else
    {
        code <<= 1; code |= 1;
    }
      }

     j = (OffTime + OnTime);

     for (k = 0; k < j; k += TIME_STEP)
    DelayUs(TIME_STEP);
  }

        data = code;

  *RC5data = code;
  *RC5addr = code;

  sprintf(tmp, "Off %4d On %4d", OffTime, OnTime);
  WriteLCD( 1, 1, tmp);

  //*****************************************************
  //* only to dump the data received with a single led
  //*****************************************************
        tmp[0] = '<';

        bit_mask = 1 << (6 - 1);

     for (i = 0; i < 6; i++)
    {
        if ((data & bit_mask) == 0)
    tmp[i+1] = '0';
      else
    tmp[i+1] = '1';

        data <<= 1;
     }
        tmp[i+1] = '>';
  tmp[i+2] = '\0';

  WriteLCD( 2, 2, tmp);

  DelayMs(250);

  return 0;
    }
    return -1;
}

von Di P. (drpepper) Benutzerseite


Lesenswert?

Neue Frage, gleiches Thema:

Was tut die Zeile
1
  TCNT0 = -2;     // 2 * 256 = 512 cycle
?
Wieso wird ins TIMER-Count Register eingegriffen?

Ich möchte den Timer2 eines AtMega88 für rc5 und Sekundenerzeugung 
zusammen benutzen, und bin mir unsicher über den Prescaler, den ich 
wählen sollte.
Momentan verwende ich den Prescaler 256 auf 8MHz und erzeuge Sekunden so 
(Timer2 zählt nur bis 250):
1
ISR (TIMER2_OVF_vect) {
2
  if(t1 < 125) {
3
    t1++;
4
  }
5
  else {
6
    t1 = 0;
7
    newsecond = 1;
8
  }
9
}

von Di P. (drpepper) Benutzerseite


Lesenswert?

hat jemand eine idee?

von Karl H. (kbuchegg)


Lesenswert?

Di Pi schrieb:
> Neue Frage, gleiches Thema:
>
> Was tut die Zeile
>
1
  TCNT0 = -2;     // 2 * 256 = 512 cycle
> ?
> Wieso wird ins TIMER-Count Register eingegriffen?

Weil er haben möchte, dass der Timer nicht von 0 bis 255 zählen muss, 
bis der nächste Interrupt kommt, sondern schon etwas früher. Also setzt 
der den Timer auf 256 - 2 = 254. Dann macht der Timer noch 2 Ticks und 
löst den nächsten Interrupt aus. 2 Ticks bei einem Vorteiler von 256 
macht 512 Prozessorzyklen.

> Momentan verwende ich den Prescaler 256 auf 8MHz und erzeuge Sekunden so
> (Timer2 zählt nur bis 250):

Wie machst du es, dass der Timer nur bis 250 zählt?

von Bingo (Gast)


Lesenswert?

Was tut die Zeile

  TCNT0 = -2;     // 2 * 256 = 512 cycle


-2 ist auch 0xFE , mit einer prescaler von 256 , und 2 interrupts 
(ticks) zum overflow interrupt (am 0) , dann dauert es  2 * prescaler 
cycles = 512 cycles.

mfg
Bingo Dänemark

von Di P. (drpepper) Benutzerseite


Lesenswert?

1
  // Uhr für Timestep-Erzeugung
2
  TCCR2A = (1 << WGM22) | (1 << WGM21) | (1 << WGM20);
3
  TCCR2B = (1 << CS22) | (1 << CS21);
4
  TIMSK2 = (1 << TOIE2);
5
  OCR2A = 250;

Das ist meine Timer-Init.



Sehe ich es dann richtig, dass ich den Timer nicht für eine Zeitbasis 
verwenden kann? Ich bin mir nicht sicher, ob ich das Rücksetzen des 
TCNT-Registers einfach auskommentieren darf.

von Karl H. (kbuchegg)


Lesenswert?

Di Pi schrieb:
>
1
>   // Uhr für Timestep-Erzeugung
2
>   TCCR2A = (1 << WGM22) | (1 << WGM21) | (1 << WGM20);
3
>   TCCR2B = (1 << CS22) | (1 << CS21);
4
>   TIMSK2 = (1 << TOIE2);
5
>   OCR2A = 250;
6
>
>
> Das ist meine Timer-Init.
>
>
>
> Sehe ich es dann richtig, dass ich den Timer nicht für eine Zeitbasis
> verwenden kann? Ich bin mir nicht sicher, ob ich das Rücksetzen des
> TCNT-Registers einfach auskommentieren darf.

Dein Timer arbeitet in einem ganz anderen Modus.
Peters Timer tickt einfach nur vor sich hin. Dein Timer ist im CTC Modus 
(wenn ich das richtig sehe)

von Peter D. (peda)


Lesenswert?

Di Pi schrieb:
>
1
>   // Uhr für Timestep-Erzeugung
2
>   TCCR2A = (1 << WGM22) | (1 << WGM21) | (1 << WGM20);
3
>   TCCR2B = (1 << CS22) | (1 << CS21);
4
>   TIMSK2 = (1 << TOIE2);
5
>   OCR2A = 250;
6
>
>
> Das ist meine Timer-Init.

Dann weißt Du ja, welche Interruptzeit rauskommt.
Für den RC5-Interrupt brauchst Du etwa 100µs.


> Sehe ich es dann richtig, dass ich den Timer nicht für eine Zeitbasis
> verwenden kann?

Außer im Countermodus ist jeder Timer eine Zeitbasis.
Du kannst auch im 100µs Interrupt auf 1s runterteilen (Zählvariable).

Da Du aber 3 Timer hast, kannst Du auch ruhig einen weiteren nehmen.


Peter

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.