Forum: Mikrocontroller und Digitale Elektronik MSP430 Timing: Was laeuft hier falsch?


von Markus (Gast)


Lesenswert?

Hallo,

Fuer Testzwecke moechte ich einfach einen String von 1 und 0 auf einem 
I/O Port meines MSP430 ausgeben. Jedes Bit soll 10us lang sein.

Zuerst setze ich die clock frequency auf 16 MHz:
1
    DIRECT_SET_BIT(CSCTL0_H, CSKEY >> 8);
2
    DIRECT_SET_BIT(CSCTL1, DCOFSEL_4 | DCORSEL);
3
    DIRECT_SET_BIT(CSCTL2, SELA__LFXTCLK | SELS__DCOCLK | SELM__DCOCLK);
4
    DIRECT_SET_BIT(CSCTL3, DIVA__1 | DIVS__1 | DIVM__1); 
5
    CLR_BIT(CSCTL6, MODCLKREQEN | SMCLKREQEN | MCLKREQEN);
6
    SET_BIT(CSCTL6, ACLKREQEN);

Danach setze ich meinen I/O port auf Ausgang und definiere statisch 
bits:
1
#define BIT_0 CLR_BIT(PIN_TX_OUT, PIN_TX);\
2
        NOPx40;\
3
        NOPx40;\
4
        NOPx40;\
5
        NOPx35;
6
7
#define BIT_1 SET_BIT(PIN_TX_OUT, PIN_TX);\
8
        NOPx40;\
9
        NOPx40;\
10
        NOPx40;\
11
        NOPx35;
12
13
SET_BIT(PIN_TX_DIR, PIN_TX);

Die NOP Makros sind einfach rekursiv definiert mit:
1
#define NOP __asm("NOP")
2
#define NOPx2\
3
        NOP;\
4
        NOP;
5
#define NOPx4\
6
        NOPx2;\
7
        NOPx2;
8
#define NOPx6\
9
        NOPx5;\
10
        NOP;
11
// etc.

Schliesslich gebe ich 16x Einser aus mit 15 Nuller dazwischen:
1
BIT_1;BIT_0;BIT_1;BIT_0;BIT_1;BIT_0;BIT_1;BIT_0;
2
BIT_1;BIT_0;BIT_1;BIT_0;BIT_1;BIT_0;BIT_1;BIT_0;
3
BIT_1;BIT_0;BIT_1;BIT_0;BIT_1;BIT_0;BIT_1;BIT_0;
4
BIT_1;BIT_0;BIT_1;BIT_0;BIT_1;BIT_0;BIT_1;BIT_0;

Das uebersetzt 1:1 in Assembler. Der Portzugriff BIS.B<->#-128, &PAOUT_H 
und AND.B<->#127, &PAOUT_H hat lt. Handbuch 5 Cycles. 10us mit 16MHz 
sind 160 Cycles. Deswegen habe ich 3x40 und 1x35 NOPs hinzugefuegt. Denn 
ein NOP sollte einen Cycle benoetigen oder? Also muessten die Bits nach 
meinem Verstaendnis mit exakt 10us Laenge ausgegeben werden.

Laut Messungen ist der Block vom ersten zum letzten 1 (also 31 bits) 
aber 388.15us lang, d.h. pro bit 12.51us.

Wo mache ich den Fehler?

von Roland E. (roland0815)


Lesenswert?

Lies nach:
Was sind Makros.
Schaue dir mal deinen Assembler im Debug an.

Sprungoperationen vergessen?

von Peter D. (peda)


Lesenswert?

Diese ganze NOPperei kannst Du Dir sparen mit dem __delay_cycles() 
Macro.

Nimm besser einen Timer. Dann hast Du zwar einen Jitter, aber keine 
Fehlerakkumulation.

von Markus (Gast)


Lesenswert?

Hi Roland,

> Lies nach:
> Was sind Makros.
> Schaue dir mal deinen Assembler im Debug an.
> Sprungoperationen vergessen?

Done. Wie geschrieben "Das uebersetzt 1:1 in Assembler." --> gecheckt. 
Es gibt keine Sprungoperationen. etc.

> Diese ganze NOPperei kannst Du Dir sparen mit dem __delay_cycles()
> Macro.

Super, das ist echt besser.
Allerdings loest es mein Problem nicht. Mit trial and error habe ich nun 
gefunden dass ich __delay_cycles(150) nehmen muss. Das sollten 
150/16e6=9.375us sein. Fuer 10us fehlen also 625ns, also 10 Cycles.

Hier nochmal als Referenz der Assembler code:
1
 215                            ; Begin 150 cycle delay
2
 216 0104 0D14                  PUSHM.A #1,r13
3
 217 0106 3D40 2E00             MOV.W   #46, r13
4
 218 010a 1D83          1:      SUB.W   #1, r13
5
 219 010c 0020                  JNE     1b
6
 220 010e 0D16                  POPM.A  #1,r13
7
 221 0110 003C                  JMP     .+2
8
 222                            ; End 150 cycle delay
9
 223                            .loc 1 110 20
10
 224                            .loc 1 110 21
11
 225 0112 F2D0 80FF             BIS.B   #-128, &PAOUT_H
12
 225      0000
13
 226                            .loc 1 110 21
14
 227                            ; Begin 150 cycle delay
15
 228 0118 0D14                  PUSHM.A #1,r13
16
 229 011a 3D40 2E00             MOV.W   #46, r13
17
 230 011e 1D83          1:      SUB.W   #1, r13
18
 231 0120 0020                  JNE     1b
19
 232 0122 0D16                  POPM.A  #1,r13
20
 233 0124 003C                  JMP     .+2
21
 234                            ; End 150 cycle delay
22
 235                            .loc 1 110 26
23
 236                            .loc 1 110 27
24
 237 0126 F2F0 7F00             AND.B   #127, &PAOUT_H
25
 237      0000
26
 238                            .loc 1 110 27

Kann es sein, dass "BIS.B   #-128, &PAOUT_H" und "AND.B   #127, 
&PAOUT_H" 10 Cycles statt 5 benoetigen?? Falls sein, woher koennten die 
fehlenden 5 Cycles kommen?

> Nimm besser einen Timer. Dann hast Du zwar einen Jitter, aber keine
> Fehlerakkumulation.

Gut dass du das sagst, denn genau den moechte ich debuggen!! ;-)

Derzeit verwende ich den Timer, habe aber das Problem dass irgendwas mit 
dem Timing nicht stimmt. An der (nicht-MSP) Empfangsseite sample ich das 
Signal 50x und mache einen Matched Filter und downsample. Allerdings 
sind die Bitzeiten nicht deterministisch. Das ist mein eigentliches 
Problem und ich werde dazu wahrscheinlich einen neuen Thread starten 
wenn ich mehr dazu weiss.

Fuer jetzt moechte ich eigentlich mit "first principles" so einfach wie 
moeglich das richtige Timing hinbekommen

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.