Thông báo

Collapse
No announcement yet.

Sử dụng chức năng capture của PIC

Collapse
X
 
  • Lọc
  • Giờ
  • Show
Clear All
new posts

  • #16
    Vì đã quá lâu tôi không lập trình, nên tôi không nhớ chính xác lắm, chibang nên kiểm tra lại việc này.

    Theo tôi nhớ, hoạt động capture sẽ ngắt ở hai trường hợp, một là khi có tín hiệu capture, hai là khi timer tràn. Nếu timer tràn mà không có tín hiệu capture, thì giá trị max của timer sẽ được lưu vào cpp.

    Do đó, việc làm của bạn là không hợp lý.

    Tôi xin lỗi nếu tôi nhớ sai, bạn kiểm tra lại dùm phần này.
    Falleaf
    Công ty TNHH Thương mại và Giao nhận R&P
    58/57 Nguyễn Minh Hoàng - Phường 12 - Quận Tân Bình - TP.HCM
    mail@falleaf.net - VP: (04) 36408561 - (08) 38119870

    Comment


    • #17
      Nguyên văn bởi falleaf
      Vì đã quá lâu tôi không lập trình, nên tôi không nhớ chính xác lắm, chibang nên kiểm tra lại việc này.

      Theo tôi nhớ, hoạt động capture sẽ ngắt ở hai trường hợp, một là khi có tín hiệu capture, hai là khi timer tràn. Nếu timer tràn mà không có tín hiệu capture, thì giá trị max của timer sẽ được lưu vào cpp.

      Do đó, việc làm của bạn là không hợp lý.

      Tôi xin lỗi nếu tôi nhớ sai, bạn kiểm tra lại dùm phần này.
      Trang 65 của datasheet 16F87xA có nói:
      CCP1IF chỉ được đặt khi capture xảy ra(các mode tuỳ theo cài đặt:
      • Every falling edge
      • Every rising edge
      • Every 4th rising edge
      • Every 16th rising edge).
      Còn TMR1IF xảy ra khi bộ đinh thời tràn. Bộ định thời tràn ko tác động gì tới capture bởi vậy nên ko như bác nói.
      -------------------

      Comment


      • #18
        Vì tôi nhớ vậy thôi, bác viết code và thử lại đi, nếu không đúng thì đúng là tôi nói bậy rồi, xin lỗi bác vậy. Dạo này chắc già, nên hơi lẩn thẩn.

        << mới 25 thôi đó... hehhehee... anh em nào thử rồi thì báo lại nhé, vì tôi vẫn không nhớ khác đi được...
        Falleaf
        Công ty TNHH Thương mại và Giao nhận R&P
        58/57 Nguyễn Minh Hoàng - Phường 12 - Quận Tân Bình - TP.HCM
        mail@falleaf.net - VP: (04) 36408561 - (08) 38119870

        Comment


        • #19
          Chương trình mới

          #include <16F876A.h>
          #use delay(clock=4000000)
          #fuses HS,NOWDT, NOPROTECT
          #use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7)
          #bit TMR1IF 0x0C.0
          int16 CCP1Value;
          int16 CCP1OldValue;
          BOOLEAN CCP1Captured;


          #int_CCP1
          CCP1_isr()
          {

          if(TMR1IF)
          {
          CCP1Value = CCP_1 +(65535-CCP1OldValue);
          CCP1OldValue = CCP_1;
          TMR1IF=0;

          }
          else
          {
          CCP1Value = CCP_1 - CCP1OldValue;
          CCP1OldValue = CCP_1;
          }
          CCP1Captured = TRUE;

          }
          //--------------------------------------------------------------------------
          void Init_ccp(void)
          {
          setup_ccp1(CCP_CAPTURE_RE);
          setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
          CCP1Value = 0;
          CCP1OldValue = 0;
          CCP1Captured = TRUE;
          enable_interrupts(INT_CCP1);
          enable_interrupts(GLOBAL);
          }
          //--------------------------------------------------------------------------
          void main()
          {
          float Freq;
          Init_ccp();
          printf("Frequence test:\r\n");
          while (TRUE) {

          if (CCP1Captured) {

          // F = 1/T
          // Timer1 prescaler DIV_BY_8
          // Pic16F876 4Mz -> 0.000001 * 8

          Freq = 1.0/((float)CCP1Value*8e-6);
          printf("Freq:%f\r\n",Freq);
          CCP1Captured = FALSE;
          }
          }
          }
          Càng biết nhiều càng thấy mình biết ít.

          Comment


          • #20
            Ko ổn định

            Theo góp ý của CHIBANG tôi đã sửa lại ct một chút, mặc dù vậy số liệu vẫn chưa thật sự ổn định.

            Vì xung clock đã chia 8 nên khả năng timer1 tràn nhiều lần là khó xảy ra.

            Tôi cũng có thử thêm dùng cả ngắt timer1 như ý kiến của CHIBANG nhưng kết quả không khác.

            Mọi nguời cho ý kiến xem còn vấn đề gì không.

            Tôi dùng NE555 phát thử 1 xung 78 HZ, đo tần số hiển thị giá trị khá chuẩn nhưng đôi lúc lại bị 1 giá trị quá bé hoặc quá lớn. Chưa rõ nguyên nhân
            Càng biết nhiều càng thấy mình biết ít.

            Comment


            • #21
              Re: Chương trình mới

              Nguyên văn bởi ATYLA
              #include <16F876A.h>
              #use delay(clock=4000000)
              #fuses HS,NOWDT, NOPROTECT
              #use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7)
              #bit TMR1IF 0x0C.0
              int16 CCP1Value;
              int16 CCP1OldValue;
              BOOLEAN CCP1Captured;


              #int_CCP1
              CCP1_isr()
              {

              if(TMR1IF)
              {
              CCP1Value = CCP_1 +(65535-CCP1OldValue);
              CCP1OldValue = CCP_1;
              TMR1IF=0;

              }
              else
              {
              CCP1Value = CCP_1 - CCP1OldValue;
              CCP1OldValue = CCP_1;
              }
              CCP1Captured = TRUE;

              }
              //--------------------------------------------------------------------------
              void Init_ccp(void)
              {
              setup_ccp1(CCP_CAPTURE_RE);
              setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
              CCP1Value = 0;
              CCP1OldValue = 0;
              CCP1Captured = TRUE;
              enable_interrupts(INT_CCP1);
              enable_interrupts(GLOBAL);
              }
              //--------------------------------------------------------------------------
              void main()
              {
              float Freq;
              Init_ccp();
              printf("Frequence test:\r\n");
              while (TRUE) {

              if (CCP1Captured) {

              // F = 1/T
              // Timer1 prescaler DIV_BY_8
              // Pic16F876 4Mz -> 0.000001 * 8

              Freq = 1.0/((float)CCP1Value*8e-6);
              printf("Freq:%f\r\n",Freq);
              CCP1Captured = FALSE;
              }
              }
              }
              Có vẻ phức tạp đấy nhỉ.
              1-Bác check cho tui xem xung tạo = 555 cua bac' co' chuan ko? nguồn nuôi? tụ lọc? nếu chuẩn rồi thì tiếp

              2-Có thể tại đây:
              #int_CCP1
              CCP1_isr()
              {
              //Tràn ngay tại thời điểm này mới đen...bác hiểu chứ?
              /*
              Nghĩa là tai thoi diem capture thi timer chua kip tran, giả sử nó là 655535, nhưng khi vao ngat thi đen thay, nó bị tràn về ko nên TMR1IF=1;
              */
              if(TMR1IF)
              {
              CCP1Value = CCP_1 +(65535-CCP1OldValue);
              CCP1OldValue = CCP_1;
              TMR1IF=0;
              }
              else
              {
              CCP1Value = CCP_1 - CCP1OldValue;
              CCP1OldValue = CCP_1;
              }
              CCP1Captured = TRUE;
              }

              Bởi thế sửa thành thế này xem có đc ko?
              #int_CCP1
              CCP1_isr()
              {
              if(CCP1OldValue>CCP1Value)
              {
              CCP1Value = CCP_1 +(65535-CCP1OldValue);
              CCP1OldValue = CCP_1;
              }
              else
              {
              CCP1Value = CCP_1 - CCP1OldValue;
              CCP1OldValue = CCP_1;
              }
              CCP1Captured = TRUE;
              }

              Nếu vẫn ko ổn định thì làm kém đi = cách

              #int_CCP1
              CCP1_isr()
              {
              TMR1ON=0;
              TMR1L=0;
              TMR1H=0;
              TMR1ON=1;
              CCP1OldValue = CCP_1;
              }
              CCP1Captured = TRUE;
              }


              Nêu vẫn chưa được thì ta lại bàn tiếp

              Comment


              • #22
                Thấy mấy bác bàn luận hay quá , em cũng sẽ làm thử rồi báo cáo mấy bác , em cũng tham khảo trong Example của CCS :

                /////////////////////////////////////////////////////////////////////////
                //// EX_CCPMP.C ////
                //// ////
                //// This program will show how to use the built in CCP to ////
                //// measure a pulse width. ////
                //// ////
                //// Configure the CCS prototype card as follows: ////
                //// Connect a pulse generator to pin 3 (C2) and pin 2 (C1) ////
                //// See additional connections below. ////
                //// ////
                //// This example will work with the PCM and PCH compilers. The ////
                //// following conditional compilation lines are used to include a ////
                //// valid device for each compiler. Change the device, clock and ////
                //// RS232 pins for your hardware if needed. ////
                /////////////////////////////////////////////////////////////////////////
                //// (C) Copyright 1996,2003 Custom Computer Services ////
                //// This source code may only be used by licensed users of the CCS ////
                //// C compiler. This source code may only be distributed to other ////
                //// licensed users of the CCS C compiler. No other use, ////
                //// reproduction or distribution is permitted without written ////
                //// permission. Derivative programs created using this software ////
                //// in object code form are not restricted in any way. ////
                /////////////////////////////////////////////////////////////////////////


                #if defined(__PCM__)
                #include <16F877.h>
                #fuses HS,NOWDT,NOPROTECT,NOLVP
                #use delay(clock=20000000)
                #use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7) // Jumpers: 8 to 11, 7 to 12

                #elif defined(__PCH__)
                #include <18F452.h>
                #fuses HS,NOWDT,NOPROTECT,NOLVP
                #use delay(clock=20000000)
                #use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7) // Jumpers: 8 to 11, 7 to 12
                #endif


                long rise,fall,pulse_width;

                #int_ccp2
                void isr()
                {
                rise = CCP_1;
                fall = CCP_2;

                pulse_width = fall - rise; // CCP_1 is the time the pulse went high
                } // CCP_2 is the time the pulse went low
                // pulse_width/(clock/4) is the time

                // In order for this to work the ISR
                // overhead must be less than the
                // low time. For this program the
                // overhead is 45 instructions. The
                // low time must then be at least
                // 9 us.

                void main()
                {
                printf("\n\rHigh time (sampled every second):\n\r");
                setup_ccp1(CCP_CAPTURE_RE); // Configure CCP1 to capture rise
                setup_ccp2(CCP_CAPTURE_FE); // Configure CCP2 to capture fall
                setup_timer_1(T1_INTERNAL); // Start timer 1

                enable_interrupts(INT_CCP2); // Setup interrupt on falling edge
                enable_interrupts(GLOBAL);

                while(TRUE) {
                delay_ms(1000);
                printf("\r%lu us ", pulse_width/5 );
                }
                }

                Comment


                • #23
                  Nếu tần số < 10HZ thì làm thế nào?Thuật toán kia tính toán giá trị là : CCP1Value = CCP_1 +(65535-CCP1OldValue);. Chỉ áp dụng trong trường hợp giữa hai sường xung lên Timer1 chỉ Reset có 1 lần Nếu tần số <10HZ tức là giữa hai sườn xung lên Timer1 đã RESET n lần. Nên công thức phải là : CCP1Value = CCP_1 +(65535*n-CCP1OldValue);. Vậy làm sao để xác định n trong chương trình ngắt ?
                  Last edited by dieucay333; 17-04-2009, 10:54.

                  Comment


                  • #24
                    tôi viết một code giải mã tín hiều điều khiển từ xa thế này ko biết sai ở đâu mà thấy con vi điều khiển ko làm việc mong cac bác chỉ giáo.
                    #include <16f877A.h>
                    #use delay(clock=4000000)
                    #fuses HS,NOWDT, NOPROTECT
                    #use fast_IO(B)
                    #byte portB=0x06
                    #bit B0=portB.0
                    #bit B1=portB.1
                    #bit B2=portB.2
                    #bit B3=portB.3
                    #bit B4=portB.4
                    #bit B5=portB.5
                    #bit B6=portB.6
                    #bit B7=portB.7
                    int16 CCP1Value;
                    BOOLEAN CCP1Captured;
                    #int_CCP1
                    void ngat()
                    {
                    CCP1value=CCP_1;
                    set_timer1(0);
                    CCP1captured=TRUE;
                    }
                    void init_CCP1()
                    {
                    setup_CCP1(CCP_CAPTURE_RE);
                    setup_timer_1(T1_EXTERNAL|T1_DIV_BY_8);
                    CCP1captured=TRUE;
                    CCP1value=0;
                    enable_interrupts(int_CCP1);
                    enable_interrupts(global);
                    }
                    float dochuky()
                    {
                    float T;
                    init_CCP1();
                    if(CCP1captured==TRUE)
                    { T=(CCP1value)*8e-6;
                    CCP1captured=FALSE;
                    }
                    return T;
                    }
                    void main()
                    {

                    int8 A;
                    int i;
                    float T;
                    while(TRUE)
                    {
                    A=0b00000010;//lam nhu the de vi ma bit cua phim 1 la 0h
                    for(i=0;i<8;i++)
                    {
                    T=dochuky();
                    if(T<=1300&&T>=1100) {A=A+0;}
                    else if(T<=1900&&T>=1700) A=A+0b00000001;
                    A=A>>1;
                    }

                    if(A==0b00000000) B0=!B0;
                    else if(A==0b00000001) B1=!B1;
                    else if(A==0b00000010) B2=!B2;
                    else if(A==0b00000011) B3=!B3;
                    else if(A==0b00000100) B4=!B4;
                    else if(A==0b00000101) B5=!B5;
                    else if(A==0b00000110) B6=!B6;
                    else if(A==0b00000111) B7=!B7;
                    }
                    }

                    Comment


                    • #25
                      sao chi thay post code ma ko thay mô phỏng thế này

                      Comment


                      • #26
                        Đo tần số hay độ rộng xung thì các bác tham khảo link này: http://www.ccsinfo.com/forum/viewtopic.php?t=33153
                        Không hiểu lúc mô phỏng trên Proteus thì luôn bị hụt 1Hz so với tần số gốc,chẳng hạn 80 thì chỉ còn 79
                        Nếu không cần đáp ứng nhanh thì các bác dùng CCP để đếm xung trong 1 giây thì sẽ chính xác hơn,thế này thôi:

                        #int_timer1
                        void ngat_timer1() // cứ 1s thì cập nhật giá trị tần số 1 lần
                        {
                        dem++;
                        if(dem>19) //Mac dinh la 19 =1s
                        {
                        tanso = dem1;
                        dem1 = 0; //su dung khi do tan so
                        dem=0;
                        if(count>9999)
                        count=0;
                        }
                        //T= 20 x (66536-15535) x 1 x4/4000000 = 1s
                        set_timer1(15535);
                        }
                        #int_ccp1
                        void ccp1_isr(void)
                        {
                        dem1 = dem1 + 1;
                        }

                        void main()
                        {
                        setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
                        set_timer1(15535);
                        enable_interrupts(int_timer1);
                        while(1)
                        {
                        display(tanso);
                        }
                        }

                        Các bác tự khai báo biến,em chỉ viết phần thân.
                        Chỉ có điều chỉ chạy được khi mô phỏng bằng Proteus,còn khi làm ra mạch thỉ cái CCP nó tự chạy rồi hiển thị số lung tung lúc thì 50 lúc 70,chắc bị nhiễu từ mạng điện.


                        email:
                        Giá mà mạch điện tử không có nhiễu (noise) thì mình bây giờ đã là ... đại gia

                        Comment


                        • #27
                          Cần giúp đỡ phần đọc capture gửi lên máy tính

                          Mình đã thiết lập code để đọc capture gửi lên máy tính. Không biết code đọc capture của mình đã chính xác chưa, nhưng mình bị lỗi hàm MID. Vì CCP_1 là 1 chuỗi số, mà gửi lên PC thì chỉ có thể 1 ký tự trong 1 thời điểm, nên mình dùng hàm MID để cắt từng ký tự ra, nhưng nó lại không hiểu mặt dù mình đã include thêm file string.h vào rồi. Nhờ mọi người hướng dẫn thêm, cảm ơn.

                          Code:
                          #include <16f877a.h>
                          #include <string.h>
                          #use Fast_IO(B)
                          #byte PORTB = 0x6
                          #byte TRISB = 0x86
                          
                          int32 rise, fall, pulse_width;
                          unsigned char i, str;
                          
                          #int_ccp1
                            void isr()
                            {
                               rise = CCP_1;                                     //CCP_1 is the time the pulse went high
                               fall = CCP_2;                                     //CCP_2 is the time the pulse went low
                               pulse_width = fall - rise;                        //pulse width
                               
                               for (i=1; i<=strlen(CCP_1); i++)
                               {
                                   str = mid(CCP_1, i, 1);
                                   putc(str);
                               }
                               
                               set_timer1(0);
                            }            
                          
                          
                          void main()
                          {
                          
                             setup_ccp1(CCP_CAPTURE_RE);    // Configure CCP1 to capture rise
                             setup_ccp2(CCP_CAPTURE_FE);    // Configure CCP2 to capture fall
                             setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);       // Start timer 1
                          
                             Set_tris_B(0);
                             while(true)
                             {
                              //  putc('A');
                              //  delay_ms(500);
                             }
                          }

                          Comment


                          • #28
                            Mình tham khảo trong CCS thấy có hàm PUTS() cho phép hiển thị 1 chuỗi ký tự, nhưng khì mình đưa CCP_1 {PUTS(CCP_1)} vào thì không thấy hiện ra gì cả, nhưng vẫn có dữ liệu được gửi lên..

                            Comment


                            • #29
                              Mình vẫn chưa hiểu về chế độ capture này. Khi có cạnh lên, CCP_1 sẽ lưu là lưu cái gì, hay là nó lưu thời gian mà Timer đếm được, nếu vậy thì tại sao ko đọc dữ liệu trực tiếp từ Timer. (Hay là đọc dữ liệu từ Timer sẽ bị sai, còn CCP_1 bắt được sẽ lưu giá trị này sẽ là giá trị ngay thời điểm có xung lên - nếu mình chọn xung lên).

                              Một chút thắc mắc ngoài lề tí, mình thấy mấy diễn đàn thường ít trả lời mấy câu hỏi cơ bản quá. Hay là để cho người mới tự mò. Mình thì tự học con PIC này, nên gặp nhiều khó khăn chút. Trước học 89 thì quá nhiều tài liệu với lại viết bằng ASM nên cũng dễ hiểu. Giờ học PIC viết C, thấy cách diễn đạt nó hơi khác khác tí nên hơi choáng. ^^

                              Comment


                              • #30
                                Mình cũng dùng chức năng này để đo vậy tốc động cơ, khổ nỗi là giá trị mình đọc về là 16bit, lúc trừ thì không biết trừ theo kieeri gì! Nối 2 giá trị 8 bit lại thì nó hiểu là số có dấu mặc dù mình đã định nghĩa unsigned !

                                Comment

                                Về tác giả

                                Collapse

                                ATYLA Tìm hiểu thêm về ATYLA

                                Bài viết mới nhất

                                Collapse

                                Đang tải...
                                X