|
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. |
11-05-2008, 12:19 PM | #2 |
Nhập môn đệ tử
Tham gia ngày: Oct 2007
Bài gửi: 4
: |
Vấn đề ngắt tiếp theo ...
Cũng với chương trình ngắt phía trên:
+Khai báo biến toàn cục: Code:
unsigned int ADC_1; unsigned int ADC_2; 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 } else if (addr_select == 2) { LATD = ADC_2; //ADC_2 } else { LATD = addr_select; } IFS3bits.INT4IF = 0; //ensure interrupt not pending } ví dụ: Code:
ADC_1 = 0xAA; ADC_2 = 0xBB; Vấn đề ở đây là gì ??? Các bác giúp em với |
12-05-2008, 12:59 AM | #3 | |
Trưởng lão PIC bang
|
Trích:
Bạn cũng có thể viết các đoạn code/chương trình con bằng hợp ngữ và truy xuất chúng từ C. Theo tôi, mikroC for dsPIC chỉ dùng để làm quen với PIC24/dsPIC thôi, còn viết code cho các project nghiêm túc thì không nên dùng. Thân,
__________________
Biển học mênh mông, sức người có hạn. Đang gặp vấn đề cần được giúp đỡ? Hãy dành ra vài phút đọc luồng sau: http://www.picvietnam.com/forum/showthread.php?t=1263 |
|
12-05-2008, 01:05 AM | #4 | |
Trưởng lão PIC bang
|
Trích:
Theo tôi thì nên dùng switch case thay cho các if lồng nhau. Thân,
__________________
Biển học mênh mông, sức người có hạn. Đang gặp vấn đề cần được giúp đỡ? Hãy dành ra vài phút đọc luồng sau: http://www.picvietnam.com/forum/showthread.php?t=1263 |
|
12-05-2008, 12:04 PM | #5 |
Nhập môn đệ tử
Tham gia ngày: Oct 2007
Bài gửi: 4
: |
Cám ơn anh Nam đã giúp đỡ !!! .Em sẽ nghiên cứu để chuyển sang C30.
Về vấn đề hàm ngắt INT4: -Ban đầu khi em chưa sử dụng biến ADC_1 và ADC_2 mà đưa luôn giá trị ra PORTD: Code:
void interrupt_int4() org 0x80 { //When ADS is asserted addr_select = PORTA; addr_select &= 0x3F; if (addr_select == 0) { LATD = 0xAA; } else if (addr_select == 2) { LATD = 0xBB; } else { LATD = addr_select; } IFS3bits.INT4IF = 0; //ensure interrupt not pending } Vấn đề ở đây có lẽ là do cách mình khai báo biến: Code:
unsigned int ADC_1; unsigned int ADC_2; 1>Liệu có sự thay đổi nào của ADC_1 và ADC_2 khi nhảy vào trong hàm ngắt 2>cách gán giá trị trong hàm ngắt như sau có vấn đề: Code:
LATD = ADC_1; LATD = ADC_2; |
13-05-2008, 05:43 AM | #6 |
Trưởng lão PIC bang
|
Ở post #2 bạn đặt các giá trị hằng số vào ADC_1 và ADC_2 và cho biết kết quả không đúng khi có ngắt ngoài, nhưng ở post #4 bạn lại cho biết giá trị của ADC_1 và ADC_2 có được từ việc chuyển đổi A/D. Liệu có khả năng khi bạn thử đặt các giá trị 0xAA và 0xBB vào ADC_1 và ADC_2 thì thao tác chuyển đổi A/D lại ghi các giá trị khác vào ADC_1 và ADC_2 hay không?
Bạn tham khảo ví dụ 5.1 trong tutorial 5 cho dsPIC của tôi. Tôi đã dùng đúng cách mà bạn đang dùng để đọc ngõ vào analog và cập nhật các thanh ghi PDC bằng kết quả chuyển đổi A/D. Tôi cũng dùng biến unsigned int, và không hề có điều gì bất thường xảy ra. Thân,
__________________
Biển học mênh mông, sức người có hạn. Đang gặp vấn đề cần được giúp đỡ? Hãy dành ra vài phút đọc luồng sau: http://www.picvietnam.com/forum/showthread.php?t=1263 |
14-05-2008, 12:14 AM | #7 |
Nhập môn đệ tử
Tham gia ngày: Oct 2007
Bài gửi: 4
: |
Cảm ơn anh Nam đã giúp đỡ.
Em đã giải quyết được vấn đề ngắt này,và chỉnh lại code cho hợp lý: Code:
//--- External Interrupt routine (INT4 - ADS)--- void interrupt_int4() org 0x80 { //When ADS is asserted addr_select = PORTA; addr_select &= 0x3F; switch (addr_select) { case 0: LATD = ADC_1; break; case 2: LATD = ADC_2; break; default: LATD = 0xDD; } IFS3bits.INT4IF = 0; //ensure interrupt not pending } (Ở phía trên em cho ADC_1 = 0xAA và ADC_2 = 0xBB chỉ là để test ) Vấn đề của em là do tín hiệu ngắt ngoài được lấy từ PC,dữ liệu cũng được truyền về PC (và còn một số vấn đề khác của phần cứng)nên ban đầu ko rõ nguyên nhân.Vì tín hiệu ngắt ngoài ko ổn định nên giá trị nhận được ko chinh xác.Còn lại hàm ngắt và chuyển đổi ADC ko có vấn đề gì. thay đổi nội dung bởi: hanhthien184, 14-05-2008 lúc 12:20 AM. |
|
|