mikrocontroller.net

Forum: PC Hard- und Software Probleme beim einlesen eines Datenstroms über Interrupts


Autor: Johannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo, ich wende mich mit einem mir unerklärlichem Phänomen an dieses 
Forum und hoffe irgendwer kann mir helfen.

Ich habe bei einem Projekt die Aufgabe bekommen einen RDS-Datenstrom mit 
einem ATmega8 einzulesen und auszuwerten. Das RDS-Signal liegt dabei 
seriell an (Data/Clk). Das eigentliche einlesen erfolgt über eine 
Interrupt Routine.
volatile uint16_t data;

GIMSK |=(1<<INT0);
MCUCR |= _BV(ISC01) | _BV(ISC00);          // INT0 interrupt on rising edge
PORTD |= ( 1 << PD2 ); 

DDRD = 0x00;
PORTD |= ( 1 << PD0 );                     // Port PD0 = Datenleitung

ISR(INT0_vect) 
{
  /* read RDS-data*/
  data=data << 1;
  if( bit_is_set(PIND,PD0) ) data|=0x01;
}
 
Ein Block der RDS Übertragung ist 26 Bit lang. Aus diesen 26 Bit wird 
mit der Funktion Calculate_Syndrom das Syndrom berechnet.
/********************************************************************************
* int Calculate_Syndrom(unsigned long Data)
* Funktion:   Syndrom berechnen
* Parameter:   32Bit Datenwort
* zur�ck:      10Bit Syndrom
*********************************************************************************/
unsigned int Calculate_Syndrom(unsigned long Data)
{
  unsigned int MSB16, LSB16;

  MSB16 = (Data>>16) & 0x03FF;      //16 Bit rechts schieben und ausmaskieren
  LSB16 = Data;

  MSB16 &= 0x3FFF;       // nur 26 Bit verwenden
  if((LSB16 & 0x0001) == 0x0001)    // Multiplikation des empfangen Wortes mit
    MSB16 ^= 0x031B;          // der Kontrollmatrix
  if((LSB16 & 0x0002) == 0x0002)
    MSB16 ^= 0x038F;
  if((LSB16 & 0x0004) == 0x0004)
    MSB16 ^= 0x02A7;
  if((LSB16 & 0x0008) == 0x0008)
    MSB16 ^= 0x00F7;
  if((LSB16 & 0x0010) == 0x0010)
    MSB16 ^= 0x01EE;
  if((LSB16 & 0x0020) == 0x0020)
    MSB16 ^= 0x03DC;
  if((LSB16 & 0x0040) == 0x0040)
    MSB16 ^= 0x0201;
  if((LSB16 & 0x0080) == 0x0080)
    MSB16 ^= 0x01BB;
  if((LSB16 & 0x0100) == 0x0100)
    MSB16 ^= 0x0376;
  if((LSB16 & 0x0200) == 0x0200)
    MSB16 ^= 0x0355;
  if((LSB16 & 0x0400) == 0x0400)
    MSB16 ^= 0x0313;
  if((LSB16 & 0x0800) == 0x0800)
    MSB16 ^= 0x039F;
  if((LSB16 & 0x1000) == 0x1000)
    MSB16 ^= 0x0287;
  if((LSB16 & 0x2000) == 0x2000)
    MSB16 ^= 0x00B7;
  if((LSB16 & 0x4000) == 0x4000)
    MSB16 ^= 0x016E;
  if((LSB16 & 0x8000) == 0x8000)
    MSB16 ^= 0x02DC;

   // MSB16 = 0x00FF;
  return MSB16;
}

 

Jetzt zu meinem Problem:
Bei folgendem Datenstrom sollte das Syndrom = 0 sein: 
11111111111111110011001101  [0x03FFFCCD]
Wenn ich jetzt diesen Datenstrom an den Mikrocontroller anlege und über 
die Interrupt-Routine einlese so kommt leider nicht 0 heraus. Wobei die 
Routine einliest und die eingelesenen Bits richtig sind. Das Merkwürdige 
ist jedoch, wenn ich den Wert direkt an Calculate_Syndrom() übergebe ist 
das Ergebnis korrekt. Auch wenn ich die ISR-Routine simmuliere in dem 
ich 26mal linksschiebe und die letzte Stelle entsprechend setzte kommt 
auch 0 heraus.
Ich vermute das irgendwie die 26 Bit nicht richtig eingelesen werden, 
denn meine Funktion zum Syndrom berechnen funktioniert ja.

Wenn jemand eine Idee hat wäre das super, ich bin mit meinem Latein am 
Ende.
mfG Johannes

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
MSB16 &= 0x3FFF;       // nur 26 Bit verwenden


3FFF sind 14 Bit

Autor: Johannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OK. Ich hab die Funktion selber "geklaut" und die Kommentare sind dem 
entsprechend auch nicht von mir. Dort liegt aber nicht das Problem. denn 
wie oben schon beschrieben ergiebt der folgende Aufruf das erwünschte 
Ergebnis 0.
unsigned long a;
unsigned int b;

a = 0x03fffccd;  //[00000011111111111111110011001101] 

b = Calculate_Syndrom(a);

mfG Johannes

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
volatile uint16_t data;

...

ISR(INT0_vect) 
{
  /* read RDS-data*/
  data=data << 1;
  if( bit_is_set(PIND,PD0) ) data|=0x01;
}

Wie sollen denn die 26 Bit in ein uint16_t passen?

Autor: Johannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also, war ein Fehler beim kopieren des Codes ins Forum. Es ist natürlich 
ein uint32_t. Jetzt noch mal zum eigentlichen Problem. Ich habe folgende 
Feststellung gemacht:

Bis zum 25. Bit erfolgt eine richtige Berechnung des Syndroms. Erst beim 
26. Bit ist die Berechnung falsch. Ich habe mir auch andere Programme 
zum verarbeiten von RDS Daten angesehen, diese machen im Prinzip genau 
das gleiche wie ich. Ich kann absolut keinen Fehler mehr feststellen 
bzw. weiß nicht was da noch in Frage käme. Speicherprobleme eventuell.

Bin auf jeden Fall für jeden Tipp dankbar.

Johannes

Autor: Johannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oh, das war etwas mißverständlich geschrieben. Ich meinte damit bis zum 
25. eingegebenen Bit, also [1111111111111111001100110] erfolgt eine 
richtige Berechnung.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und meinst du nicht, dass dann vielleicht die Codezeilen, die darüber 
entscheiden, wann 26 Bits eingelesen wurden, von Interesse sein könnten?

Autor: Johannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oh sorry ich bin grad ein bisschen durcheinander, weshalb ich die 
Funktion des Programms nicht richtig rübergebracht habe. In der main 
Funktion wird in einer Endlosschleife die Syndromberechnung für data 
durchgeführt und das Ergebnis auf einem Display ausgegeben. Das heißt 
wenn noch kein Interrupt ausgeführt wurde wird immer für data = 
0x00000000 das Syndrom berechnet, wobei nur die ersten 26 Stellen von 
rechts berücksichtigt werden. erfolgt ein Interrupt (später ausgelöst 
von der Clock Leitung) so wird das eingelesene Bit, also 0 oder 1 von 
rechts eingeschoben und bis zum nächsten Interrupt wird aus dem neuen 
data das Syndrom berechnet. Gebe ich jetzt die Werte, die data bei den 
26 mal schieben jeweils erhält, in Calculate Syndrom so ergibt sich nach 
dem 26. mal schieben als syndrom 0.
Gebe ich den Datenstrom jetzt über die ISR ein (mit zwei entprellten 
Tastern, einmal Clock und einmal Data) so ist das berechnete Syndrom bis 
zum 25. eingegbenen Bit richtig.

Ich hoffe das schafft etwas Klarheit. Johannes

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Johannes wrote:

> Gebe ich den Datenstrom jetzt über die ISR ein (mit zwei entprellten
> Tastern, einmal Clock und einmal Data) so ist das berechnete Syndrom bis
> zum 25. eingegbenen Bit richtig.

Und wo ist der Sourcecode dazu? Wie soll irgend jemand in unbekanntem 
Code einen Fehler finden?

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.