mikrocontroller.net

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


Autor: tt (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: déjà vu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
(ust1_data[3]).h ?

Autor: déjà vu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>(ust1_data[3]).h ?

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

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

Autor: tt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke, guter Ansatz

ust1_data[3].i8.h

bringt keine Fehlermeldung mehr.

Autor: Peter (Gast)
Datum:

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

Autor: Punktrichter (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Ralph (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
probier es mal so

 SSP1BUF=ust1_data[3].i8.h;

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: déjà vu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
#include <stdint.h>
#include <avr/io.h>

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

volatile uint16_t x ;
volatile un_i16 y;

int main(void)
{
    x = 0x1234;
    y.i16 = 0x5678;

    DDRB = x & 0xff;;
    PORTB = x >> 8;;
    DDRC = y.l;
    PORTC = y.h;
}

ergibt:
0000005c <main>:
volatile uint16_t x ;
volatile un_i16 y;

int main(void)
{
  5c:   cf e5           ldi     r28, 0x5F       ; 95
  5e:   d4 e0           ldi     r29, 0x04       ; 4
  60:   de bf           out     0x3e, r29       ; 62
  62:   cd bf           out     0x3d, r28       ; 61
    x = 0x1234;
  64:   84 e3           ldi     r24, 0x34       ; 52
  66:   92 e1           ldi     r25, 0x12       ; 18
  68:   90 93 61 00     sts     0x0061, r25
  6c:   80 93 60 00     sts     0x0060, r24
    y.i16 = 0x5678;
  70:   88 e7           ldi     r24, 0x78       ; 120
  72:   96 e5           ldi     r25, 0x56       ; 86
  74:   90 93 63 00     sts     0x0063, r25
  78:   80 93 62 00     sts     0x0062, r24

    DDRB = x & 0xff;;
  7c:   80 91 60 00     lds     r24, 0x0060
  80:   90 91 61 00     lds     r25, 0x0061
  84:   87 bb           out     0x17, r24       ; 23
    PORTB = x >> 8;;
  86:   80 91 60 00     lds     r24, 0x0060
  8a:   90 91 61 00     lds     r25, 0x0061
  8e:   89 2f           mov     r24, r25
  90:   99 27           eor     r25, r25
  92:   88 bb           out     0x18, r24       ; 24
    DDRC = y.l;
  94:   80 91 62 00     lds     r24, 0x0062
  98:   84 bb           out     0x14, r24       ; 20
    PORTC = y.h;
  9a:   80 91 63 00     lds     r24, 0x0063
  9e:   85 bb           out     0x15, r24       ; 21
}
  a0:   80 e0           ldi     r24, 0x00       ; 0
  a2:   90 e0           ldi     r25, 0x00       ; 0
  a4:   00 c0           rjmp    .+0             ; 0xa6 <_exit>

000000a6 <_exit>:
  a6:   ff cf           rjmp    .-2             ; 0xa6 <_exit>

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

Autor: déjà vu (Gast)
Datum:

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

Autor: Peter (Gast)
Datum:

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

Autor: déjà vu (Gast)
Datum:

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

Autor: déjà vu (Gast)
Datum:

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

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;

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

int main()
{
  un_i16 x;
  uint16_t y;
  volatile uint8_t a,b,c,d; 

  x.i16 = 0x1234;
  y = 0x1234;

  a = x.i8.l;
  b = x.i8.h;

  c = y & 0xff;
  d = y >> 8;
}
ergibt:
      1          #include <stdlib.h>
      2          #include <string.h>
      3          
      4          typedef unsigned char uint8_t;
      5          typedef unsigned short uint16_t;
      6          
      7          typedef union
      8          {
      9            uint16_t i16;
     10            struct
     11            {
     12              uint8_t l;
     13              uint8_t h;
     14            }i8;
     15          } un_i16;
     16          

   \                                 In segment CODE, align 4, keep-with-next
     17          int main()
     18          {
   \                     main:
   \   00000000   04D04DE2           SUB      SP,SP,#+4
     19            un_i16 x;
     20            uint16_t y;
     21            volatile uint8_t a,b,c,d; 
     22          
     23            x.i16 = 0x1234;
   \   00000004   3410A0E3           MOV      R1,#+52
   \   00000008   481D81E3           ORR      R1,R1,#0x1200
   \   0000000C   B210CDE1           STRH     R1,[SP, #+2]
     24            y = 0x1234;
   \   00000010   3400A0E3           MOV      R0,#+52
   \   00000014   480D80E3           ORR      R0,R0,#0x1200
     25          
     26            a = x.i8.l;
   \   00000018   0220DDE5           LDRB     R2,[SP, #+2]
   \   0000001C   0020CDE5           STRB     R2,[SP, #+0]
     27            b = x.i8.h;
   \   00000020   0320DDE5           LDRB     R2,[SP, #+3]
   \   00000024   0020CDE5           STRB     R2,[SP, #+0]
     28          
     29            c = y & 0xff;
   \   00000028   0000CDE5           STRB     R0,[SP, #+0]
     30            d = y >> 8;
   \   0000002C   2004B0E1           LSRS     R0,R0,#+8
   \   00000030   0000CDE5           STRB     R0,[SP, #+0]
     31          }
   \   00000034   0000A0E3           MOV      R0,#+0
   \   00000038   04D08DE2           ADD      SP,SP,#+4        ;; stack cleaning
   \   0000003C   1EFF2FE1           BX       LR               ;; return

   Maximum stack usage in bytes:

     Function CSTACK
     -------- ------
     main         4


   Segment part sizes:

     Function/Label Bytes
     -------------- -----
     main             64
      Others           4

 
 68 bytes in segment CODE
 
 64 bytes of CODE memory (+ 4 bytes shared)

Errors: none
Warnings: none

Autor: déjà vu (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
int main(void)
{
  5c:   cb e5           ldi     r28, 0x5B       ; 91
  5e:   d4 e0           ldi     r29, 0x04       ; 4
  60:   de bf           out     0x3e, r29       ; 62
  62:   cd bf           out     0x3d, r28       ; 61
  un_i16 x;
  uint16_t y;
  volatile uint8_t a,b,c,d;

  x.i16 = 0x1234;
  64:   84 e3           ldi     r24, 0x34       ; 52
  66:   92 e1           ldi     r25, 0x12       ; 18
  y = 0x1234;

  a = x.i8.l;
  68:   89 83           std     Y+1, r24        ; 0x01
  b = x.i8.h;
  6a:   9a 83           std     Y+2, r25        ; 0x02

  c = y & 0xff;
  6c:   8b 83           std     Y+3, r24        ; 0x03
  d = y >> 8;
  6e:   82 e1           ldi     r24, 0x12       ; 18
  70:   90 e0           ldi     r25, 0x00       ; 0
  72:   8c 83           std     Y+4, r24        ; 0x04
}

Autor: déjà vu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
vorweg schonmal das ergebnis von avr-gcc mit x und y als volatile:
int main(void)
{
  5c:   c7 e5           ldi     r28, 0x57       ; 87
  5e:   d4 e0           ldi     r29, 0x04       ; 4
  60:   de bf           out     0x3e, r29       ; 62
  62:   cd bf           out     0x3d, r28       ; 61
  volatile un_i16 x;
  volatile uint16_t y;
  volatile uint8_t a,b,c,d;

  x.i16 = 0x1234;
  64:   84 e3           ldi     r24, 0x34       ; 52
  66:   92 e1           ldi     r25, 0x12       ; 18
  68:   9a 83           std     Y+2, r25        ; 0x02
  6a:   89 83           std     Y+1, r24        ; 0x01
  y = 0x1234;
  6c:   9c 83           std     Y+4, r25        ; 0x04
  6e:   8b 83           std     Y+3, r24        ; 0x03

  a = x.i8.l;
  70:   89 81           ldd     r24, Y+1        ; 0x01
  72:   8d 83           std     Y+5, r24        ; 0x05
  b = x.i8.h;
  74:   8a 81           ldd     r24, Y+2        ; 0x02
  76:   8e 83           std     Y+6, r24        ; 0x06

  c = y & 0xff;
  78:   8b 81           ldd     r24, Y+3        ; 0x03
  7a:   9c 81           ldd     r25, Y+4        ; 0x04
  7c:   8f 83           std     Y+7, r24        ; 0x07
  d = y >> 8;
  7e:   8b 81           ldd     r24, Y+3        ; 0x03
  80:   9c 81           ldd     r25, Y+4        ; 0x04
  82:   89 2f           mov     r24, r25
  84:   99 27           eor     r25, r25
  86:   88 87           std     Y+8, r24        ; 0x08
}

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
     26            a = x.i8.l;
   \   00000014   0010D0E5           LDRB     R1,[R0, #+0]
   \   00000018   0410C0E5           STRB     R1,[R0, #+4]
     27            b = x.i8.h;
   \   0000001C   0110D0E5           LDRB     R1,[R0, #+1]
   \   00000020   0510C0E5           STRB     R1,[R0, #+5]
     28          
     29            c = y & 0xff;
   \   00000024   3410A0E3           MOV      R1,#+52
   \   00000028   0610C0E5           STRB     R1,[R0, #+6]
     30            d = y >> 8;
   \   0000002C   1210A0E3           MOV      R1,#+18
   \   00000030   0710C0E5           STRB     R1,[R0, #+7]
kein shift und keine und-verknüpfung.
globale/statische objekte mögen wohl alle compiler lieber ;-)

Autor: F. Kriewitz (freddy436)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: déjà vu (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Peter (Gast)
Datum:

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

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: déjà vu (Gast)
Datum:

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

kann iar auch das optimieren?

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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).

Autor: déjà vu (Gast)
Datum:

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

Autor: déjà vu (Gast)
Datum:

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

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

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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:
>
> LOWBYTE(y) = 0x12;
> 
> oder?

Stimmt. Wozu auch? ;)
uint16_t y;

y = 0x12; // Low byte ist jetzt 0x12
y = 0x1200 // High byte ist jetzt 0x12

Autor: déjà vu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Stimmt. Wozu auch? ;)
dann eben so:
y.h = uart_getc();
y.l = uart_getc();

x = ((uint16_t) uart_getc())<<8 | uart_getc();

Autor: déjà vu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
bzw, um im kontext zu bleiben:
LOBYTE(x) = uart_getc();
HIBYTE(x) = uart_getc();

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

geht naemlich nicht...

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
oder so
#define MAKEWORD(x,y) (((uint16_t)(x)<<8)|(y))
:-)

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter wrote:
> oder so
>
#define MAKEWORD(x,y) (((uint16_t)(x)<<8)|(y))
> :-)

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


Autor: Peter (Gast)
Datum:

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

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.
#define MAKEHI(x) ( (uint16_t) (x) << 8)

Autor: déjà vu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok, mal ein ein konkretes beispiel(vorraussetzung: union-trick 
notwendig, da avr-gcc):
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);
}

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

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

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

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> HIBYTE(counter)++;
#define INCREMENT_HI_BYTE(x) ((x)+=0x100)
;-)

Autor: déjà vu (Gast)
Datum:

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

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

Autor: déjà vu (Gast)
Datum:

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

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
ISR(TIMER0_OVF_vect)
{
    register uint16_t counter;
    counter = ((uint16_t)soft_counter << 8) | TCNT2;
    if ( (TIFR & (1<<TOV2)) && (counter & 0xff) < 0x7f) )
        counter += 0x100;
    pitch_value = counter - pitch_counter;
    pitch_counter = counter;
    status_set(STATUS_PITCH);
}
oder so (mit 8 bit variable)
ISR(TIMER0_OVF_vect)
{
    register uint8_t counter = soft_counter;
    if ( (TIFR & (1<<TOV2)) && (TCNT2 < 0x7f) )
        counter++;
    pitch_value = ((uint16_t)counter << 8) | TCNT2;
    pitch_counter = pitch_value;
    pitch_value -= pitch_counter;
    status_set(STATUS_PITCH);
}
ich weiss natürlich nicht ob's noch geht (wegen des TCNT2)...

Autor: déjà vu (Gast)
Datum:

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


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

so long, déjà vu.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

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.