Sida 1 av 2
PIC16, C, läsa av byte
Postat: 27 maj 2013, 08:56:41
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
}
Re: PIC16, C, läsa av byte
Postat: 27 maj 2013, 09:02:00
av Zeela
Prova om detta kan fungera... Helt ur huvudet utan C kompilator att testa med
Re: PIC16, C, läsa av byte
Postat: 27 maj 2013, 09:56:17
av johano
Enkelt med en shift istället:
/j
Re: PIC16, C, läsa av byte
Postat: 27 maj 2013, 10:01:15
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å:
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;
Re: PIC16, C, läsa av byte
Postat: 27 maj 2013, 12:18:07
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.
Re: PIC16, C, läsa av byte
Postat: 27 maj 2013, 21:56:53
av persika
Zeela> Prova om detta kan fungera... Helt ur huvudet utan C kompilator att testa med
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:
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
Re: Sv: PIC16, C, läsa av byte
Postat: 27 maj 2013, 22:18:26
av Zeela
Det var ju så jag menade

Re: PIC16, C, läsa av byte
Postat: 28 maj 2013, 08:20:01
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?
Re: PIC16, C, läsa av byte
Postat: 28 maj 2013, 08:30:58
av AndLi
Jag skulle vilja se lite listfiler, så man kan avgöra vilket som blir effektivast...
Re: PIC16, C, läsa av byte
Postat: 28 maj 2013, 10:22:27
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.
Re: PIC16, C, läsa av byte
Postat: 28 maj 2013, 12:09:10
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.
Re: PIC16, C, läsa av byte
Postat: 28 maj 2013, 12:39:45
av sodjan
Hur ser koden ut och vad avses med "cykler" ?
Re: PIC16, C, läsa av byte
Postat: 28 maj 2013, 12:52:53
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
Re: PIC16, C, läsa av byte
Postat: 28 maj 2013, 13:49:47
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 ============
Re: PIC16, C, läsa av byte
Postat: 28 maj 2013, 13:58:06
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.