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


von Johannes (Gast)


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.
1
volatile uint16_t data;
2
3
GIMSK |=(1<<INT0);
4
MCUCR |= _BV(ISC01) | _BV(ISC00);          // INT0 interrupt on rising edge
5
PORTD |= ( 1 << PD2 ); 
6
7
DDRD = 0x00;
8
PORTD |= ( 1 << PD0 );                     // Port PD0 = Datenleitung
9
10
ISR(INT0_vect) 
11
{
12
  /* read RDS-data*/
13
  data=data << 1;
14
  if( bit_is_set(PIND,PD0) ) data|=0x01;
15
}
Ein Block der RDS Übertragung ist 26 Bit lang. Aus diesen 26 Bit wird 
mit der Funktion Calculate_Syndrom das Syndrom berechnet.
1
/********************************************************************************
2
* int Calculate_Syndrom(unsigned long Data)
3
* Funktion:   Syndrom berechnen
4
* Parameter:   32Bit Datenwort
5
* zur�ck:      10Bit Syndrom
6
*********************************************************************************/
7
unsigned int Calculate_Syndrom(unsigned long Data)
8
{
9
  unsigned int MSB16, LSB16;
10
11
  MSB16 = (Data>>16) & 0x03FF;      //16 Bit rechts schieben und ausmaskieren
12
  LSB16 = Data;
13
14
  MSB16 &= 0x3FFF;       // nur 26 Bit verwenden
15
  if((LSB16 & 0x0001) == 0x0001)    // Multiplikation des empfangen Wortes mit
16
    MSB16 ^= 0x031B;          // der Kontrollmatrix
17
  if((LSB16 & 0x0002) == 0x0002)
18
    MSB16 ^= 0x038F;
19
  if((LSB16 & 0x0004) == 0x0004)
20
    MSB16 ^= 0x02A7;
21
  if((LSB16 & 0x0008) == 0x0008)
22
    MSB16 ^= 0x00F7;
23
  if((LSB16 & 0x0010) == 0x0010)
24
    MSB16 ^= 0x01EE;
25
  if((LSB16 & 0x0020) == 0x0020)
26
    MSB16 ^= 0x03DC;
27
  if((LSB16 & 0x0040) == 0x0040)
28
    MSB16 ^= 0x0201;
29
  if((LSB16 & 0x0080) == 0x0080)
30
    MSB16 ^= 0x01BB;
31
  if((LSB16 & 0x0100) == 0x0100)
32
    MSB16 ^= 0x0376;
33
  if((LSB16 & 0x0200) == 0x0200)
34
    MSB16 ^= 0x0355;
35
  if((LSB16 & 0x0400) == 0x0400)
36
    MSB16 ^= 0x0313;
37
  if((LSB16 & 0x0800) == 0x0800)
38
    MSB16 ^= 0x039F;
39
  if((LSB16 & 0x1000) == 0x1000)
40
    MSB16 ^= 0x0287;
41
  if((LSB16 & 0x2000) == 0x2000)
42
    MSB16 ^= 0x00B7;
43
  if((LSB16 & 0x4000) == 0x4000)
44
    MSB16 ^= 0x016E;
45
  if((LSB16 & 0x8000) == 0x8000)
46
    MSB16 ^= 0x02DC;
47
48
   // MSB16 = 0x00FF;
49
  return MSB16;
50
}

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

von Martin (Gast)


Lesenswert?

MSB16 &= 0x3FFF;       // nur 26 Bit verwenden


3FFF sind 14 Bit

von Johannes (Gast)


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.
1
unsigned long a;
2
unsigned int b;
3
4
a = 0x03fffccd;  //[00000011111111111111110011001101] 
5
6
b = Calculate_Syndrom(a);

mfG Johannes

von Stefan E. (sternst)


Lesenswert?

1
volatile uint16_t data;
2
3
...
4
5
ISR(INT0_vect) 
6
{
7
  /* read RDS-data*/
8
  data=data << 1;
9
  if( bit_is_set(PIND,PD0) ) data|=0x01;
10
}

Wie sollen denn die 26 Bit in ein uint16_t passen?

von Johannes (Gast)


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

von Johannes (Gast)


Lesenswert?

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

von Stefan E. (sternst)


Lesenswert?

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

von Johannes (Gast)


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

von Stefan E. (sternst)


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?

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.