PIC16, C, läsa av byte

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
persika
EF Sponsor
Inlägg: 1541
Blev medlem: 31 juli 2006, 22:14:37
Ort: Österlen, Skåne

PIC16, C, läsa av byte

Inlägg av persika »

PIC16F690, Hitech C, MPLAB 8.88

Jag vill ha en 24 bitsvariabel utan tecken
Sen vill jag kunna läsa av den högsta byten av de tre.

Kod: Markera allt


typedef short long uint24; 	// typ för 24 bits variabel utan tecken
uint24 A24; 		// 24 bits variabel utan tecken

typedef unsigned char uint8; // typ för 8 bits variabel utan tecken

typedef uint8 ArrTyp8x3[3];	// typ för array med 3 st 8 bitsvariabler utan tecken

uint8 A8;

void main(void)
{
init();

// test
A24= 393216;	// = 6*256*256
A8 = (ArrTyp8x3)A24[2];  // tänkte att A8 ska få värdet 6 här, men funkar inte, felmeddelande: pointer required
}
Zeela
Inlägg: 176
Blev medlem: 28 augusti 2008, 11:23:49
Ort: Åtvidaberg
Kontakt:

Re: PIC16, C, läsa av byte

Inlägg av Zeela »

Prova om detta kan fungera... Helt ur huvudet utan C kompilator att testa med :)

Kod: Markera allt

A8 = ((ArrTyp8x3)&A24)[2]
johano
Inlägg: 1943
Blev medlem: 22 januari 2008, 10:07:45
Ort: Stockholm

Re: PIC16, C, läsa av byte

Inlägg av johano »

Enkelt med en shift istället:

Kod: Markera allt

A8 = A24 >> 16;
/j
Användarvisningsbild
kimmen
Inlägg: 2042
Blev medlem: 25 augusti 2007, 16:53:51
Ort: Stockholm (Kista)

Re: PIC16, C, läsa av byte

Inlägg av kimmen »

Om du vill läsa ut de mest signifikanta 8 bitarna utan att behöva bekymra dig över endianness och huruvida det är okej med aliasing på det där sättet skulle jag föreslå:

Kod: Markera allt

A8 = A24 >> 16;
vilket inte gör några antaganden om endianness eller något annat. Eller för att få alla de tre olika delarna

Kod: Markera allt

uint8_t high, mid, low;
high = A24 >> 16;
mid = A24 >> 8;
low = A24;
Användarvisningsbild
Icecap
Inlägg: 26650
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: PIC16, C, läsa av byte

Inlägg av Icecap »

Ett trick som INTE är överförbart mellan olika endian är följande:

Kod: Markera allt

union
  {
  unsigned long Dword;
  unsigned char Byte[4];
  } A;
Då är A.Byte[3] samma som högsta byten av A.Dword.
Användarvisningsbild
persika
EF Sponsor
Inlägg: 1541
Blev medlem: 31 juli 2006, 22:14:37
Ort: Österlen, Skåne

Re: PIC16, C, läsa av byte

Inlägg av persika »

Zeela> Prova om detta kan fungera... Helt ur huvudet utan C kompilator att testa med

Kod: Markera allt

A8 = ((ArrTyp8x3)&A24)[2]
Tyvärr funkade det inte, felmeddelande: "cast type must be scalar or void"


Efter en del letande på internet om pekare och en del experimenterande fick jag till det med:

Kod: Markera allt

A8 = ((uint8*)&A24)[2];
Jag hittade en pdf om pekare, inte precis om ovanstående problem, men bra info ändå:
http://hem.hj.se/~aran/Systemkonstrukti ... re_Ted.pdf
Zeela
Inlägg: 176
Blev medlem: 28 augusti 2008, 11:23:49
Ort: Åtvidaberg
Kontakt:

Re: Sv: PIC16, C, läsa av byte

Inlägg av Zeela »

Det var ju så jag menade :)
Användarvisningsbild
SeniorLemuren
Inlägg: 8427
Blev medlem: 26 maj 2009, 12:20:37
Ort: Kristinehamn

Re: PIC16, C, läsa av byte

Inlägg av SeniorLemuren »

Måste lite nyfiket fråga varför man krånglar till så ini bomben i stället för att använda den enkla lösningen med shift?
Användarvisningsbild
AndLi
Inlägg: 18282
Blev medlem: 11 februari 2004, 18:17:59
Ort: Knivsta
Kontakt:

Re: PIC16, C, läsa av byte

Inlägg av AndLi »

Jag skulle vilja se lite listfiler, så man kan avgöra vilket som blir effektivast...
Användarvisningsbild
kimmen
Inlägg: 2042
Blev medlem: 25 augusti 2007, 16:53:51
Ort: Stockholm (Kista)

Re: PIC16, C, läsa av byte

Inlägg av kimmen »

SeniorLemuren skrev:Måste lite nyfiket fråga varför man krånglar till så ini bomben i stället för att använda den enkla lösningen med shift?
Särskilt med tanke på att andra varianter är icke-standard.
I en modern kompilator med optimering påslagen borde det inte bli någon större skillnad i prestanda, om det ens blir någon skillnad på koden som genereras över huvud taget.
Användarvisningsbild
persika
EF Sponsor
Inlägg: 1541
Blev medlem: 31 juli 2006, 22:14:37
Ort: Österlen, Skåne

Re: PIC16, C, läsa av byte

Inlägg av persika »

Jag har provat, i PIC16F690 MPLAB/Hitech C (gratisversionen) tar det

6 cykler för:
A8 = ((uint8*)&A24)[2];

Det tar 123 cykler för:
A8 = A24 >> 16;

Så om man har bråttom kan det ha betydelse, annars är ju det senare alternativet mycket snyggare kod.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: PIC16, C, läsa av byte

Inlägg av sodjan »

Hur ser koden ut och vad avses med "cykler" ?
Användarvisningsbild
SeniorLemuren
Inlägg: 8427
Blev medlem: 26 maj 2009, 12:20:37
Ort: Kristinehamn

Re: PIC16, C, läsa av byte

Inlägg av SeniorLemuren »

Jag vet inte hur man definierar en 3 byte variabel i mikroC, men så här ser asm-filen ut när jag kompilerar en 32-bitars variabel med skift 16. µC PIC18F4550.

Kod: Markera allt

_main:

;skifttest.c,4 ::                 void main() {
;skifttest.c,5 ::                 A8 = A32 >> 24 ;
        MOVF        _A32+3, 0 
        MOVWF       R0 
        CLRF        R1 
        CLRF        R2 
        CLRF        R3 
        MOVF        R0, 0 
        MOVWF       _A8+0 
;skifttest.c,6 ::                 }
L_end_main:
        GOTO        $+0
; end of _main
Användarvisningsbild
persika
EF Sponsor
Inlägg: 1541
Blev medlem: 31 juli 2006, 22:14:37
Ort: Österlen, Skåne

Re: PIC16, C, läsa av byte

Inlägg av persika »

Så här ser C-koden ut:

Kod: Markera allt


typedef short long uint24; // 24 bits variabel utan tecken 
uint24 A24; 

typedef unsigned char uint8; // 8 bits variabel utan tecken
uint8 A8;



//-----------------main----------------------------
void main(void)
{

A24 = 393216; // = 6 * 256 * 256

A8 = ((uint8*)&A24)[2];

A8 = A24 >> 16;

A8 = A24 / 65536;
}
//-----------------main----------------------------
Jag lade även till en division, som också kan lösa uppgiften.
Med cykler menade jag instruktionscykler, avläst i Stoppwatch i MPLAB.
Förra gången har jag kanske tryckt fel på nåt vis, nu fick jag:

A8 = ((uint8*)&A24)[2]; // 4 instruktionscykler
A8 = A24 >> 16; // 123 instruktionscykler
A8 = A24 / 65536; // 1019 instruktionscykler

Här är list-fil från Hitech-C, det aktuella avsnittet:

Kod: Markera allt

   211 ;; *************** function _main *****************
   212 ;; Defined at:
   213 ;;		line 23 in file "P:\PROGRAM\pic\test\testA24A8.c"
   214 ;; Parameters:    Size  Location     Type
   215 ;;		None
   216 ;; Auto vars:     Size  Location     Type
   217 ;;		None
   218 ;; Return value:  Size  Location     Type
   219 ;;		None               void
   220 ;; Registers used:
   221 ;;		wreg, status,2, status,0, pclath, cstack
   222 ;; Tracked objects:
   223 ;;		On entry : 17F/0
   224 ;;		On exit  : 0/0
   225 ;;		Unchanged: 0/0
   226 ;; Data sizes:     COMMON   BANK0   BANK1   BANK2
   227 ;;      Params:         0       0       0       0
   228 ;;      Locals:         0       0       0       0
   229 ;;      Temps:          5       0       0       0
   230 ;;      Totals:         5       0       0       0
   231 ;;Total ram usage:        5 bytes
   232 ;; Hardware stack levels required when called:    1
   233 ;; This function calls:
   234 ;;		___aldiv
   235 ;; This function is called by:
   236 ;;		Startup code after reset
   237 ;; This function uses a non-reentrant model
   238 ;;
   239                           psect	maintext
   240                           	file	"P:\PROGRAM\pic\test\testA24A8.c"
   241                           	line	23
   242                           	global	__size_of_main
   243  003F                     	__size_of_main	equ	__end_of_main-_main
   244                           	
   245  0719                     _main:	
   246                           	opt	stack 7
   247                           ; Regs used in _main: [wreg+status,2+status,0+pclath+cstack]
   248                           	line	25
   249                           	
   250  0719                     l3040:	
   251                           ;testA24A8.c: 25: A24 = 393216;
   252  0719  3000               	movlw	0
   253  071A  1283               	bcf	status, 5	;RP0=0, select bank0
   254  071B  1303               	bcf	status, 6	;RP1=0, select bank0
   255  071C  00A6               	movwf	(_A24)
   256  071D  3000               	movlw	0
   257  071E  00A7               	movwf	(_A24+1)
   258  071F  3006               	movlw	06h
   259  0720  00A8               	movwf	(_A24+2)
   260                           	line	27
   261                           ;testA24A8.c: 27: A8 = ((uint8*)&A24)[2];
   262  0721  0828               	movf	0+(_A24)+02h,w
   263  0722  00F9               	movwf	(??_main+0)+0
   264  0723  0879               	movf	(??_main+0)+0,w
   265  0724  00A9               	movwf	(_A8)
   266                           	line	29
   267                           	
   268  0725                     l3042:	
   269                           ;testA24A8.c: 29: A8 = A24 >> 16;
   270  0725  0826               	movf	(_A24),w
   271  0726  00F9               	movwf	((??_main+0)+0)
   272  0727  0827               	movf	(_A24+1),w
   273  0728  00FA               	movwf	((??_main+0)+0+1)
   274  0729  0828               	movf	(_A24+2),w
   275  072A  00FB               	movwf	((??_main+0)+0+2)
   276  072B  3010               	movlw	010h
   277  072C  00FC               	movwf	(??_main+3)+0
   278  072D                     u2335:
   279  072D  0D7B               	rlf	(??_main+0)+2,w
   280  072E  0CFB               	rrf	(??_main+0)+2,f
   281  072F  0CFA               	rrf	(??_main+0)+1,f
   282  0730  0CF9               	rrf	(??_main+0)+0,f
   283  0731                     u2330:
   284  0731  0BFC               	decfsz	(??_main+3)+0,f
   285  0732  2F2D               	goto	u2335
   286  0733  0879               	movf	0+(??_main+0)+0,w
   287  0734  00FD               	movwf	(??_main+4)+0
   288  0735  087D               	movf	(??_main+4)+0,w
   289  0736  00A9               	movwf	(_A8)
   290                           	line	31
   291                           	
   292  0737                     l3044:	
   293                           ;testA24A8.c: 31: A8 = A24 / 65536;
   294  0737  3000               	movlw	0
   295  0738  00F3               	movwf	(?___aldiv+3)
   296  0739  3001               	movlw	01h
   297  073A  00F2               	movwf	(?___aldiv+2)
   298  073B  3000               	movlw	0
   299  073C  00F1               	movwf	(?___aldiv+1)
   300  073D  3000               	movlw	0
   301  073E  00F0               	movwf	(?___aldiv)
   302                           
   303  073F  0826               	movf	(_A24),w
   304  0740  00F4               	movwf	0+(?___aldiv)+04h
   305  0741  0827               	movf	(_A24+1),w
   306  0742  00F5               	movwf	1+(?___aldiv)+04h
   307  0743  0828               	movf	(_A24+2),w
   308  0744  00F6               	movwf	2+(?___aldiv)+04h
   309  0745  00F9               	movwf	(??_main+0)+0
   310  0746  0D79               	rlf	(??_main+0)+0,w
   311  0747  00F9               	movwf	(??_main+0)+0
   312  0748  1C03               	skipc
   313  0749  03F9               	decf	(??_main+0)+0,f
   314  074A  02F9               	subwf	(??_main+0)+0,f
   315  074B  0979               	comf	(??_main+0)+0,w
   316  074C  00F7               	movwf	3+(?___aldiv)+04h
   317  074D  118A  2758  118A   	fcall	___aldiv
   318  0750  0870               	movf	0+(((0+(?___aldiv)))),w
   319  0751  00FA               	movwf	(??_main+1)+0
   320  0752  087A               	movf	(??_main+1)+0,w
   321  0753  1283               	bcf	status, 5	;RP0=0, select bank0
   322  0754  1303               	bcf	status, 6	;RP1=0, select bank0
   323  0755  00A9               	movwf	(_A8)
   324                           	line	32
   325                           	
   326  0756                     l891:	
   327                           	global	start
   328  0756  118A  2800         	ljmp	start
   329                           	opt stack 0
   330                           GLOBAL	__end_of_main
   331  0758                     	__end_of_main:
   332 ;; =============== function _main ends ============
Användarvisningsbild
Icecap
Inlägg: 26650
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: PIC16, C, läsa av byte

Inlägg av Icecap »

Mycket av detta beror på valda optimeringsnivåer och kompilerns "kvalitet" så det är inte alltid lika enkelt att ge klara svar på vad som är bäst.
Skriv svar