Forum: Mikrocontroller und Digitale Elektronik Array aus Unions - geht das?


von tt (Gast)


Lesenswert?

Kann ich in C ein Array von Unions anlegen und wie greife ich darauf zu?

Ich hab es so probiert:

typedef union
{
  uint16_t i16;
  struct
  {
    uint8_t l;
    uint8_t h;
  }i8;
} un_i16;


volatile un_i16 ust1_data[30];

folgender Zugriffsveruch klappt nicht:

  SSP1BUF=ust1_data.i8.h[3];

Was tun?

von déjà vu (Gast)


Lesenswert?

(ust1_data[3]).h ?

von déjà vu (Gast)


Lesenswert?

>(ust1_data[3]).h ?

geht mit
1
typedef union
2
{
3
  uint16_t i16;
4
  struct
5
  {
6
    uint8_t l;
7
    uint8_t h;
8
  };
9
} un_i16;

ansonsten halt (ust1_data[3]).i8.h ...

von tt (Gast)


Lesenswert?

Danke, guter Ansatz

ust1_data[3].i8.h

bringt keine Fehlermeldung mehr.

von Peter (Gast)


Lesenswert?

die klammern brauchst du nicht:
1
SSP1BUF = ust1_data[3].i8.h;
übrigens ist das keine gute idee, auf die beiden bytes eine 16-bit 
wertes zuzugreifen.
besser:
1
uint16_t x = 0x1234;
2
uint8_t lobyte = x & 0xff; // 0x34
3
uint8_t hibyte = x >> 8; // 0x12

von Punktrichter (Gast)


Lesenswert?

Doch, seine Art, auf beide Byte zuzugreifen kostet keine Rechenzeit und 
verbraucht minimal Speicherplatz.
Das kann man bei Deiner (insbesonder die Highbytevariante) nicht 
behaupten.

von Ralph (Gast)


Lesenswert?

probier es mal so

 SSP1BUF=ust1_data[3].i8.h;

von Simon K. (simon) Benutzerseite


Lesenswert?

Punktrichter wrote:
> Doch, seine Art, auf beide Byte zuzugreifen kostet keine Rechenzeit und
> verbraucht minimal Speicherplatz.
> Das kann man bei Deiner (insbesonder die Highbytevariante) nicht
> behaupten.

Nein, weil das Ergebnis seiner Art nirgendwo festgelegt ist und 
Plattform und Compiler abhängig ist.

Peter's Art verbraucht "normal" optimiert vermutlich genausolange - aber 
man hat kein Problem mehr mit Compilerabhängigem Gedönsel

von déjà vu (Gast)


Lesenswert?

1
#include <stdint.h>
2
#include <avr/io.h>
3
4
typedef union
5
{
6
  uint16_t i16;
7
  struct
8
  {
9
    uint8_t l;
10
    uint8_t h;
11
  };
12
} un_i16;
13
14
volatile uint16_t x ;
15
volatile un_i16 y;
16
17
int main(void)
18
{
19
    x = 0x1234;
20
    y.i16 = 0x5678;
21
22
    DDRB = x & 0xff;;
23
    PORTB = x >> 8;;
24
    DDRC = y.l;
25
    PORTC = y.h;
26
}

ergibt:
1
0000005c <main>:
2
volatile uint16_t x ;
3
volatile un_i16 y;
4
5
int main(void)
6
{
7
  5c:   cf e5           ldi     r28, 0x5F       ; 95
8
  5e:   d4 e0           ldi     r29, 0x04       ; 4
9
  60:   de bf           out     0x3e, r29       ; 62
10
  62:   cd bf           out     0x3d, r28       ; 61
11
    x = 0x1234;
12
  64:   84 e3           ldi     r24, 0x34       ; 52
13
  66:   92 e1           ldi     r25, 0x12       ; 18
14
  68:   90 93 61 00     sts     0x0061, r25
15
  6c:   80 93 60 00     sts     0x0060, r24
16
    y.i16 = 0x5678;
17
  70:   88 e7           ldi     r24, 0x78       ; 120
18
  72:   96 e5           ldi     r25, 0x56       ; 86
19
  74:   90 93 63 00     sts     0x0063, r25
20
  78:   80 93 62 00     sts     0x0062, r24
21
22
    DDRB = x & 0xff;;
23
  7c:   80 91 60 00     lds     r24, 0x0060
24
  80:   90 91 61 00     lds     r25, 0x0061
25
  84:   87 bb           out     0x17, r24       ; 23
26
    PORTB = x >> 8;;
27
  86:   80 91 60 00     lds     r24, 0x0060
28
  8a:   90 91 61 00     lds     r25, 0x0061
29
  8e:   89 2f           mov     r24, r25
30
  90:   99 27           eor     r25, r25
31
  92:   88 bb           out     0x18, r24       ; 24
32
    DDRC = y.l;
33
  94:   80 91 62 00     lds     r24, 0x0062
34
  98:   84 bb           out     0x14, r24       ; 20
35
    PORTC = y.h;
36
  9a:   80 91 63 00     lds     r24, 0x0063
37
  9e:   85 bb           out     0x15, r24       ; 21
38
}
39
  a0:   80 e0           ldi     r24, 0x00       ; 0
40
  a2:   90 e0           ldi     r25, 0x00       ; 0
41
  a4:   00 c0           rjmp    .+0             ; 0xa6 <_exit>
42
43
000000a6 <_exit>:
44
  a6:   ff cf           rjmp    .-2             ; 0xa6 <_exit>

daran sieht man ganz deutlich, dass die union-variante vorteile hat.

von déjà vu (Gast)


Lesenswert?

hmm, wer hat denn die doppelten ;; da reingemogelt? aendert aber eh 
nichts...

von Peter (Gast)


Lesenswert?

> daran sieht man ganz deutlich, dass die union-variante vorteile hat.
nein, daran sieht man, dass dein compiler nichts taugt.

von déjà vu (Gast)


Lesenswert?

achja, kompiliert mit avr-gcc, optimierung -Os
1
avr-gcc -c -mmcu=atmega8 -I. -gstabs -DF_CPU=8000000UL  -Os -Wall -Wstrict-prototypes -std=gnu99  main.c -o main.o 
2
avr-gcc -mmcu=atmega8 -I. -gstabs -DF_CPU=8000000UL  -Os -Wall -Wstrict-prototypes -std=gnu99  main.o   --output main.elf     -lm
3
avr-objcopy -O ihex -R .eeprom main.elf main.hex

von déjà vu (Gast)


Lesenswert?

>nein, daran sieht man, dass dein compiler nichts taugt.
dann kompilier mein beispiel bitte mal mit deinem kompiler und poste das 
asm-listing

von Peter (Gast)


Lesenswert?

> dann kompilier mein beispiel bitte mal mit deinem kompiler und poste das
> asm-listing
ich zeig dir mal'n output vom IAR für ARM:
1
typedef unsigned char uint8_t;
2
typedef unsigned short uint16_t;
3
4
typedef union
5
{
6
  uint16_t i16;
7
  struct
8
  {
9
    uint8_t l;
10
    uint8_t h;
11
  }i8;
12
} un_i16;
13
14
int main()
15
{
16
  un_i16 x;
17
  uint16_t y;
18
  volatile uint8_t a,b,c,d; 
19
20
  x.i16 = 0x1234;
21
  y = 0x1234;
22
23
  a = x.i8.l;
24
  b = x.i8.h;
25
26
  c = y & 0xff;
27
  d = y >> 8;
28
}
ergibt:
1
      1          #include <stdlib.h>
2
      2          #include <string.h>
3
      3          
4
      4          typedef unsigned char uint8_t;
5
      5          typedef unsigned short uint16_t;
6
      6          
7
      7          typedef union
8
      8          {
9
      9            uint16_t i16;
10
     10            struct
11
     11            {
12
     12              uint8_t l;
13
     13              uint8_t h;
14
     14            }i8;
15
     15          } un_i16;
16
     16          
17
18
   \                                 In segment CODE, align 4, keep-with-next
19
     17          int main()
20
     18          {
21
   \                     main:
22
   \   00000000   04D04DE2           SUB      SP,SP,#+4
23
     19            un_i16 x;
24
     20            uint16_t y;
25
     21            volatile uint8_t a,b,c,d; 
26
     22          
27
     23            x.i16 = 0x1234;
28
   \   00000004   3410A0E3           MOV      R1,#+52
29
   \   00000008   481D81E3           ORR      R1,R1,#0x1200
30
   \   0000000C   B210CDE1           STRH     R1,[SP, #+2]
31
     24            y = 0x1234;
32
   \   00000010   3400A0E3           MOV      R0,#+52
33
   \   00000014   480D80E3           ORR      R0,R0,#0x1200
34
     25          
35
     26            a = x.i8.l;
36
   \   00000018   0220DDE5           LDRB     R2,[SP, #+2]
37
   \   0000001C   0020CDE5           STRB     R2,[SP, #+0]
38
     27            b = x.i8.h;
39
   \   00000020   0320DDE5           LDRB     R2,[SP, #+3]
40
   \   00000024   0020CDE5           STRB     R2,[SP, #+0]
41
     28          
42
     29            c = y & 0xff;
43
   \   00000028   0000CDE5           STRB     R0,[SP, #+0]
44
     30            d = y >> 8;
45
   \   0000002C   2004B0E1           LSRS     R0,R0,#+8
46
   \   00000030   0000CDE5           STRB     R0,[SP, #+0]
47
     31          }
48
   \   00000034   0000A0E3           MOV      R0,#+0
49
   \   00000038   04D08DE2           ADD      SP,SP,#+4        ;; stack cleaning
50
   \   0000003C   1EFF2FE1           BX       LR               ;; return
51
52
   Maximum stack usage in bytes:
53
54
     Function CSTACK
55
     -------- ------
56
     main         4
57
58
59
   Segment part sizes:
60
61
     Function/Label Bytes
62
     -------------- -----
63
     main             64
64
      Others           4
65
66
 
67
 68 bytes in segment CODE
68
 
69
 64 bytes of CODE memory (+ 4 bytes shared)
70
71
Errors: none
72
Warnings: none

von déjà vu (Gast)


Lesenswert?

>ich zeig dir mal'n output vom IAR für ARM:
aendert sich was, wenn x und y auch als volatile deklariert werden?

hier mal dein beispiel mit avr-gcc:
1
int main(void)
2
{
3
  5c:   cb e5           ldi     r28, 0x5B       ; 91
4
  5e:   d4 e0           ldi     r29, 0x04       ; 4
5
  60:   de bf           out     0x3e, r29       ; 62
6
  62:   cd bf           out     0x3d, r28       ; 61
7
  un_i16 x;
8
  uint16_t y;
9
  volatile uint8_t a,b,c,d;
10
11
  x.i16 = 0x1234;
12
  64:   84 e3           ldi     r24, 0x34       ; 52
13
  66:   92 e1           ldi     r25, 0x12       ; 18
14
  y = 0x1234;
15
16
  a = x.i8.l;
17
  68:   89 83           std     Y+1, r24        ; 0x01
18
  b = x.i8.h;
19
  6a:   9a 83           std     Y+2, r25        ; 0x02
20
21
  c = y & 0xff;
22
  6c:   8b 83           std     Y+3, r24        ; 0x03
23
  d = y >> 8;
24
  6e:   82 e1           ldi     r24, 0x12       ; 18
25
  70:   90 e0           ldi     r25, 0x00       ; 0
26
  72:   8c 83           std     Y+4, r24        ; 0x04
27
}

von déjà vu (Gast)


Lesenswert?

vorweg schonmal das ergebnis von avr-gcc mit x und y als volatile:
1
int main(void)
2
{
3
  5c:   c7 e5           ldi     r28, 0x57       ; 87
4
  5e:   d4 e0           ldi     r29, 0x04       ; 4
5
  60:   de bf           out     0x3e, r29       ; 62
6
  62:   cd bf           out     0x3d, r28       ; 61
7
  volatile un_i16 x;
8
  volatile uint16_t y;
9
  volatile uint8_t a,b,c,d;
10
11
  x.i16 = 0x1234;
12
  64:   84 e3           ldi     r24, 0x34       ; 52
13
  66:   92 e1           ldi     r25, 0x12       ; 18
14
  68:   9a 83           std     Y+2, r25        ; 0x02
15
  6a:   89 83           std     Y+1, r24        ; 0x01
16
  y = 0x1234;
17
  6c:   9c 83           std     Y+4, r25        ; 0x04
18
  6e:   8b 83           std     Y+3, r24        ; 0x03
19
20
  a = x.i8.l;
21
  70:   89 81           ldd     r24, Y+1        ; 0x01
22
  72:   8d 83           std     Y+5, r24        ; 0x05
23
  b = x.i8.h;
24
  74:   8a 81           ldd     r24, Y+2        ; 0x02
25
  76:   8e 83           std     Y+6, r24        ; 0x06
26
27
  c = y & 0xff;
28
  78:   8b 81           ldd     r24, Y+3        ; 0x03
29
  7a:   9c 81           ldd     r25, Y+4        ; 0x04
30
  7c:   8f 83           std     Y+7, r24        ; 0x07
31
  d = y >> 8;
32
  7e:   8b 81           ldd     r24, Y+3        ; 0x03
33
  80:   9c 81           ldd     r25, Y+4        ; 0x04
34
  82:   89 2f           mov     r24, r25
35
  84:   99 27           eor     r25, r25
36
  86:   88 87           std     Y+8, r24        ; 0x08
37
}

von Peter (Gast)


Lesenswert?

> aendert sich was, wenn x und y auch als volatile deklariert werden?
ja, es kommt jedesmal eine instruction dazu, weil der zugriff auf die 
variablen ja jedesmal neu erfolgen muss.

btw, am besten siehts aus, wenn man die variablen nicht in der funktion 
hat:
1
     26            a = x.i8.l;
2
   \   00000014   0010D0E5           LDRB     R1,[R0, #+0]
3
   \   00000018   0410C0E5           STRB     R1,[R0, #+4]
4
     27            b = x.i8.h;
5
   \   0000001C   0110D0E5           LDRB     R1,[R0, #+1]
6
   \   00000020   0510C0E5           STRB     R1,[R0, #+5]
7
     28          
8
     29            c = y & 0xff;
9
   \   00000024   3410A0E3           MOV      R1,#+52
10
   \   00000028   0610C0E5           STRB     R1,[R0, #+6]
11
     30            d = y >> 8;
12
   \   0000002C   1210A0E3           MOV      R1,#+18
13
   \   00000030   0710C0E5           STRB     R1,[R0, #+7]
kein shift und keine und-verknüpfung.
globale/statische objekte mögen wohl alle compiler lieber ;-)

von F. K. (freddy436)


Lesenswert?

Mich würde mal interessieren welcher Compiler den in der Praxis Probleme 
mit der union Variante hat.

Ich benutze eigentlich auch immer die union Variante.
Die für mich entscheidenden Vorteile:
- Garantiert eine kurze Laufzeit (unabhängig von Qualität des 
Compilers...)
- Deutlich übersichtlicher als die mask/shift Variante.
- Bisher hatte ich noch keine Probleme ;)

Was ich mir problematisch vorstelle sind big/little endian Systeme.
Aber da habe ich doch das selbe Problem auch beim shiften?
Wenn das Probleme verursacht gewinnt aber auch hier wieder die union 
Variante, dann definiert man halt zwei unions, je nach endian.
Beim shiften müsste man alles direkt im Code ändern

von Peter (Gast)


Lesenswert?

> Was ich mir problematisch vorstelle sind big/little endian Systeme.
das ist der hauptgrund, weshalb man es nicht mit unions machen sollte.

> Aber da habe ich doch das selbe Problem auch beim shiften?
nein, shift und andere operatoren sind unabhängig von der internen 
repräsentation der daten.

von déjà vu (Gast)


Lesenswert?

nungut, ich geb mich geschlagen. (avr-)gcc braucht den umweg ueber die 
union, um (in diesem fall) effizienten code zu liefern.

das einzige, womit ich nicht einverstanden bin ist die aussage von 
simon:
>Peter's Art verbraucht "normal" optimiert vermutlich genausolange - aber
>man hat kein Problem mehr mit Compilerabhängigem Gedönsel
unions sind c-standard und nicht "compilerabhaengiges gedoensel". das 
man sie benutzen muss, um das gleiche ergebnis wie mit teuren 
bezahlkompilern zu erhalten ist aergerlich, aber funktionieren tuts mit 
beiden.

so long, déjà vu.

von Peter (Gast)


Lesenswert?

so mach' ich das immer :-)
1
#define LOBYTE(x) ((x)&0xff)
2
#define HIBYTE(x) ((x)>>8)

von Simon K. (simon) Benutzerseite


Lesenswert?

déjà vu wrote:
> unions sind c-standard und nicht "compilerabhaengiges gedoensel".

Ja, unions sind c-standard. Aber nur solange, wie man auf gleichen wegen 
die Daten schreibt/liest. (Sprich: über die gleiche member-variable 
reinschreibt, wie man rausliest)

Wenn man unterschiedliche Union-member zum schreiben und lesen benutzt 
ist das Verhalten nicht mehr im C-Standard definiert.

von déjà vu (Gast)


Lesenswert?

nachtrag:
rein interessehalber, wie siehts eigentlich andersrum aus?
1
y.l = 0x34;
2
y.h = 0x12;
im gegensatz zu:
1
x = 0x34;
2
x |= 0x12 << 8;

kann iar auch das optimieren?

von Peter (Gast)


Lesenswert?

> unions sind c-standard und nicht "compilerabhaengiges gedoensel".

ja, aber es ist nicht alles genau definiert. der compiler könnte 
padding-bytes einsetzen (um zugriffe zu optimieren) und schon passen 
deine bytes nicht mehr. unions sind dazu da, speicherplatz zu sparen. so 
wie du sie verwendest, ist das verhalten undefiniert (auch wenn's in der 
realität oft gut geht).

von déjà vu (Gast)


Lesenswert?

>Wenn man unterschiedliche Union-member zum schreiben und lesen benutzt
>ist das Verhalten nicht mehr im C-Standard definiert.
wieder was gelernt.

von déjà vu (Gast)


Lesenswert?

>so mach' ich das immer :-)
>#define LOBYTE(x) ((x)&0xff)
>#define HIBYTE(x) ((x)>>8)

das geht aber so dann nicht mehr:
1
LOWBYTE(y) = 0x12;
oder?

von Simon K. (simon) Benutzerseite


Lesenswert?

déjà vu wrote:
>>so mach' ich das immer :-)
>>#define LOBYTE(x) ((x)&0xff)
>>#define HIBYTE(x) ((x)>>8)
>
> das geht aber so dann nicht mehr:
>
1
> LOWBYTE(y) = 0x12;
2
>
> oder?

Stimmt. Wozu auch? ;)
1
uint16_t y;
2
3
y = 0x12; // Low byte ist jetzt 0x12
4
y = 0x1200 // High byte ist jetzt 0x12

von déjà vu (Gast)


Lesenswert?

>Stimmt. Wozu auch? ;)
dann eben so:
1
y.h = uart_getc();
2
y.l = uart_getc();
3
4
x = ((uint16_t) uart_getc())<<8 | uart_getc();

von déjà vu (Gast)


Lesenswert?

bzw, um im kontext zu bleiben:
1
LOBYTE(x) = uart_getc();
2
HIBYTE(x) = uart_getc();

mir ist schon klar, dass das nicht geht; aber gibts dafuer ein 
sinnvolles define?
1
#define LOBYTE(x) ( ((un_i16)(x)).l )

geht naemlich nicht...

von Peter (Gast)


Lesenswert?

oder so
1
#define MAKEWORD(x,y) (((uint16_t)(x)<<8)|(y))
:-)

von Simon K. (simon) Benutzerseite


Lesenswert?

Peter wrote:
> oder so
>
1
#define MAKEWORD(x,y) (((uint16_t)(x)<<8)|(y))
> :-)

Jou, oder mit weniger Funktionalität
1
#define MAKEHI(x) ((x) << 8)

von Peter (Gast)


Lesenswert?

> Jou, oder mit weniger Funktionalität
> #define MAKEHI(x) ((x) << 8)
hehe, wenn 'x' ein 'char' ist, gibt das immer 0

von Simon K. (simon) Benutzerseite


Lesenswert?

Peter wrote:
>> Jou, oder mit weniger Funktionalität
>> #define MAKEHI(x) ((x) << 8)
> hehe, wenn 'x' ein 'char' ist, gibt das immer 0

Mist, da hast du recht.
1
#define MAKEHI(x) ( (uint16_t) (x) << 8)

von déjà vu (Gast)


Lesenswert?

ok, mal ein ein konkretes beispiel(vorraussetzung: union-trick 
notwendig, da avr-gcc):
1
ISR(TIMER0_OVF_vect)
2
{
3
    register convert16to8_t counter;
4
    counter.u8h = soft_counter;
5
    counter.u8l = TCNT2;
6
    if ( (TIFR & (1<<TOV2)) && (counter.u8l < 0x7f) )
7
        counter.u8h++;
8
    pitch_value = counter.u16 - pitch_counter;
9
    pitch_counter = counter.u16;
10
    status_set(STATUS_PITCH);
11
}

gaebe es da ein #define, mit dem ich das schreiben koennte:
1
HIBYTE(counter)++;

danach suche ich naemlich schon laenger.
1
#define HIBYTE(x) ( ((un_i16)(x)).h )

funktioniert wiegesagt nur als r-value, nicht als l-value.

von Peter (Gast)


Lesenswert?

> HIBYTE(counter)++;
1
#define INCREMENT_HI_BYTE(x) ((x)+=0x100)
;-)

von déjà vu (Gast)


Lesenswert?

und unabhaengig davon:
1
ISR(TIMER0_OVF_vect)
2
{
3
 37a:   1f 92           push    r1
4
 37c:   0f 92           push    r0
5
 37e:   0f b6           in      r0, 0x3f        ; 63
6
 380:   0f 92           push    r0
7
 382:   11 24           eor     r1, r1
8
 384:   2f 93           push    r18
9
 386:   3f 93           push    r19
10
 388:   8f 93           push    r24
11
    register convert16to8_t counter;
12
    counter.u8h = soft_counter;
13
 38a:   32 2d           mov     r19, r2
14
    counter.u8l = TCNT2;
15
 38c:   84 b5           in      r24, 0x24       ; 36
16
 38e:   28 2f           mov     r18, r24
17
    if ( (TIFR & (1<<TOV2)) && (counter.u8l < 0x7f) )
18
 390:   08 b6           in      r0, 0x38        ; 56
19
 392:   06 fe           sbrs    r0, 6
20
 394:   03 c0           rjmp    .+6             ; 0x39c <__vector_9+0x22>
21
 396:   8f 37           cpi     r24, 0x7F       ; 127
22
 398:   08 f4           brcc    .+2             ; 0x39c <__vector_9+0x22>
23
        counter.u8h++;
24
 39a:   3f 5f           subi    r19, 0xFF       ; 255
25
    pitch_value = counter.u16 - pitch_counter;
26
 39c:   49 01           movw    r8, r18
27
 39e:   8c 18           sub     r8, r12
28
 3a0:   9d 08           sbc     r9, r13
29
    pitch_counter = counter.u16;
30
 3a2:   69 01           movw    r12, r18
31
    status_set(STATUS_PITCH);
32
 3a4:   00 9a           sbi     0x00, 0 ; 0
33
 3a6:   8f 91           pop     r24
34
 3a8:   3f 91           pop     r19
35
 3aa:   2f 91           pop     r18
36
 3ac:   0f 90           pop     r0
37
 3ae:   0f be           out     0x3f, r0        ; 63
38
 3b0:   0f 90           pop     r0
39
 3b2:   1f 90           pop     r1
40
 3b4:   18 95           reti
41
}

das mach mir erstmal einer in c nach... ;)

von déjà vu (Gast)


Lesenswert?

>#define INCREMENT_HI_BYTE(x) ((x)+=0x100)
dann bleib ich lieber bei meinem "union gedoensel" :P

von Peter (Gast)


Lesenswert?

> ISR(TIMER0_OVF_vect)
> {
>    register convert16to8_t counter;
>    counter.u8h = soft_counter;
>    counter.u8l = TCNT2;
>    if ( (TIFR & (1<<TOV2)) && (counter.u8l < 0x7f) )
>        counter.u8h++;
>    pitch_value = counter.u16 - pitch_counter;
>    pitch_counter = counter.u16;
>    status_set(STATUS_PITCH);
>}

probier mal so:
1
ISR(TIMER0_OVF_vect)
2
{
3
    register uint16_t counter;
4
    counter = ((uint16_t)soft_counter << 8) | TCNT2;
5
    if ( (TIFR & (1<<TOV2)) && (counter & 0xff) < 0x7f) )
6
        counter += 0x100;
7
    pitch_value = counter - pitch_counter;
8
    pitch_counter = counter;
9
    status_set(STATUS_PITCH);
10
}
oder so (mit 8 bit variable)
1
ISR(TIMER0_OVF_vect)
2
{
3
    register uint8_t counter = soft_counter;
4
    if ( (TIFR & (1<<TOV2)) && (TCNT2 < 0x7f) )
5
        counter++;
6
    pitch_value = ((uint16_t)counter << 8) | TCNT2;
7
    pitch_counter = pitch_value;
8
    pitch_value -= pitch_counter;
9
    status_set(STATUS_PITCH);
10
}
ich weiss natürlich nicht ob's noch geht (wegen des TCNT2)...

von déjà vu (Gast)


Lesenswert?

beide versionen machen die ISR nur laenger, war ja auch nicht anders zu 
erwarten. mir gings eigentlich auch um ein universelles #define fuer r- 
und l-values. das man das auch "konventionell" schreiben kann, war mir 
schon klar. trotzdem danke, dass du dir die muehe gemacht hast, meinen 
code umzuschreiben. aber "lesbarer" wirds dadurch nicht wirklich. das 
mit dem #define waere halt schoen, da man sich die .u16 sparen koennte. 
aber letztlich kommts ja eh nur auf den bytecode an. und den hab ich mir 
schon  mit komischen c-konstrukten zurechtgebogen ;)

der vollstaendigkeit halber:
1
ISR(TIMER0_OVF_vect)
2
{
3
 37a:   1f 92           push    r1
4
 37c:   0f 92           push    r0
5
 37e:   0f b6           in      r0, 0x3f        ; 63
6
 380:   0f 92           push    r0
7
 382:   11 24           eor     r1, r1
8
 384:   2f 93           push    r18
9
 386:   3f 93           push    r19
10
 388:   8f 93           push    r24
11
 38a:   9f 93           push    r25
12
    register uint16_t counter;
13
    counter = ((uint16_t)soft_counter << 8) | TCNT2;
14
 38c:   82 2d           mov     r24, r2
15
 38e:   99 27           eor     r25, r25
16
 390:   38 2f           mov     r19, r24
17
 392:   22 27           eor     r18, r18
18
 394:   84 b5           in      r24, 0x24       ; 36
19
 396:   99 27           eor     r25, r25
20
 398:   28 2b           or      r18, r24
21
 39a:   39 2b           or      r19, r25
22
    if ( (TIFR & (1<<TOV2)) && (counter & 0xff) < 0x7f)
23
 39c:   08 b6           in      r0, 0x38        ; 56
24
 39e:   06 fe           sbrs    r0, 6
25
 3a0:   04 c0           rjmp    .+8             ; 0x3aa <__vector_9+0x30>
26
 3a2:   2f 37           cpi     r18, 0x7F       ; 127
27
 3a4:   10 f4           brcc    .+4             ; 0x3aa <__vector_9+0x30>
28
        counter += 0x100;
29
 3a6:   20 50           subi    r18, 0x00       ; 0
30
 3a8:   3f 4f           sbci    r19, 0xFF       ; 255
31
    pitch_value = counter - pitch_counter;
32
 3aa:   49 01           movw    r8, r18
33
 3ac:   8c 18           sub     r8, r12
34
 3ae:   9d 08           sbc     r9, r13
35
    pitch_counter = counter;
36
 3b0:   69 01           movw    r12, r18
37
    status_set(STATUS_PITCH);
38
 3b2:   00 9a           sbi     0x00, 0 ; 0
39
 3b4:   9f 91           pop     r25
40
 3b6:   8f 91           pop     r24
41
 3b8:   3f 91           pop     r19
42
 3ba:   2f 91           pop     r18
43
 3bc:   0f 90           pop     r0
44
 3be:   0f be           out     0x3f, r0        ; 63
45
 3c0:   0f 90           pop     r0
46
 3c2:   1f 90           pop     r1
47
 3c4:   18 95           reti
48
}


1
ISR(TIMER0_OVF_vect)
2
{
3
 37a:   1f 92           push    r1
4
 37c:   0f 92           push    r0
5
 37e:   0f b6           in      r0, 0x3f        ; 63
6
 380:   0f 92           push    r0
7
 382:   11 24           eor     r1, r1
8
 384:   2f 93           push    r18
9
 386:   3f 93           push    r19
10
 388:   8f 93           push    r24
11
 38a:   9f 93           push    r25
12
    register uint8_t counter = soft_counter;
13
 38c:   92 2d           mov     r25, r2
14
    if ( (TIFR & (1<<TOV2)) && (TCNT2 < 0x7f) )
15
 38e:   08 b6           in      r0, 0x38        ; 56
16
 390:   06 fe           sbrs    r0, 6
17
 392:   04 c0           rjmp    .+8             ; 0x39c <__vector_9+0x22>
18
 394:   84 b5           in      r24, 0x24       ; 36
19
 396:   8f 37           cpi     r24, 0x7F       ; 127
20
 398:   08 f4           brcc    .+2             ; 0x39c <__vector_9+0x22>
21
        counter++;
22
 39a:   9f 5f           subi    r25, 0xFF       ; 255
23
    pitch_value = ((uint16_t)counter << 8) | TCNT2;
24
 39c:   89 2f           mov     r24, r25
25
 39e:   99 27           eor     r25, r25
26
 3a0:   38 2f           mov     r19, r24
27
 3a2:   22 27           eor     r18, r18
28
 3a4:   84 b5           in      r24, 0x24       ; 36
29
 3a6:   99 27           eor     r25, r25
30
    pitch_counter = pitch_value;
31
 3a8:   69 01           movw    r12, r18
32
 3aa:   c8 2a           or      r12, r24
33
 3ac:   d9 2a           or      r13, r25
34
    pitch_value -= pitch_counter;
35
 3ae:   88 24           eor     r8, r8
36
 3b0:   99 24           eor     r9, r9
37
    status_set(STATUS_PITCH);
38
 3b2:   00 9a           sbi     0x00, 0 ; 0
39
 3b4:   9f 91           pop     r25
40
 3b6:   8f 91           pop     r24
41
 3b8:   3f 91           pop     r19
42
 3ba:   2f 91           pop     r18
43
 3bc:   0f 90           pop     r0
44
 3be:   0f be           out     0x3f, r0        ; 63
45
 3c0:   0f 90           pop     r0
46
 3c2:   1f 90           pop     r1
47
 3c4:   18 95           reti
48
}

so long, déjà vu.

von Peter (Gast)


Lesenswert?

> beide versionen machen die ISR nur laenger, war ja auch nicht anders zu
> erwarten.
ja, schade :-(
den GCC sollte man eben mit vorsicht geniessen, aber wenn man die tricks 
kennt...

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.