|
Tài trợ cho PIC Vietnam |
Lỗi lập trình ngôn ngữ cấp cao Những lỗi trường gặp trong lập trình. Khóa luồng khi bug được lỗi. |
|
Ðiều Chỉnh | Xếp Bài |
21-08-2008, 12:23 AM | #1 |
Nhập môn đệ tử
Tham gia ngày: Apr 2008
Bài gửi: 6
: |
Lỗi không ngắt được trong CCS
Mình viết Ct điều khiển động cơ bước từ máy tính. Cụ thể là điều khiển 1 mâm quay, trên hành trình mâm có công tắc giới hạn, nối vào portB. Cấu trúc ct như sau:
- Phần khai báo biến, mức ưu tiên, RS232... - Các hàm phát xung cho động cơ (dùng delay_us trong CCS). - Hàm phục vụ ngắt nối tiếp (INT_RDA): báo ngắt khi có kí tự gởi xuống, ứng với mỗi kí tự thì gọi hàm phát xung tương ứng - Hàm phục vụ ngắt PortB (INT_RB): khi công tắc báo ngắt thì gọi hàm phát xung. Ý định của mình là khi gửi kí tự A chẳng hạn, hàm ngắt RDA cho mâm quay trái, gặp công tắc thì hàm ngắt RB cho dừng, delay 1s rồi quay ngược lại 1 góc nào đó. Mình đã test thử từng phần riêng, là gửi A thì mâm quay trái tốt, tác động bằng tay lên công tắc thì mâm quay ngược lại tốt, nghĩa là đáp ứng ngắt tốt. Nhưng khi đang quay trái mà gặp công tắc thì không ngắt được. phải đến khi thực hiện hết quay trái của ngắt RDA, nếu t/h ngắt RB còn thì nó mới thực hiện ngắt RB. Lưu ý là mình đã đặt mức ưu tiên ngắt RB cao hơn RDA rồi. Ở đây mình phán đoán nó bị lỗi như giống như trường hợp cảnh báo "Warning 216 : Interrupts disable during call to prevent re_entrancy:tên hàm" lỗi này hình như là 1 ngắt có dùng các hàm delay_us, delay_ms mà ở ngoài cũng có 1 hàm delay này đang chạy thì ngắt sẽ bị disable? Đây là link trên CCSInfo, do trình độ AV có hạn nên mình ko hiểu nhiều lắm: http://www.ccsinfo.com/forum/viewtop...er=asc&start=0 Trường hợp của mình là đều dùng Delay_us trong cả 2 ngắt. Mình chỉ là newbie với PIC, ai có kinh nghiệm có thể giúp mình khắc phục không? |
21-08-2008, 12:36 AM | #2 |
Super Moderator
Tham gia ngày: Feb 2006
Bài gửi: 150
: |
Bạn có thể post code lên được không, có thể sẽ dễ giải quyết vấn đề hơn, chú ý là ngắt INT_RB là ngắt on change, xử lý không tốt ở đây cũng nảy sinh vấn đề rồi.
|
21-08-2008, 02:01 AM | #3 |
Nhập môn đệ tử
Tham gia ngày: Apr 2008
Bài gửi: 6
: |
Ct của mình dùng đk 1 tay máy 3 trục dùng 3 đcơ bước nên nó dài dòng quá, ban đầu post lên sợ ko ai đọc.
Mình tóm tắt là có 3 motor bước, mỗi cái quay 1 trục, trên hành trình có gắn 3 ctắc để set vị trí home, ctắc nối vào chân ngắt của RB. Giao tiếp RS232 báo ngắt khi bộ đệm nhận dữ liệu đầy. Hoạt động: gửi 1 kí tự xuống PIC thì ngắt nối tiếp RDA gọi hàm quay động cơ tương ứng. Gửi kí tự "O" thì ngắt RDA đk 3 trục về vtrí home, bằng cách là khi mỗi trục gặp ctắc, hàm ngắt RB đặt mức ưu tiên cao hơn sẽ ngắt hàm RDA, cho dừng và quay 3 trục về home. Vấn đề ở đây là ngắt RB ko ngắt đc hàm RDA đang thực thi, nên 3 động cơ không dừng như mong muốn. Nếu ngắt RDA ko chạy thì ngắt RB vẫn hoạt động tốt. Mình cũng thử là cho RB ngắt khi chạy phát xung ngoài hàm main, thì vẫn ko ngắt đc. Trình dịch cảnh báo Warning 216 như mình nói. đây là code, mọi ngừoi chịu khó xem giúp mình: Code:
#include <16F877A.h> #fuses HS,NOWDT,NOPROTECT,NOLVP #use delay(clock=20000000) #use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7) #priority rb,rda #byte porta=0x05 #byte portb=0x06 #byte portd=0x08 #bit catch=porta.3 // ngo ra nam cham #bit clock1=porta.2 // Step motor 1 #bit en_step1=porta.1 #bit dir1=porta.0 #bit clock2=portd.7 // step motor 2 #bit en_step2=portd.6 #bit dir2=portd.5 #bit en_step3=portd.3 // step motor 3 #bit dir3=portd.2 #bit clock3=portd.1 int count1; // bien dem so xung motor1 int16 count2,count3; // motor2 va 3 char ss; void rotate_high1() // ham phat xung cho motor 1 { // quay toc do cao clock1=1; delay_us(30000); clock1=0; delay_us(500); } void rotate_low1() // motor 1 toc do thap { clock1=1; delay_us(50000); clock1=0; delay_us(500); } void rotate_high2() { clock2=1; delay_us(1000); clock2=0; delay_us(100); } void rotate_low2() { clock2=1; delay_us(2000); clock2=0; delay_us(100); } void rotate3() { clock3=1; delay_us(700); clock3=0; delay_us(100); } //************************************************** void left_right() // ham quay motor 1 { int tam; tam=count1; en_step1=1; while (count1>0) { count1--; if ((count1>30)&&(count1<(tam-30))) { rotate_high1(); } else { rotate_low1(); } } count1=0; delay_ms(500); } //**************************************************** void go_up_down() // ham quay motor 2 { en_step2=1; while (count2>0) { count2--; if (dir2==0) { rotate_low2(); } else { rotate_high2(); } } count2=0; delay_ms(500); en_step2=0; } //***************************************************** void in_out() // ham quay motor 3 { en_step3=1; while (count3>0) { count3--; rotate3(); } delay_ms(1000); en_step3=0; count3=0; } //******************************************************* #int_RB void rb_isr() // ham phuc vu ngat RB { int current; int last; set_tris_b(0xff); current=input_b(); last=current; delay_ms(50); set_tris_b(0xff); current=input_b(); if (current==last) { clear_interrupt(int_RDA); if (!bit_test(current,4)) // ctac tren mam xoay bao ngat { if (home) // chi thuc hien khi o che do home: { // quay mam ben phai 60 do en_step1=0; count1=70; dir1=1; en_step1=1; while (count1>0) { count1--; if ((count1>30)&&(count1<(70-30))) { rotate_high1(); } else { rotate_low1(); } } count1=0; } } if (!bit_test(current,5)) // ctac trong bao ngat { en_step3=0; delay_ms(500); count3=2000; dir3=0; in_out(); } if (!bit_test(current,6)) //ctac tren bao ngat { en_step2=0; delay_ms(500); count2=500; dir2=1; go_up_down(); count2=0; } if (!bit_test(current,7)) // cam bien phat hien co vat den { putc('y'); delay_ms(10); } } clear_interrupt(int_RB); } //**************************************************************** #int_RDA // ham phuc vu ngat noi tiep void RDA_isr() { delay_us(50); ss=getc(); if (ss=='u') // di len { count2=2000; dir2=0; go_up_down(); printf("done"); } if (ss=='d') // di xuong { count2=2000; dir2=1; go_up_down(); printf("done"); } if (ss=='l') // quay trai { count1=70; //1 lan quay 60 do dir1=0; left_right(); printf("done"); } if (ss=='r') // quay phai { count1=70; dir1=1; left_right(); printf("done"); } if (ss=='i') //di vao { count3=4000; //1 lan di chuyen 30mm dir3=1; in_out(); printf("done"); } if (ss=='o') // di ra { count3=4000; dir3=0; in_out(); printf("done"); } if (ss=='#') // test comm { putc('!'); delay_us(100); } if (ss=='O') // go home: dieu khien tay may { // ve vi tri home home=1; count1=100; dir1=0; left_right(); count2=2000; dir2=0; go_up_down(); count3=2666; dir3=1; in_out(); home=0; } if (ss=='1') // chuong trinh di chuyen cho vat 1 { count2=10000; // chay xuong dir2=1; go_up_down(); catch=1; // gap vat count2=10000; // di len dir2=0; go_up_down(); count1=102; // xoay 90 do dir1=1; left_right(); count3=13333; // di ra dir3=0; in_out(); count2=10000; // ha xuong dir2=1; go_up_down(); catch=0; // nha vat count2=10000; // di len dir2=0; go_up_down(); count1=102; // xoay 90 do dir1=0; left_right(); count3=13333; // di vao dir3=1; in_out(); } clear_interrupt(int_rda); } void main() { enable_interrupts(INT_RB|H_TO_L); enable_interrupts(GLOBAL); ext_int_edge(H_TO_L); enable_interrupts(INT_RDA); set_tris_d(0x00); set_tris_b(0xff); set_tris_a(0x00); printf("reset"); while (1) { } } thay đổi nội dung bởi: bazooka2006, 21-08-2008 lúc 02:07 AM. |
21-08-2008, 11:44 AM | #4 | |
Super Moderator
Tham gia ngày: Feb 2006
Bài gửi: 150
: |
Trích:
PHP Code:
PHP Code:
|
|
21-08-2008, 02:48 PM | #5 | ||
Nhập môn đệ tử
Tham gia ngày: Apr 2008
Bài gửi: 6
: |
Trích:
Trích:
|
||
21-08-2008, 03:29 PM | #6 | |
Super Moderator
Tham gia ngày: Feb 2006
Bài gửi: 150
: |
Trích:
PHP Code:
|
|
08-09-2008, 02:59 PM | #7 |
Nhập môn đệ tử
Tham gia ngày: Oct 2007
Bài gửi: 9
: |
code trên không sai nhưng ccsc sai mấy ông mở cái set 16f877a.h ra và coi có set đúng
hay khong tôi từng bị cái này với 16f887.h rồi hầu như ngát RB sai cả sửa lai code theo 16f877a.h thì ok, => phien bản của các cong cụ lạp trình cấp cao chưa chăc hoản toàn đúng ==> khong tin thì sài 16f887 bien dịch mọi phien bản ccsc khác nhau = không chạy RB nếu khong sủa lại 16f887.h |
17-05-2010, 06:28 AM | #8 |
Nhập môn đệ tử
Tham gia ngày: Jul 2009
Bài gửi: 8
: |
mình đang gặp lỗi tương tự như trên. Không thể dùng ngắt rb và Rda trong cùng chương trình. Khi bỏ hoàn toàn ngắt rb thì chương trình chạy bình thường, còn khi thêm vào thì lại không chạy được. Ai đã giải quyết được vấn đề này xin giúp đỡ mình
|
27-05-2010, 05:51 PM | #9 |
Nhập môn đệ tử
Tham gia ngày: Oct 2008
Bài gửi: 4
: |
mình dùng ngắt và hàm delay cùng lúc không được. mình lập trình bằng CCS
dùng ngắt timer.Khi có cả delay và timer thì chỉ có "ngắt" chạy còn delay thì hoạt đông không chính xác. Delay_ms(2000) mà đợi tới cả chục giây mới có. Bạn nào biết nguyên nhân không và xin cho cách khắc phục vấn đề trên ( mình muốn dùng cả 2 delay và ngắt timer ). Thanks |
28-05-2010, 01:18 AM | #10 |
Đệ tử 1 túi
Tham gia ngày: Jul 2009
Bài gửi: 11
: |
Mình cũng đang viết 1 chương trình điều khiển động cơ 1 chiều, dữ liệu được nhập từ máy tính. Trong chương trình có dùng 3 ngắt là RDA, RB0 và ngắt của timer1 để tạo chu kỳ trích mẫu.
Có điều đáng nói là khi chạy thì chương trình thường bị treo sau khoảng 1-2s. Mình nghĩ là có xung đột về ngắt nên đã disable ngắt RDA sau khi nhận được dữ liệu từ máy tính. Và quả thật sau khi disable thì chương trình chạy ngon. Tuy nhiên, khi đang chạy mà muốn truyền thêm dữ liệu từ PC xuống để thay đổi các thông số thì lại ko được (Vì đã disable ngắt RDA). Mình đã thử nhiều cách nhưng vẫn không thay đổi được gì. Mong mọi người cho ý kiến để cải thiện chương trình của mình. Thanks. Sau đây là chương trình của mình: Code:
#include <16f877a.h> #include <def_877a.h> #include <stdlib.h> #fuses NOWDT, HS, NOPUT, NOPROTECT, NODEBUG, NOBROWNOUT, NOLVP, NOCPD, NOWRT #use delay(clock=20000000) #use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8) #include <lcd_lib_4bit.c> void ht(int16 a); void init(); void pid(); void nhapheso(); void display(int16 n); void truyen(); int16 count=0, tocdo=0, C, temp, temp1, k, tocdodat ; signed int16 e2=0; signed int16 e1=0; int16 e_sum=0; int16 e_del=0; int16 duty=0; float Kp=0; float Ki=0; float Kd=0; int flag=0; float u, T=0.01; unsigned char text[30], text2[5] ; unsigned char a1[5], dem=0, i=0, j=0,i1=0; #INT_RDA void Receive_isr() { text[dem]=getc(); if(text[dem]=='@') //kiem tra dieu kien ket thuc { flag =1; //ket thuc nhan, bat co bao dem=0; } else dem++; } #INT_EXT void ngatR0() { count++;//set_timer0(0); } #int_timer1 void Timer11_isr() { // Ham duoc goi khi TImer1 tran (65535->0) set_timer1(53036); tocdo= 30*(count + get_timer0()); // printf("%ld\t",tocdo); count = 0; set_timer0(0); } void main(){ init(); lcd_putcmd(0x01); while(true){ truyen(); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// pid(); if(RC1==0) set_PWM1_duty(duty); if(RC1==1) set_PWM1_duty(1023 - duty); lcd_putcmd(0x80); ht(tocdo); printf("n%4Lu",tocdo); display(tocdo); //lcd_putchar("hi"); } } void init() { lcd_init(); nhapheso(); setup_timer_0 (RTCC_DIV_1|RTCC_EXT_L_TO_H); // Timer0 is Counter setup_timer_1(T1_INTERNAL | T1_DIV_BY_4); setup_ccp1(CCP_PWM); setup_timer_2(T2_DIV_BY_4, 255, 1);//4*4*256*1/20000000=204.8us=4.8khz set_timer0(0); set_timer1(53036); enable_interrupts(INT_RTCC); enable_interrupts(int_timer1); enable_interrupts(int_ext); ext_int_edge(L_TO_H); enable_interrupts(GLOBAL); lcd_putcmd(0x80); count=0; trisc=0; trisd=0; trisa=255; trisb=1; } void pid(){ e2 = tocdodat - tocdo; e_sum += e2; // e_del = e2 - e1; // e1 = e2; u = u + Kp*e2 + Ki*e_sum*T; if (u>24){ u=24; e_sum -=e2; } if (u<0){ u = 0; e_sum -=e2; } duty = u*1023/24; } void ht(long a) { int nghin,tram,chuc,dvi; nghin=a/1000; tram=(a%1000)/100; chuc=(a%100)/10; dvi=(a%10); lcd_putchar(nghin+48); lcd_putchar(tram+48); lcd_putchar(chuc+48); lcd_putchar(dvi+48); } void nhapheso(){ lcd_putchar("nhap tu PC"); enable_interrupts(int_rda); enable_interrupts(GLOBAL); while(!flag) ; } void truyen() { enable_interrupts(int_rda); enable_interrupts(GLOBAL); if(flag){ //if ((strchr(text,'T')) && (strrchr(text, '@'))) text2[0] = text[0]; text2[1] = text[1]; text2[2] = text[2]; text2[3] = text[3]; text2[4] = text[4]; tocdodat = atol(text2); //---------------------------------------- while (text[i] != 'P') i++; while (text[j] != 'I') j++; i1 = i; temp = j - i; for (i = 0; i < temp; i++) a1[i] = text[i1 + i + 1]; Kp = atof(a1); printf("P%f",Kp); delay_ms(100); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// i = j; while (text[j] != 'D') j++; i1 = i; temp = j - i; for (i = 0; i < temp; i++) a1[i] = text[i1 + i + 1]; Ki = atof(a1); printf("I%f",Ki); delay_ms(100); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// i = j; while (text[j] != 'C') j++; i1 = i; temp = j - i; for (i = 0; i < temp; i++) a1[i] = text[i1 + i + 1]; Kd = atof(a1); printf("D%f",Kd); delay_ms(100); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// i = j; while (text[j] != '@') j++; i1 = i; temp = j - i; for (i = 0; i < temp; i++) a1[i] = text[i1 + i + 1]; C = atol(a1); printf("C%Lu",C); flag=0; i=0; j=0; dem=0; if(C==1) RC1=1; If(C==0) RC1=0; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// } disable_interrupts(int_rda); disable_interrupts(global); } void display(int16 n){ int nghin,tram,chuc,dvi; nghin = n/1000; tram = (n%1000)/100; chuc = (n%100)/10; dvi = n%10; PORTB=dvi<<1; RD0=0; delay_ms(1);RD0=1; PORTB=chuc<<1; RD1=0; delay_ms(1);RD1=1; PORTB=tram<<1; RC4=0; delay_ms(1);RC4=1; PORTB=nghin<<1; RC5=0; delay_ms(1);RC5=1; } |
03-06-2013, 10:47 PM | #11 | |
Nhập môn đệ tử
Tham gia ngày: May 2012
Bài gửi: 3
: |
Trích:
|
|
31-08-2015, 10:00 AM | #12 |
Nhập môn đệ tử
Tham gia ngày: Aug 2015
Bài gửi: 2
: |
lỗi dòng portb=0; là lỗi j zây mọi người, sữa sao được đây
#INCLUDE<16F877A.H> #FUSES HS,NOWDT,NOPROTECT,NOLVP #USE DELAY(CLOCK=40000000) #use fast_io(b) #byte port=0x06 int8 sck,slx,bx,bl,gt; void main() { set_tris_b(0); while(true) { sck=8; bl=0; portb=(0); delay_ms(1000); while(sck>0) { bx=1; slx=sck; while(slx>0) { gt=bl|bx; portb=gt; delay_ms(1000); bx=bx<<1; slx--; } bl=gt; sck--; } } } |
|
|