Forum: Mikrocontroller und Digitale Elektronik Bitweiser Vergleich funktioniert nicht


von Riebers (Gast)


Lesenswert?

Moin Elite,

ich habe eine char Variable und möchte jeweils prüfen, ob die einzelnen 
Bits '1' oder '0' sind. Dabei soll für eine bestimmte Dauer ein Ausgang 
auf High oder Low geschaltet werden. Das ganze läuft innerhalb der ISR 
ab. Das Problem welches ich habe ist, dass der char irgendwie falsch 
herum ausgelesen wird, obwohl das eigentlich nicht sein kann. Hier mal 
mein Code.
1
 
2
static unsigned char TMR0_Overflow = 0; // Zählt die Überlaufe von TMR0
3
static unsigned char index = 128;       // Dient zur Ausgabe von Data
4
static unsigned char Data = 0xAA;              // 10101010
5
static unsigned char T = 100;         // Mid-Bit Time T (Period Time = 2*T)
6
// Der Abschnitt aus der ISR
7
TMR0_Overflow++;
8
if(TMR0_Overflow==T){
9
  if(Data & index) {
10
     LATC=0x01;
11
  }else{
12
     LATC=0x00;
13
  }
14
15
  index /=2;
16
  TMR0_Overflow=0;
17
  if(index==0){
18
    index=128;
19
  }
20
}

Alles was vor diesem Abschnitt ausgeführt werden soll passt soweit, blos 
hier wird nicht wie erwartet die 10101010 sondern komischer weise 
010101010 ausgegeben :(
Das habe ich mit einem Oszilloskop gemessen. Hat jemand nen Schimmer 
warum das so ist?

Beste Grüße

Riebers

von Rainer U. (r-u)


Lesenswert?

Vielleicht hat die Leitung einen Pull up aktiviert, und/oder Du 
interpretierst den Anfang falsch? sende doch mal 01101111 und zum 
Vergleich 10010000 - wie sieht es da aus?

von Falk B. (falk)


Lesenswert?

@Riebers (Gast)

>ich habe eine char Variable und möchte jeweils prüfen, ob die einzelnen
>Bits '1' oder '0' sind.

Siehe Bitmanipulation.

>static unsigned char index = 128;       // Dient zur Ausgabe von Data

Bei sowas schreibt man das besser binär (wenn es der Compiler kann, denn 
das ist kein Standard-C) oder in Hexadezimal. Das ist besser lesbar.

>  index /=2;

Hier macht man besser eine Schiebeoperation, auch wenn die meisten 
Compiler das automatisch machen.

>Alles was vor diesem Abschnitt ausgeführt werden soll passt soweit, blos
>hier wird nicht wie erwartet die 10101010 sondern komischer weise
>010101010 ausgegeben :(

Das ist doch das Gleiche, wenn es aneinandergereiht ist. Den Unterschied 
sieht man nur, wenn es einmalig ausgegeben wird.

von Lutz (Gast)


Lesenswert?

Riebers schrieb:
> static unsigned char TMR0_Overflow = 0; // Zählt die Überlaufe von TMR0

Meckert der Compiler nicht, wenn du einen int einem char zuweisen 
willst?
=> '0' usw.

von Riebers (Gast)


Lesenswert?

@Falk Brunner
Ich habe auch Versucht das als Schieberegister zu machen, hat aber auch 
nicht geklappt. Ich gebe vorher eine definierte Bitfolge aus. Das ganze 
dient zum Daten versenden. Es beginnt mit einem Startbit, dann eine 
Bitfolge für die Synchronisation des Empängers, dann eine kurze Pause 
damit der Empänger sich Synchronisieren kann. Dann sollen Nutzdaten 
geschickt werden. Jedoch, wie schon erwähnt, ist der ganze Byte um eins 
nach rechts Verschoben. Habe es schon mit 11111111 versucht. Es kommt 
aber nur 7 mal die '1' an. Dafür vor dem Byte noch eine '0'.
Ich Versuche nochmal das als Register zu programmieren TT .

Danke soweit

Riebers

von Riebers (Gast)


Lesenswert?

Ich habe das mal für den Vergleich Bitweise geschoben. Ist aber immer 
noch der gleiche Fehler. Oder liegt das an was anderem?! Hier mal der 
Code falls jemanden was auffällt.
1
void TMR0_ISR(void)
2
{
3
    static unsigned char step_counter = 0;
4
    static unsigned int Data = 0xFF;        // 10101010
5
    static unsigned char T = 100;            // Mid-Bit Time T (Period Time = 2*T)
6
    static unsigned char StartBit = 0;
7
    static unsigned char TMR0_Overflow = 0;
8
    static unsigned int index = 0x80;
9
    // Clear the TMR0 interrupt flag
10
    INTCONbits.TMR0IF = 0;
11
12
    TMR0 = timer0ReloadVal;
13
    // Start of Data Transmission (5 ms high)
14
//    StartBit------------------------------------------------------------------
15
    switch(StartBit){
16
        case 0:
17
            LATC=0x01;
18
            TMR0_Overflow++;
19
            if(TMR0_Overflow==10) {
20
                LATC^=0x01;
21
                TMR0_Overflow=0;
22
                StartBit=1;
23
            }
24
            break;
25
        // Sync Bits T --- One low Impuls and one high Impuls ---> 2*T----------
26
        case 1:
27
            TMR0_Overflow++;
28
            if(TMR0_Overflow==T) {
29
                LATC^=0x01;
30
                TMR0_Overflow=0;
31
                step_counter+=1;
32
                if(step_counter==2){
33
                    step_counter=0;
34
                    StartBit=2;
35
                }
36
            }
37
            break;
38
        // Waittime ---> 2*T --- Receiver Calculates T--------------------------
39
        case 2:
40
            TMR0_Overflow++;
41
            if(TMR0_Overflow==2*T) {
42
                TMR0_Overflow=0;
43
                StartBit=3;
44
            }
45
            break;
46
        // Data Transmission----------------------------------------------------
47
        case 3:
48
            TMR0_Overflow++;
49
            if(TMR0_Overflow==T){
50
                if(Data & index) {
51
                    LATC=0x01;
52
                }else{
53
                    LATC=0x00;
54
                }
55
56
                index >>=1;
57
                TMR0_Overflow=0;
58
                if(index==0){
59
                    index=0x80;
60
                    StartBit=4;
61
                }
62
            }
63
64
            break;
65
        // Guard Time (2*T) -- Data Transmission complete-----------------------
66
        case 4:
67
            TMR0_Overflow++;
68
            LATC=0x00;
69
            if(TMR0_Overflow==2*T){
70
                StartBit=0;
71
                TMR0_Overflow=0;
72
            }
73
            break;
74
            
75
    }
76
}

@Lutz nee, kommt das Gleiche raus, egal ob ich int oder char nehme...
Die Waittime und Guardtime passen. Habe ich schon überprüft. Irgendwas 
passt bei der Datenübertragung nicht, ich komme aber nicht drauf.

Beste Grüße

von Reiner_Gast (Gast)


Lesenswert?

Riebers schrieb:
> case 0:
>             if(TMR0_Overflow==10) {
>                 LATC^=0x01;
>                 TMR0_Overflow=0;
>                 StartBit=1;
>             }
>         case 1:
>             if(TMR0_Overflow==T) {
>                 LATC^=0x01;
>                 TMR0_Overflow=0;
>                 step_counter+=1;
>             }

In den beiden Case Blöcken für die Werte 0 und 1 wird LATC auf 0 
gesetzt, wenn TMR0_Overflow groß genug geworden ist... Ist das evtl. für 
die führende "0" Verantwortlich?

von Joe F. (easylife)


Lesenswert?

Machs nicht zu kompliziert.

Riebers schrieb:
> Ich habe auch Versucht das als Schieberegister zu machen, hat aber auch
> nicht geklappt.

Sähe dann so aus:
1
static unsigned char TMR0_Overflow = 0; // Zählt die Überlaufe von TMR0
2
static unsigned char Data = 0xAA;              // 10101010
3
static unsigned char T = 100;         // Mid-Bit Time T (Period Time = 2*T)
4
5
// Der Abschnitt aus der ISR
6
TMR0_Overflow++;
7
if(TMR0_Overflow==T) {
8
  LATC = (Data & 0x80) ? 0x01 : 0x00;
9
  Data <<= 1;
10
  TMR0_Overflow=0;
11
}

Zu beachten ist halt, dass Data durch die Schiebeoperationen während der 
Ausgabe verändert wird und hinterher 0x00 ist.

: Bearbeitet durch User
von Theor (Gast)


Lesenswert?

Ich schlage vor, dass Du, falls Du ein Zwei-Kanal-Oszilloskop hast, 
während des ersten Bits der Daten eine 1 ausgibst. Dann siehst Du 
eindeutig die Zuordnung.

von Theor (Gast)


Lesenswert?

Theor schrieb:
Sorry. Sollte besser heissen:

Ich schlage vor, dass Du, falls Du ein Zwei-Kanal-Oszilloskop hast,
während des ersten Bits der Daten auf einem zusätzlichen Portpin eine 
1 ausgibst. Dann siehst Du eindeutig die zeitliche Zuordnung.

von Apollo M. (Firma: @home) (majortom)


Lesenswert?

hallo,
das gelaber hier erscheint mir nutzlos, wenn der to es nicht schaft den 
uc zu benennen und die port config transparent zu machen. weil, einige 
uc kennen port invertierung oder toggle mode oder ...


mt

von Rolf M. (rmagnus)


Lesenswert?

Falk B. schrieb:
>>static unsigned char index = 128;       // Dient zur Ausgabe von Data
>
> Bei sowas schreibt man das besser binär (wenn es der Compiler kann, denn
> das ist kein Standard-C) oder in Hexadezimal. Das ist besser lesbar.

Noch besser finde ich:
1
static unsigned char index = 1 << 7;

>>  index /=2;
>
> Hier macht man besser eine Schiebeoperation, auch wenn die meisten
> Compiler das automatisch machen.

Was er draus macht, sollte man dem Compiler überlassen. Wesentlich ist, 
welche Aktion man beabsichtigt. Aus Gründen besserer Lesbarkeit sollte 
man die dann auch hinschreiben. Also ist der Inhalt der Variablen eher 
eine Zahl, die ich durch zwei dividieren will, oder eine Reihe von Bits, 
die ich um ein Bit nach rechts schieben will? Hier ist es ganz 
offensichtlich letzteres.

von easy (Gast)


Lesenswert?

Rolf M. schrieb:
> Noch besser finde ich:static unsigned char index = 1 << 7;

Noch besser finde ich
1
static unsigned char index = BIT_7;

von Riebers (Gast)


Lesenswert?

nochmal für mt.
Nutze einen PICLF1509 und den RC0 Port als Ausgang. Hier initialisiere 
ich die Pins.
1
void PIN_MANAGER_Initialize(void)
2
{
3
    /**
4
    LATx registers
5
    */   
6
    LATA = 0x00;    
7
    LATB = 0x00;    
8
    LATC = 0x00;    
9
10
    /**
11
    TRISx registers
12
    */    
13
    TRISA = 0x3F;
14
    TRISB = 0xF0;
15
    TRISC = 0xFE;
16
17
    /**
18
    ANSELx registers
19
    */   
20
    ANSELC = 0xCF;
21
    ANSELB = 0x30;
22
    ANSELA = 0x17;
23
24
    /**
25
    WPUx registers
26
    */ 
27
    WPUB = 0x00;
28
    WPUA = 0x00;
29
    OPTION_REGbits.nWPUEN = 1;
30
31
    
32
    /**
33
    APFCONx registers
34
    */
35
    APFCON = 0x00;
36
37
38
   
39
    
40
}
Hier nochmal die PIC Config.
1
// CONFIG1
2
#pragma config FOSC = INTOSC    // Oscillator Selection Bits->INTOSC oscillator: I/O function on CLKIN pin
3
#pragma config WDTE = OFF    // Watchdog Timer Enable->WDT disabled
4
#pragma config PWRTE = OFF    // Power-up Timer Enable->PWRT disabled
5
#pragma config MCLRE = ON    // MCLR Pin Function Select->MCLR/VPP pin function is MCLR
6
#pragma config CP = OFF    // Flash Program Memory Code Protection->Program memory code protection is disabled
7
#pragma config BOREN = ON    // Brown-out Reset Enable->Brown-out Reset enabled
8
#pragma config CLKOUTEN = OFF    // Clock Out Enable->CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin
9
#pragma config IESO = ON    // Internal/External Switchover Mode->Internal/External Switchover Mode is enabled
10
#pragma config FCMEN = ON    // Fail-Safe Clock Monitor Enable->Fail-Safe Clock Monitor is enabled
11
12
// CONFIG2
13
#pragma config WRT = OFF    // Flash Memory Self-Write Protection->Write protection off
14
#pragma config STVREN = ON    // Stack Overflow/Underflow Reset Enable->Stack Overflow or Underflow will cause a Reset
15
#pragma config BORV = LO    // Brown-out Reset Voltage Selection->Brown-out Reset Voltage (Vbor), low trip point selected.
16
#pragma config LPBOR = OFF    // Low-Power Brown Out Reset->Low-Power BOR is disabled
17
#pragma config LVP = OFF    // Low-Voltage Programming Enable->High-voltage on MCLR/VPP must be used for programming

Beste Grüße

Riebers

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.