|
Tài trợ cho PIC Vietnam |
dsPIC - Bộ điều khiển tín hiệu số 16-bit Theo dự kiến của Microchip, vào khoảng năm 2011 dsPIC sẽ có doanh số lớn hơn PIC |
|
Ðiều Chỉnh | Xếp Bài |
10-05-2008, 07:35 PM | #1 |
Nhập môn đệ tử
Tham gia ngày: Oct 2007
Bài gửi: 4
: |
Nhờ các bác giải quyết một vấn đề về ngắt
Em sử dụng dsPIC33FJ256GP710 cấu hình hoạt động ở 40MIPS.
Hàm phục vụ ngắt (ngắt ngoài INT4) của em như sau: Code:
void interrupt_int4() org 0x80 { //When ADS is asserted addr_select = PORTA; addr_select &= 0x3F; if (addr_select == 0) { LATD = ADC_1; //ADC_1 LATFbits.LATF0 = 0; //LRDYi active LATFbits.LATF0 = 1; //LRDYi inative } else if (addr_select == 2) { LATD = ADC_2; //ADC_2 LATFbits.LATF0 = 0; //LRDYi active LATFbits.LATF0 = 1; //LRDYi inative } else { LATD = addr_select; LATFbits.LATF0 = 0; //LRDYi active LATFbits.LATF0 = 1; //LRDYi inative } IFS3bits.INT4IF = 0; //ensure interrupt not pending } Tuy nhiên khi viết chương trình với C (MikroC) thì nó tự động push tất cả các thanh ghi làm việc nên mất khá nhiều chu kỳ lệnh: View assembly của chương trình trên ta thấy: Code:
$0200 $ _interrupt_int4: $0200 $F80036 PUSH RCOUNT $0202 $781F80 PUSH W0 $0204 $200020 MOV #2, W0 $0206 $09000C REPEAT #12 $0208 $781FB0 PUSH [W0++] ;INT_TEST.c,15 :: void interrupt_int4() org 0x80 { //When ADS is asserted ;INT_TEST.c,16 :: addr_select = PORTA; $020A $801610 MOV PORTA, W0 $020C $8A2000 MOV W0, _addr_select ;INT_TEST.c,17 :: addr_select &= 0x3F; $020E $2003F1 MOV #63, W1 $0210 $244000 MOV #@_addr_select, W0 $0212 $608090 AND W1, [W0], W1 $0214 $8A2001 MOV W1, _addr_select ;INT_TEST.c,18 :: if (addr_select == 0) $0216 $508060 SUB W1, #0, W0 $0218 $3A000A BRA NZ L_interrupt_int4_0, L_interrupt_int4_0 ;INT_TEST.c,20 :: LATD = ADC_1; //ADC_1 $021A $822010 MOV _ADC_1, W0 $021C $8816B0 MOV W0, LATD ;INT_TEST.c,21 :: LATFbits.LATF0 = 0; //LRDYi active $021E $2FFFE1 MOV #65534, W1 $0220 $202E20 MOV #@LATFbits+0, W0 $0222 $608810 AND W1, [W0], [W0] ;INT_TEST.c,22 :: LATFbits.LATF0 = 1; //LRDYi inative $0224 $200011 MOV #1, W1 $0226 $202E20 MOV #@LATFbits+0, W0 $0228 $708810 IOR W1, [W0], [W0] ;INT_TEST.c,23 :: } $022A $040258 GOTO L_interrupt_int4_1 $022E $ L_interrupt_int4_0: ;INT_TEST.c,24 :: else if (addr_select == 2) $022E $822001 MOV _addr_select, W1 $0230 $508062 SUB W1, #2, W0 $0232 $3A000A BRA NZ L_interrupt_int4_2, L_interrupt_int4_2 ;INT_TEST.c,26 :: LATD = ADC_2; //ADC_2 $0234 $822020 MOV _ADC_2, W0 $0236 $8816B0 MOV W0, LATD ;INT_TEST.c,27 :: LATFbits.LATF0 = 0; //LRDYi active $0238 $2FFFE1 MOV #65534, W1 $023A $202E20 MOV #@LATFbits+0, W0 $023C $608810 AND W1, [W0], [W0] ;INT_TEST.c,28 :: LATFbits.LATF0 = 1; //LRDYi inative $023E $200011 MOV #1, W1 $0240 $202E20 MOV #@LATFbits+0, W0 $0242 $708810 IOR W1, [W0], [W0] ;INT_TEST.c,29 :: } $0244 $040258 GOTO L_interrupt_int4_3 $0248 $ L_interrupt_int4_2: ;INT_TEST.c,32 :: LATD = addr_select; $0248 $822000 MOV _addr_select, W0 $024A $8816B0 MOV W0, LATD ;INT_TEST.c,33 :: LATFbits.LATF0 = 0; //LRDYi active $024C $2FFFE1 MOV #65534, W1 $024E $202E20 MOV #@LATFbits+0, W0 $0250 $608810 AND W1, [W0], [W0] ;INT_TEST.c,34 :: LATFbits.LATF0 = 1; //LRDYi inative $0252 $200011 MOV #1, W1 $0254 $202E20 MOV #@LATFbits+0, W0 $0256 $708810 IOR W1, [W0], [W0] ;INT_TEST.c,35 :: } $0258 $ L_interrupt_int4_3: $0258 $ L_interrupt_int4_1: ;INT_TEST.c,36 :: IFS3bits.INT4IF = 0; //ensure interrupt not pending $0258 $2FFBF1 MOV #65471, W1 $025A $2008A0 MOV #@IFS3bits+0, W0 $025C $608810 AND W1, [W0], [W0] ;INT_TEST.c,37 :: } $025E $ L_end__interrupt_int4: $025E $2001A0 MOV #26, W0 $0260 $09000C REPEAT #12 $0262 $78104F POP [W0--] $0264 $78004F POP W0 $0266 $F90036 POP RCOUNT $0268 $064000 RETFIE vì chương trình của em rất lớn nên nếu chuyển tất cả sang ASM thì không đủ thời gian thực hiện. =>Các bác nào có hướng giải quyết nào hay giúp em với. |
|
|