PIC Vietnam

Go Back   PIC Vietnam > Microchip PIC > Các ngôn ngữ lập trình khác (CCS C, HT PIC,...) > Lỗi lập trình ngôn ngữ cấp cao

Tài trợ cho PIC Vietnam
Trang chủ Đăng Kí Hỏi/Ðáp Thành Viên Lịch Bài Trong Ngày Vi điều khiển

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.

Trả lời
 
Ðiều Chỉnh Xếp Bài
Old 21-08-2008, 12:23 AM   #1
bazooka2006
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?
bazooka2006 vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Old 21-08-2008, 12:36 AM   #2
phamminhtuan
Super Moderator
 
phamminhtuan's Avatar
 
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.
phamminhtuan vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Old 21-08-2008, 02:01 AM   #3
bazooka2006
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.
bazooka2006 vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Old 21-08-2008, 11:44 AM   #4
phamminhtuan
Super Moderator
 
phamminhtuan's Avatar
 
Tham gia ngày: Feb 2006
Bài gửi: 150
:
Trích:
Nguyên văn bởi bazooka2006 View Post
Code:
#include <16F877A.h>
...
#priority rb,rda  

...
#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)
     { 
 
     }
}
Mình có quote cho bạn những đoạn code trên, bạn cần lưu ý những điều sau để tự sửa lại chương trình:
  • Trong PIC16F877A không có ưu tiên ngắt, do đó chỉ dẫn #priority không có tác dụng
  • Khi xảy ra bất kì 1 ngắt nào, thì GIE = 0 để tránh xảy ra các ngắt chồng nhau, nó chỉ được set = 1 khi có lệnh RETFIE, có nghĩa là khi xảy ra 1 ngắt bất kì thì chỉ khi thực hiện xong ngắt đó mới có thể giải quyết ngắt tiếp theo
  • Khi xử lý 1 ngắt, trước khi kết thúc trình phục vụ ngắt, bạn phải xóa cờ ngắt đó bằng lệnh clear_interrupt();, nếu không sau khi thoát ra khỏi ngắt đó, nó sẽ quay trở lại
  • enable_interrupts(INT_RB|H_TO_L); không có OR với H_TO_L, tuy nhiên do giá trị H_TO_L = 0, nên chương trình bạn không bị ảnh hưởng
  • Dưới đây là file list C/ASM đơn giản để bạn thấy rõ điều đó
PHP Code:
#include<16f877a.h>
#use delay(clock=4Mhz)
#use rs232(baud=9600, UART1)
#INT_RDA
void rda(){
   
unsigned char c;
   
getc(); //Lệnh này sau khi đọc xong kí tự, thì cờ ngắt tự động bị xóa
   
output_b(0xAA);
}

#INT_RB
void rb(){
   
output_b(0x55);
   
clear_interrupt(INT_RB);
}

void main(){
   
enable_interrupts(INT_RDA);
   
enable_interrupts(INT_RB);
   
enable_interrupts(GLOBAL);
   
   while(
1);

đây là file list, lược bớt đoạn đầu, là đoạn chỉ lưu các thanh ghi và lựa chọn nhảy đến vị trí các chương trình phục vụ ngắt, không hề có lệnh nào xóa cờ ngắt
PHP Code:
.................... #INT_RDA 
.................... void rda(){ 
....................    
unsigned char c
....................    
getc(); 
003C:  BTFSS  0C.5
003D
:  GOTO   03C
003E
:  MOVF   1A,W
003F
:  MOVWF  28
....................    output_b(0xAA); 
0040:  BSF    03.5
0041
:  CLRF   06
0042
:  MOVLW  AA
0043
:  BCF    03.5
0044
:  MOVWF  06
.................... } 
....................  
0045:  BCF    0C.5
0046
:  BCF    0A.3
0047
:  BCF    0A.4
0048:  GOTO   023
.................... #INT_RB 
.................... void rb(){ 
....................    
output_b(0x55); 
0049:  
BSF    03.5
004A
:  CLRF   06
004B
:  MOVLW  55
004C
:  BCF    03.5
004D
:  MOVWF  06
....................    clear_interrupt(INT_RB); 
004E:  BCF    0B.0 //Chỉ khi có lệnh này, thì cờ ngắt của INT_RB mới được xóa
.................... } 
phamminhtuan vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Old 21-08-2008, 02:48 PM   #5
bazooka2006
Nhập môn đệ tử
 
Tham gia ngày: Apr 2008
Bài gửi: 6
:
Trích:
Nguyên văn bởi phamminhtuan View Post

Trong PIC16F877A không có ưu tiên ngắt, do đó chỉ dẫn #priority không có tác dụng
Cám ơn bạn minhtuan, quả thực trong datasheet 16f87xA ko hề nhắc đến điều này, mình nhầm to chỗ này rồi.
Trích:
Khi xảy ra bất kì 1 ngắt nào, thì GIE = 0 để tránh xảy ra các ngắt chồng nhau, nó chỉ được set = 1 khi có lệnh RETFIE, có nghĩa là khi xảy ra 1 ngắt bất kì thì chỉ khi thực hiện xong ngắt đó mới có thể giải quyết ngắt tiếp theo.
  • Một câu hỏi đặt ra là ngay khi thực hiện ngắt 1, có thể tự set bit GIE lên 1 để nhận các ngắt khác không?
  • Thứ 2 là vấn đề của mình vẫn chưa giải quyết được. Như mình đã nói, mình đã test thử là thay vì cho chạy đcơ trong ngắt RDA, thì mình đưa đoạn đó ra ngoài main(), trong ngắt RDA chỉ set 1 bit cờ rồi thoát. Hàm main sẽ lặp vòng hỏi cờ này, nếu thấy =1 thì cho chạy đcơ. Và, khi đoạn này đang chạy, nếu ctắc báo ngắt RB, vẫn ko thể dừng được, nghĩa là ko thực thi ngắt RB được. Chỉ khi hàm quay đcơ này chạy xong, nếu ngắt RB còn, hay mình tự tác động thì nó ngắt tốt.
  • Và nếu đưa đoạn ct quay đcơ ra ngoài main như trên, thì CCS báo "Warning 216 : Interrupt disable..." như đã nói.
    Có lẽ việc dùng delay_ms/us trong các ISR khi ở ngoài cũng có hàm này đang chạy sẽ thực sự gây bug là disable các ISR chăng?
bazooka2006 vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Old 21-08-2008, 03:29 PM   #6
phamminhtuan
Super Moderator
 
phamminhtuan's Avatar
 
Tham gia ngày: Feb 2006
Bài gửi: 150
:
Trích:
Nguyên văn bởi bazooka2006 View Post
Cám ơn bạn minhtuan, quả thực trong datasheet 16f87xA ko hề nhắc đến điều này, mình nhầm to chỗ này rồi.
  • Một câu hỏi đặt ra là ngay khi thực hiện ngắt 1, có thể tự set bit GIE lên 1 để nhận các ngắt khác không?
  • Thứ 2 là vấn đề của mình vẫn chưa giải quyết được. Như mình đã nói, mình đã test thử là thay vì cho chạy đcơ trong ngắt RDA, thì mình đưa đoạn đó ra ngoài main(), trong ngắt RDA chỉ set 1 bit cờ rồi thoát. Hàm main sẽ lặp vòng hỏi cờ này, nếu thấy =1 thì cho chạy đcơ. Và, khi đoạn này đang chạy, nếu ctắc báo ngắt RB, vẫn ko thể dừng được, nghĩa là ko thực thi ngắt RB được. Chỉ khi hàm quay đcơ này chạy xong, nếu ngắt RB còn, hay mình tự tác động thì nó ngắt tốt.
  • Và nếu đưa đoạn ct quay đcơ ra ngoài main như trên, thì CCS báo "Warning 216 : Interrupt disable..." như đã nói.
    Có lẽ việc dùng delay_ms/us trong các ISR khi ở ngoài cũng có hàm này đang chạy sẽ thực sự gây bug là disable các ISR chăng?
  • Dĩ nhiên, nếu bạn cứ set GIE lên, thì ngắt tiếp theo sẽ xảy ra trong khi đang thực thi ngắt cũ, và các giá trị mà CCS lưu lại sẽ bị đè lên bởi cái mới, giá trị con trỏ chương trình lưu lại chính là cái nơi xảy ra ngắt sau, thế nên chắc chắn 1 điều là chương trình của bạn chỉ có thể trở về tại vị trí nằm trong chương trình xử lý ngắt cũ(tại nơi xảy ra ngắt mới), và không thể trở về tại chương trình chính.
  • Việc bạn xác định ngắt RB không xảy ra trong khi động cơ đang quay bạn cần kiểm chứng bằng LED chẳng hạn
  • Còn hàm delay, bạn dịch thử 1 đoạn có delay, xem file list thì thấy rõ ngay, ví dụ bạn xem sau đây nhé, nó chỉ là những dòng lệnh bình thường như bao dòng lệnh khác thôi, chẳng tác động gì tới ngắt cả, thế nên, delay ở đâu cũng thế cả, có ngắt thì phục vụ ngắt.
PHP Code:
.................... #use delay(clock=4Mhz) 

0053:  MOVLW  29
0054
:  MOVWF  04
0055
:  BCF    03.7
0056
:  MOVF   00,W
0057
:  BTFSC  03.2
0058:  GOTO   067
0059:  MOVLW  01
005A
:  MOVWF  78
005B
:  CLRF   77
005C
:  DECFSZ 77,F
005D
:  GOTO   05C
005E
:  DECFSZ 78,F
005F
:  GOTO   05B
0060
:  MOVLW  4A
0061
:  MOVWF  77
0062
:  DECFSZ 77,F
0063
:  GOTO   062
0064
:  GOTO   065
0065
:  DECFSZ 00,F
0066
:  GOTO   059
0067:  BCF    0A.3
0068:  BCF    0A.4
0069:  GOTO   087 (RETURN)
//và
....................    delay_ms(1000); 
0082:  
MOVLW  04
0083:  MOVWF  28
0084:  MOVLW  FA
0085:  MOVWF  29
0086:  GOTO   053
0087:  DECFSZ 28,F
0088:  GOTO   084 
Bạn thấy rõ, CCS C sẽ tính toán các giá trị nạp vào các ô nhớ RAM ở địa chỉ 28 và 29, sau đó nhảy tới chương trình delay ở địa chỉ 53 để thực thi hàm delay, đến khi thực thi xong, thì lại nhảy 87, làm cho xong hết thì ra khỏi delay, bạn thấy đấy, delay chẳng liên quan gì đến xử lý ngắt cả. Bạn hãy viết các chương trình đơn giản hơn để kiểm nghiệm
phamminhtuan vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Old 08-09-2008, 02:59 PM   #7
quangduy
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
quangduy vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Old 17-05-2010, 06:28 AM   #8
vuxuansyhut
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
vuxuansyhut vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Old 27-05-2010, 05:51 PM   #9
nguyenung
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
nguyenung vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Old 28-05-2010, 01:18 AM   #10
tungbka
Đệ tử 1 túi
 
Tham gia ngày: Jul 2009
Bài gửi: 11
:
Unhappy

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;

}
tungbka vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Old 03-06-2013, 10:47 PM   #11
changnhoc123
Nhập môn đệ tử
 
Tham gia ngày: May 2012
Bài gửi: 3
:
Trích:
Nguyên văn bởi tungbka View Post
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;

}
bạn dis rda kiểu gì vậy, chỉ mình với, mình cũng bị lỗi này
changnhoc123 vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Old 31-08-2015, 10:00 AM   #12
Ham học
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--;
}

}

}
Ham học vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn
Trả lời


Quyền Sử Dụng Ở Diễn Ðàn
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is Mở
Smilies đang Mở
[IMG] đang Mở
HTML đang Tắt

Chuyển đến


Múi giờ GMT. Hiện tại là 08:56 AM.


Được sáng lập bởi Đoàn Hiệp
Powered by vBulletin®
Page copy protected against web site content infringement by Copyscape
Copyright © PIC Vietnam