Forum: Mikrocontroller und Digitale Elektronik XC8 für Pic18 Arithmetik


von Holger S. (alberich)


Lesenswert?

Hallo zusammen,
mich macht gerade das einfache byteweise Auslesen eines 16 Bit Messwerts 
über i2c wahnsinnig, C- und PIC18-Versierte mögen doch bitte mal 
darüberschauen und mir sagen, auf welchem Schlauch ich stehe.

Ich betreibe div. Sensoren via I2C an einem PIC18 Controller, welchen 
ich mit MPLAB-X und XC8 programmiere.
Das funktionierte anfangs alles recht problemlos, mit steigender 
Komplexität schlichen sich einige sehr seltsame Effekte ein, bereits 
funktionierender Code lieferte plötzlich wirre Daten.
Einen solchen Effekt konnte ich einkreisen & wäre für eine Erklärung 
dankbar:
Ein 16bit Messwert wird über I2c byteweise ausgelesen, und soll nun zu 
einem 16 bit int werden, welcher dann auf einem Display (4 char Hex) 
angezeigt wird. Die von i2c gelesenen Daten liegen in einem unsigned 
char Array, Indexposition 4 (lo) und 5 (hi).
Der Testcode soll nun das hi-Byte aus dem Array in eine int Variable 
kopieren und 8 bit nach links shiften. Die int Variable wird dann auf 
einem Display ausgegeben. Das lo Byte vergessen wir erst mal. Das 
Hi-Byte des realen Messwerts toggelt zwischen 0x44 und 0x45.
************
1. Beispiel. So sollte es funktionieren...
1
unsigned char bb = I2C_Recv[5];
2
int z = bb << 8;
3
showint(z);
Ergebnis: Die Anzeige zeigt für das hi-Byte wirr alle möglichen Werte 
an, lo ist immer "00":
************
2. Beispiel. Ich spare mir zu Debugzwecken das shiften:
1
unsigned char bb = I2C_Recv[5];
2
int z = bb;
3
showint(z);
Ergebnis: Die Anzeige toggelt zwischen "0044" und "0045". passt.
************
3. Beispiel. Ich shifte nur 4 Bit:
1
unsigned char bb = I2C_Recv[5];
2
int z = bb << 4;
3
showint(z);
Ergebnis: Die Anzeige toggelt zwischen "0440" und "0450". passt.
************
4. Beispiel. Ich shifte komplett, verwende aber ein hardcode 
Messergebnis:
1
unsigned char bb = 0x44; 
2
int z = bb << 8;
3
showint(z);
Ergebnis: Die Anzeige zeigt stabil "4400".
************
Tatsächlich kann ich mein Messergebnis erfolgreich um 5 bit nach links 
shiften, dann toggelt die Anzeige zwischen "0880" und "08A0", das passt. 
Sobald ich 6 bit oder mehr shifte, zeigt mein Display nur noch wirre 
Werte.

Die Messwerte werden vor den Codebeispielen vom Sensor gelesen, kein 
asynchrones Auslesen.
Interrupts werden lediglich für die LED-Anzeige benutzt.

Hat irgendjemand eine Idee, was da passiert?
ciao
Alberich

von Frank K. (fchk)


Lesenswert?

Mach mal
1
int z = (int)bb << 8;

Der Compiler weiß wohl, dass wenn Du ein char 8 bits nach links oder 
rechts schiebst, immer 0 rauskommt. Standardkonform ist das nicht, er 
hätte den Operanden erst nach int wandeln müssen. Vim Schieben um 4 
unterbleibt diese Optimierung.

fchk

von Andreas H. (ahz)


Lesenswert?

Frank K. schrieb:
> Standardkonform ist das nicht, er
> hätte den Operanden erst nach int wandeln müssen

Frank, bist Du da sicher ?

Ich habe da im Hinterkopf, dass die RHS (also bb << 8) insgesamt auf das 
Format der LHS gecastet wird. Den Ausdruck bb << 8 macht der Compiler 
vor der Zuweisung, dann aber mit dem Datentyp von bb, also unsigned 
char.

Über sollche Details "stolpert" man ja immer gerne mal (und ich 
besonders ;-)

Grüße
Andreas

von Holger S. (alberich)


Lesenswert?

Ich habe das auch schon Schrittweise versucht, char->int und dann int 
shiften, gleiches Ergebnis. Ebenso mit 4 bit shiften und dann noch mal 4 
bit, keine Änderung. Beispiel 4 dürfte dann ja auch nicht funktionieren.

Aber von meiner Warte aus schließen sich die 4 Beispiele eh gegenseitig 
aus. Irgendeine Optimierung könnte Schuld sein, glaube ich aber 
eigentlich nicht.

Der Code hat ja mal funktioniert. Dann habe ich Gimmicks wie dezimale 
Ausgabe hinzugefügt & dann fing das an.

Ich hatte zwischendurch beispielsweise folgenden Effekt: Eine Methode
1
void NonsenseCalc() {
2
    int xy = 0x3482;
3
    xy = xy / 23;
4
}
macht eigentlich nichts. Wenn ich sie während der Messwertumrechnung 
aufgerufen habe, lieferte die Messwertumrechnung wirre Ergebnisse.

Ich hatte das dann auf irgendeinen Stacküberlauf o.ä. geschoben und die 
Zahl der Funktionsaufrufe minimiert, das half erst mal. Jetzt habe ich 
allerdings für die Fehlersuche den Code für einzelne Sensoren komplett 
entfernt, ohne dass es geholfen hätte.

von Frank K. (fchk)


Lesenswert?

Holger Schneider schrieb:
> Ich habe das auch schon Schrittweise versucht, char->int und dann int
> shiften, gleiches Ergebnis. Ebenso mit 4 bit shiften und dann noch mal 4
> bit, keine Änderung. Beispiel 4 dürfte dann ja auch nicht funktionieren.

Bei Beispiel 4 kann der Compiler das Ergebnis bereits zur Compilezeit 
berechnen. Da dürftest Du dann nur eine Konstante im Binary finden.

Lass Dir den erzeugten Assemblercode ausgeben. Dann siehst Du, was der 
Compiler daraus macht.

fchk

von Stefan (Gast)


Lesenswert?

> Bei Beispiel 4 kann der Compiler das Ergebnis bereits zur Compilezeit
> berechnen. Da dürftest Du dann nur eine Konstante im Binary finden.

Es geht hier um den XC8 ;).
1
801                           ;main.c: 36: unsigned char bb = 0x44;
2
   802  0010  3044                 movlw  68
3
   803  0011  00F3                 movwf  ??_main
4
   804  0012  0873                 movf  ??_main,w
5
   805  0013  00F7                 movwf  main@bb
6
   806                           
7
   807                           ;main.c: 37: int z = bb << 6;
8
   808  0014  0877                 movf  main@bb,w
9
   809  0015  00F3                 movwf  ??_main
10
   810  0016  01F4                 clrf  ??_main+1
11
   811  0017  3006                 movlw  6
12
   812  0018                     u15:  
13
   813  0018  35F3                 lslf  ??_main,f
14
   814  0019  0DF4                 rlf  ??_main+1,f
15
   815  001A  0B89                 decfsz  9,f
16
   816  001B  2818                 goto  u15
17
   817  001C  0873                 movf  ??_main,w
18
   818  001D  00F5                 movwf  main@z
19
   819  001E  0874                 movf  ??_main+1,w
20
   820  001F  00F6                 movwf  main@z+1
21
   821                           
22
   822                           ;main.c: 38: showInt(z);
23
   823  0020  0876                 movf  main@z+1,w
24
   824  0021  01F2                 clrf  showInt@2475+1
25
   825  0022  07F2                 addwf  showInt@2475+1,f
26
   826  0023  0875                 movf  main@z,w
27
   827  0024  01F1                 clrf  showInt@2475
28
   828  0025  07F1                 addwf  showInt@2475,f
29
   829  0026  2028                 fcall  _showInt

von Michael S. (rbs_phoenix)


Lesenswert?

Wie sieht der ASM aus, wenn es mit Funktionsaufruf ist?
6 shifts sehe ich da auch nicht, eher 8.

Was passiert, wenn du z = bb machst und erst danach << 8?
Kann es so wie es momentan ist nicht so sein, dass er bb nach links 
shiftet, einen Überlauf hat und dann erst die Zuweisung macht?

von Max H. (hartl192)


Lesenswert?

Probiers mal damit:
z=IC_Recv[5];
z=(z<<8)+IC_Recv[4];

von Axel S. (a-za-z0-9)


Lesenswert?

Holger Schneider schrieb:
> Ein 16bit Messwert wird über I2c byteweise ausgelesen, und soll nun zu
> einem 16 bit int werden, welcher dann auf einem Display (4 char Hex)
> angezeigt wird. Die von i2c gelesenen Daten liegen in einem unsigned
> char Array, Indexposition 4 (lo) und 5 (hi).

Aha. Aber dann brauchst du den 16 Bit Zwischenwert doch gar nicht?
1
void hexout(uint8_t x)
2
{
3
    uint8_t nibble= x>>4;
4
    putc(nibble>9 ? '0'+nibble : 'A'-10+nibble);
5
    nibble= x& 0x0F;
6
    putc(nibble>9 ? '0'+nibble : 'A'-10+nibble);
7
}
8
9
hexout(I2C_Recv[5]);
10
hexout(I2C_Recv[4]);

und nur für den Fall, daß du den 16 Bit int auch noch für etwas anderes 
als die Ausgabe brauchst:
1
uint16_t val= I2C_Recv[5];
2
val= val<<8 | I2C_Recv[4];


XL

von Dieter W. (dds5)


Lesenswert?

>    811  0017  3006                 movlw  6
>    812  0018                     u15:
>    813  0018  35F3                 lslf  ??_main,f
>    814  0019  0DF4                 rlf  ??_main+1,f
>    815  001A  0B89                 decfsz  9,f
>    816  001B  2818                 goto  u15

Da geht was kräftig schief.

Die Laufvariable für die shift-Schleife wird in das w-Register geladen 
aber in der Schleife wird plötzlich die Adresse 9 als Zähler verwendet.

Laut DB liegt auf 9 je nach Bank das PORTE oder TRISE Register (falls 
vorhanden).

Keine Ahnung warum der Compiler da Mist macht.

von chris (Gast)


Lesenswert?

bei 16f ja, bei 18f nein, da sind die Ports anders gemappt.

von Dieter W. (dds5)


Lesenswert?

chris schrieb:
> bei 16f ja, bei 18f nein, da sind die Ports anders gemappt.

Grmpf, da fehlt mir offenbar der aktuelle Bezug.

Ich mach schon seit ein paar Jahren nix mehr mit PIC16 und 18, ist nur 
noch Schubladen-Wissen.

von Max H. (hartl192)


Lesenswert?

chris schrieb:
> bei 16f ja, bei 18f nein, da sind die Ports anders gemappt.
Beim PIC16 sind SFR am Anfang jeder Bank, bei P18 sind die meisten am 
Ende der letzten Bank.

Mein XC8 löst das so:
1
21:                     bb=I2C_Recv[5];
2
  7FCC    C008     MOVFF 0x8, 0xd
3
  7FCE    F00D     NOP
4
22:                  z=bb<<6;//+I2C_Recv[4];
5
  7FD0    500D     MOVF 0xd, W, ACCESS
6
  7FD2    6E01     MOVWF 0x1, ACCESS
7
  7FD4    6A02     CLRF 0x2, ACCESS
8
  7FD6    0E06     MOVLW 0x6
9
  7FD8    90D8     BCF 0xfd8, 0, ACCESS
10
  7FDA    3601     RLCF 0x1, F, ACCESS
11
  7FDC    3602     RLCF 0x2, F, ACCESS
12
  7FDE    2EE8     DECFSZ 0xfe8, F, ACCESS
13
  7FE0    D7FB     BRA 0x7fd8
14
  7FE2    C001     MOVFF 0x1, 0xb
15
  7FE4    F00B     NOP
16
  7FE6    C002     MOVFF 0x2, 0xc
17
  7FE8    F00C     NOP
Ich habe jetzt nicht nachgeschaut, aber 0xfe8 müsste die Adresse des 
WREG sein.

: Bearbeitet durch User
von Holger S. (alberich)


Lesenswert?

Ich habe zwei Varianten compiliert & den Code gegenübergestellt. Ein mal 
der funktionierende Shift um 4 Bit, dann der nicht funktionierende Shift 
um 8 Bit:
************ 4-Bit shift:
1
unsigned char bb = I2C_Recv[5]; 
2
int z = ((int)bb) << 4;
Assemblercode:
1
   911                           ;gyro.c: 77: unsigned char bb = I2C_Recv[5];
2
   912  0003C6  C07E  F091           movff  _I2C_Recv+5,Gyroscope@bb
3
   913                           
4
   914                           ; BSR set to: 0
5
   915                           ;gyro.c: 78: z = ((int)bb) << 4;
6
   916  0003CA  0100                 movlb  0  ; () banked
7
   917  0003CC  0100                 movlb  0  ; () banked
8
   918  0003CE  5191                 movf  Gyroscope@bb& (0+255),w,b
9
   919  0003D0  6E20                 movwf  ??_Gyroscope& (0+255),c
10
   920  0003D2  6A21                 clrf  (??_Gyroscope+1)& (0+255),c
11
   921  0003D4  3A20                 swapf  ??_Gyroscope,f,c
12
   922  0003D6  3A21                 swapf  ??_Gyroscope+1,f,c
13
   923  0003D8  0EF0                 movlw  240
14
   924  0003DA  1621                 andwf  ??_Gyroscope+1,f,c
15
   925  0003DC  5020                 movf  ??_Gyroscope,w,c
16
   926  0003DE  0B0F                 andlw  15
17
   927  0003E0  1221                 iorwf  ??_Gyroscope+1,f,c
18
   928  0003E2  0EF0                 movlw  240
19
   929  0003E4  1620                 andwf  ??_Gyroscope,f,c
20
   930  0003E6  C020  F092           movff  ??_Gyroscope,Gyroscope@z
21
   931  0003EA  C021  F093           movff  ??_Gyroscope+1,Gyroscope@z+1

************ 8-Bit shift:
1
unsigned char bb = I2C_Recv[5]; 
2
int z = ((int)bb) << 8;
Assemblercode:
1
   911                           ;gyro.c: 77: unsigned char bb = I2C_Recv[5];
2
   912  0003C6  C07E  F091           movff  _I2C_Recv+5,Gyroscope@bb
3
   913                           
4
   914                           ; BSR set to: 0
5
   915                           ;gyro.c: 78: z = ((int)bb) << 8;
6
   916  0003CA  0100                 movlb  0  ; () banked
7
   917  0003CC  0100                 movlb  0  ; () banked
8
   918  0003CE  5191                 movf  Gyroscope@bb& (0+255),w,b
9
   919  0003D0  0100                 movlb  0  ; () banked
10
   920  0003D2  0100                 movlb  0  ; () banked
11
   921  0003D4  6F93                 movwf  (Gyroscope@z+1)& (0+255),b
12
   922  0003D6  0100                 movlb  0  ; () banked
13
   923  0003D8  6B92                 clrf  Gyroscope@z& (0+255),b

Offensichtlich wird da optimiert. Eigentlich wird nirgendwo geshiftet, 
das höchste der Gefühle ist ein swapf... Die "movlb  0  ; () banked" 
verstehe ich allerdings nicht.

von Holger S. (alberich)


Lesenswert?

Der Vollständigkeit halber noch ein (ebenfalls nicht funktionierender) 
Shift um 6 Bit:
1
unsigned char bb = I2C_Recv[5];
2
int z = ((int)bb) << 6;
Assemblercode:
1
   911                           ;gyro.c: 77: unsigned char bb = I2C_Recv[5];
2
   912  0003C6  C07E  F091           movff  _I2C_Recv+5,Gyroscope@bb
3
   913                           
4
   914                           ; BSR set to: 0
5
   915                           ;gyro.c: 78: z = ((int)bb) << 6;
6
   916  0003CA  0100                 movlb  0  ; () banked
7
   917  0003CC  0100                 movlb  0  ; () banked
8
   918  0003CE  5191                 movf  Gyroscope@bb& (0+255),w,b
9
   919  0003D0  6E20                 movwf  ??_Gyroscope& (0+255),c
10
   920  0003D2  6A21                 clrf  (??_Gyroscope+1)& (0+255),c
11
   921  0003D4  0E06                 movlw  6
12
   922  0003D6                     u1615:
13
   923  0003D6  90D8                 bcf  status,0,c
14
   924  0003D8  3620                 rlcf  ??_Gyroscope,f,c
15
   925  0003DA  3621                 rlcf  ??_Gyroscope+1,f,c
16
   926  0003DC  2EE8                 decfsz  wreg,f,c
17
   927  0003DE  D7FB                 goto  u1615
18
   928  0003E0  C020  F092           movff  ??_Gyroscope,Gyroscope@z
19
   929  0003E4  C021  F093           movff  ??_Gyroscope+1,Gyroscope@z+1

Jetzt ist wenigstens mal ein Loop dabei :-)

von Frank K. (fchk)


Lesenswert?

Schreibe das mal in den Microchip-Foren.

fchk

von Axel S. (a-za-z0-9)


Lesenswert?

Holger Schneider schrieb:
> Offensichtlich wird da optimiert. Eigentlich wird nirgendwo geshiftet,
> das höchste der Gefühle ist ein swapf

Auf µC deren ALU keinen Barrelshifter hat, ist die Verwendung von swap 
(high- und low-Nibble in einem Byte tauschen) eine gute Optimierung für 
die Implementierung eines Shifts um 4 Bits. Ich würde die 
Nichtverwendung von Schiebe-Opcodes als positives Zeichen sehen.


XL

von B. S. (bestucki)


Lesenswert?

- Welchen PIC verwendest du?
- Bist du sicher, dass die Zahl korrekt in einen String umgewandelt und 
auf dem Display angezeigt wird?
- Verwendest du die aktuellste Version vom XC8 (V1.30)? Der Compiler ist 
noch jung und Microchip muss noch viele Fehler korrigieren...

Im Simulator funktioniert das Schieben (MPLAB X V1.95, XC8 V1.30):
1
  unsigned char a=1;
2
  int x=(int)a<<6;
1
1FE2  5005     MOVF a, W, ACCESS
2
1FE4  6E01     MOVWF 0x1, ACCESS
3
1FE6  6A02     CLRF 0x2, ACCESS
4
1FE8  0E06     MOVLW 0x6
5
1FEA  90D8     BCF STATUS, 0, ACCESS
6
1FEC  3601     RLCF 0x1, F, ACCESS
7
1FEE  3602     RLCF 0x2, F, ACCESS
8
1FF0  2EE8     DECFSZ WREG, F, ACCESS
9
1FF2  D7FB     BRA 0x1FEA
10
1FF4  C001     MOVFF 0x1, x
11
1FF6  F003     NOP
12
1FF8  C002     MOVFF 0x2, 0x4
13
1FFA  F004     NOP


Nachtrag:
Interessant ist auch, dass der XC8 das nicht in eine Multiplikation mit 
64 umwandelt, schliesslich besitzen die PIC18 einen 
Hardwaremultiplizierer und der erzeugte Code ist kürzer...
1
  unsigned char a=1;
2
  int x=(int)a*64;
1
1FF0  5004     MOVF a, W, ACCESS
2
1FF2  0D40     MULLW 0x40
3
1FF4  CFF3     MOVFF PRODL, x
4
1FF6  F002     NOP
5
1FF8  CFF4     MOVFF PRODH, 0x3
6
1FFA  F003     NOP

: Bearbeitet durch User
von Stefan (Gast)


Lesenswert?

ohne Worte


XC8:
1
   195                           ;main.c: 38: unsigned char a=1;
2
   196  00008C  6E15                 movwf  ??_main& (0+255),c
3
   197  00008E  0E01                 movlw  1
4
   198  000090  6E1A                 movwf  main@a,c
5
   199  000092  5015                 movf  ??_main& (0+255),w,c
6
   200                           
7
   201                           ;main.c: 39: int x=(int)a<<6;
8
   202  000094  501A                 movf  main@a,w,c
9
   203  000096  6E15                 movwf  ??_main& (0+255),c
10
   204  000098  6A16                 clrf  (??_main+1)& (0+255),c
11
   205  00009A  0E06                 movlw  6
12
   206  00009C                     u15:
13
   207  00009C  90D8                 bcf  status,0,c
14
   208  00009E  3615                 rlcf  ??_main,f,c
15
   209  0000A0  3616                 rlcf  ??_main+1,f,c
16
   210  0000A2  2EE8                 decfsz  wreg,f,c
17
   211  0000A4  D7FB                 goto  u15
18
   212  0000A6  C015  F018           movff  ??_main,main@x
19
   213  0000AA  C016  F019           movff  ??_main+1,main@x+1
20
   214                           
21
   215                           ;main.c: 40: puts(x);
22
   216  0000AE  C018  F015           movff  main@x,??_main
23
   217  0000B2  C019  F016           movff  main@x+1,??_main+1
24
   218  0000B6  6A17                 clrf  (??_main+2)& (0+255),c
25
   219  0000B8  BE16                 btfsc  (??_main+1)& (0+255),7,c
26
   220  0000BA  6817                 setf  (??_main+2)& (0+255),c
27
   221  0000BC  C015  F012           movff  ??_main,puts@s
28
   222  0000C0  C016  F013           movff  ??_main+1,puts@s+1
29
   223  0000C4  C017  F014           movff  ??_main+2,puts@s+2
30
   224  0000C8  EC84  F000           call  _puts  ;wreg free


avr-gcc:
1
474:main.c        ****   unsigned char a=1;
2
 475:main.c        ****   int x=(int)a<<6;
3
 476:main.c        ****   puts(x);
4
 924                 .LM120:
5
 925 00b8 80E4          ldi r24,lo8(64)
6
 926 00ba 90E0          ldi r25,0
7
 927 00bc 00D0          rcall puts

von Michael S. (rbs_phoenix)


Lesenswert?

Gut, dass das hier hinpasst.
Toll, jetzt muss man solche piss (AVR) Fanboys auch noch ertragen, wenns 
um ein PIC Compiler Problem/Frage geht... Die kommen bestimmt auch noch 
im Off-Topic Bereich an..

Holger Schneider schrieb:

> ************ 8-Bit shift:unsigned char bb = I2C_Recv[5];
> int z = ((int)bb) << 8;
> Assemblercode:   911                           ;gyro.c: 77: unsigned
> char bb = I2C_Recv[5];
>    912  0003C6  C07E  F091           movff  _I2C_Recv+5,Gyroscope@bb
>    913
>    914                           ; BSR set to: 0
>    915                           ;gyro.c: 78: z = ((int)bb) << 8;
>    916  0003CA  0100                 movlb  0  ; () banked
>    917  0003CC  0100                 movlb  0  ; () banked
>    918  0003CE  5191                 movf  Gyroscope@bb& (0+255),w,b
>    919  0003D0  0100                 movlb  0  ; () banked
>    920  0003D2  0100                 movlb  0  ; () banked
>    921  0003D4  6F93                 movwf  (Gyroscope@z+1)& (0+255),b
>    922  0003D6  0100                 movlb  0  ; () banked
>    923  0003D8  6B92                 clrf  Gyroscope@z& (0+255),b
>
> Offensichtlich wird da optimiert. Eigentlich wird nirgendwo geshiftet,
> das höchste der Gefühle ist ein swapf... Die "movlb  0  ; () banked"
> verstehe ich allerdings nicht.

So wie ich das sehe, weist er dem Highbyte von z die Zahl zu (921) und 
löscht das Lowbyte (923). Da braucht er nicht shiften.

von No one cares (Gast)


Angehängte Dateien:

Lesenswert?

Stefan schrieb:
> avr-gcc:

von Axel S. (a-za-z0-9)


Lesenswert?

Stefan schrieb:
> ohne Worte
>
> XC8:

[24 Instruktionen]

> avr-gcc:

[3 Instruktionen]

LOL. "Treffer, versenkt" würde ich sagen :D

Andererseits paßt es doch. Compilertechnologie von vor 30 Jahren für 
eine Mikroarchitektur von vor 30 Jahren. Muß man sich schön saufen ;)

PROST!

Und es taugt auch prima als Erklärung, warum die Compiler von MCP
closed source sind. Nix von wegen "was nix kostet, taugt nix" -
die schämen sich einfach. Und zu Recht!


XL

von Holger S. (alberich)


Lesenswert?

Also erst mal muss ich sagen, dass ich hocherfreut war, hier im Forum 
nicht die typischen Grabenkämpfe wiederzufinden. Das legt sich gerade 
wieder ein bisschen.

Aber zum Thema: Ich habe mir trotz der kruden Assemblersyntax der PICs 
den compilierten Code angeschaut, konnte so recht keinen Fehler finden & 
hab mich deshalb noch mal ins Debugging gestürzt. Ergebnis: Ein Fehler 
im I2C-Code hat dazu geführt, dass beim übermitteln der zu lesenden 
Registeradresse der Sensoren zu viele Bytes geschrieben wurden, weshalb 
diese zu Recht auch mal mit Blödsinn geantwortet haben. Beim lesen der 
Device-IDs kamen sie nicht durcheinander, beim Lesen der 
Messwertregister waren sie offensichtlich zimperlicher.
Warum ich, in zig Versuchen nachvollziehbar, das Verhalten mit der 
Anzahl der Shift-Bits steuern konnte, das bleibt wohl erst mal ein 
Geheimnis. Vielleicht wurde das Array der zu sendenden Bytes 
unterschiedlich initialisiert, je nach dem, was man im Code sonst noch 
so treibt. Und sei es nur, das es an einer anderen Stelle im Speicher 
landete. Wenn ich mich von dem Chaos erholt habe, dann schaue ich mir 
das vielleicht noch mal an ;-)

Fazit: XC8 war doch unschuldig und es war auch keine Magie am Werk, 
sondern ein ganz normaler Programmierfehler.

Vielen Dank an alle, die geholfen haben. Alleine wäre ich der falschen 
Fährte sicherlich noch weiter gefolgt - und sorry für diese falsche 
Fährte.

p.S.: Aber mit einem [hier anderen Prozessor einsetzen] wäre das 
sicherlich nicht passiert :-)

von Andreas H. (ahz)


Lesenswert?

Stefan schrieb:
> avr-gcc:
> 474:main.c        ****   unsigned char a=1;
>  475:main.c        ****   int x=(int)a<<6;
>  476:main.c        ****   puts(x);
>  924                 .LM120:
>  925 00b8 80E4          ldi r24,lo8(64)
>  926 00ba 90E0          ldi r25,0
>  927 00bc 00D0          rcall puts

Irgendwie sehe ich da was nicht. Wo ist da die Zeile 475, also der 
LShift um 6 Stellen, als ASM Code ?

Grüße
Andreas

von chris (Gast)


Lesenswert?

constant propaganation.
Da a immer 1 ist, wird X gleich mit 64 geladen, also 1<<64.
Auch der C18 Compiler da gcc macht dasselbe. Ob X8 es mit nicht 
abgeschalteter Optimierung auch macht, mòglicherweise.

von Andreas H. (ahz)


Lesenswert?

chris schrieb:
> Da a immer 1 ist, wird X gleich mit 64 geladen

Ach, das hatte ich übersehen. Dann ist es klar. Danke :-)

Grüße
Andreas

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.