mikrocontroller.net

Forum: Compiler & IDEs Peter Dannegger's RC5 Beispiel


Autor: gastfrager (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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
UBRRL = bauddivider;      //set baud rate
UBRRH = bauddivider >> 8;
UCSRA = 0;        //no U2X, MPCM
UCSRC = 1<<URSEL^1<<UCSZ1^1<<UCSZ0;  //8 Bit
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ß

Autor: Wolfgang Horn (Gast)
Datum:

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

Autor: Oliver (Gast)
Datum:

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

Autor: gastfrager (Gast)
Datum:

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

Autor: gastfrager (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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
#include "main.h"

#define RC5TIME   1.778e-3    // 1.778msec
#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)


uchar  rc5_bit;        // bit value
uchar  rc5_time;        // count bit time
uint  rc5_tmp;        // shift bits in
uint  rc5_data;        // store result


SIGNAL (SIG_OVERFLOW0)
{
  uint tmp = rc5_tmp;        // for faster access

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

  if( ++rc5_time > PULSE_MAX ){      // count pulse time
    if( !(tmp & 0x4000) && tmp & 0x2000 )  // only if 14 bits received
      rc5_data = tmp;
    tmp = 0;
  }

  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
    }
  }

  rc5_tmp = tmp;
}



mit dem Anfang von Main.c übereinstimmt
/************************************************************************/
/*                                                                      */
/*                      RC5 Remote Receiver                             */
/*                                                                      */
/*              Author: Peter Dannegger                                 */
/*                      danni@specs.de                                  */
/*                                                                      */
/************************************************************************/
#include "main.h"

#define RC5TIME   1.778e-3    // 1.778msec
#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)


uchar  rc5_bit;        // bit value
uchar  rc5_time;        // count bit time
uint  rc5_tmp;        // shift bits in
uint  rc5_data;        // store result


SIGNAL (SIG_OVERFLOW0)
{
  uint tmp = rc5_tmp;        // for faster access

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

  if( ++rc5_time > PULSE_MAX ){      // count pulse time
    if( !(tmp & 0x4000) && tmp & 0x2000 )  // only if 14 bits received
      rc5_data = tmp;
    tmp = 0;
  }

  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
    }
  }

  rc5_tmp = tmp;
}




void putchar( char c )
{
  while( (UCSRA & 1<<UDRE) == 0 );
  UDR = c;
}


void puts( char *s )
{
  while( *s )
    putchar( *s++ );
}


int main( void )
{
  uint i;
  char s[30];

  TCCR0 = 1<<CS02;      //divide by 256
  TIMSK = 1<<TOIE0;      //enable timer interrupt

  UBRRL = bauddivider;      //set baud rate
  UBRRH = bauddivider >> 8;
  UCSRA = 0;        //no U2X, MPCM
  UCSRC = 1<<URSEL^1<<UCSZ1^1<<UCSZ0;  //8 Bit
  UCSRB = 1<<RXEN^1<<TXEN;    //enable RX, TX

  sei();
  puts( "RC5-Dekoder:\n\r" );
  for(;;){        // main loop
    cli();
    i = rc5_data;      // read two bytes from interrupt !
    rc5_data = 0;
    sei();
    if( i ){
      DDRB = i;        // LED output
      putchar(( i >> 11 & 1) + '0');  // Toggle Bit
      putchar(' ');
      itoa( i >> 6 & 0x1F, s, 10);  // Device address
      puts( s );
      putchar(' ');
      itoa((i & 0x3F) | (~i >> 7 & 0x40), s, 10); // Key Code
      puts( s );
      puts( "\n\r" );
    }
  }
}


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

Gruß

Autor: Oliver (Gast)
Datum:

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

Autor: Peter Dannegger (peda)
Datum:

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

Autor: gastfrager (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

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

Danke

Gruß

Autor: andrea ciuffoli (Gast)
Datum:

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

Autor: Di Pi (drpepper) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Neue Frage, gleiches Thema:

Was tut die Zeile
  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):
ISR (TIMER2_OVF_vect) {
  if(t1 < 125) {
    t1++;
  }
  else {
    t1 = 0;
    newsecond = 1;
  }
}

Autor: Di Pi (drpepper) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hat jemand eine idee?

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

Bewertung
0 lesenswert
nicht lesenswert
Di Pi schrieb:
> Neue Frage, gleiches Thema:
>
> Was tut die Zeile
>
  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?

Autor: Bingo (Gast)
Datum:

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

Autor: Di Pi (drpepper) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
  // Uhr für Timestep-Erzeugung
  TCCR2A = (1 << WGM22) | (1 << WGM21) | (1 << WGM20);
  TCCR2B = (1 << CS22) | (1 << CS21);
  TIMSK2 = (1 << TOIE2);
  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.

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

Bewertung
0 lesenswert
nicht lesenswert
Di Pi schrieb:
>
>   // Uhr für Timestep-Erzeugung
>   TCCR2A = (1 << WGM22) | (1 << WGM21) | (1 << WGM20);
>   TCCR2B = (1 << CS22) | (1 << CS21);
>   TIMSK2 = (1 << TOIE2);
>   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.

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)

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Di Pi schrieb:
>
>   // Uhr für Timestep-Erzeugung
>   TCCR2A = (1 << WGM22) | (1 << WGM21) | (1 << WGM20);
>   TCCR2B = (1 << CS22) | (1 << CS21);
>   TIMSK2 = (1 << TOIE2);
>   OCR2A = 250;
> 
>
> 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

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.