Thông báo

Collapse
No announcement yet.

Timer0 trong Pic 16f877a CCS

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

  • Timer0 trong Pic 16f877a CCS

    Em viết một chương trình tạo xung pwm bằng timer0 với chu kỳ xung T = 51.2us nhưng không hiểu thế nào mà đều ra là 70us ??

    Đoạn chương trình C
    #include <16F877a.h>
    //#DEVICE ADC= 8
    #include <def_877a.h>
    #FUSES NOWDT, HS, NOPUT, NOPROTECT, NODEBUG, NOBROWNOUT, NOLVP, NOCPD, NOWRT
    #use Delay(Clock=20000000)

    //------------------------------------------------------------------------------------------------
    #define pwm1 RB0

    //-------------------------------ngắt timer0-----------------------------------------------
    #int_TIMER0
    void TIMER0_isr(void)
    {
    set_timer0(127);
    pwm1=!pwm1;
    }

    //-----------------------------------------------------------------------------
    void main()
    {
    setup_adc(ADC_OFF);
    set_tris_a(0xff);
    set_tris_d(0x00);
    set_tris_b(0x00);
    set_tris_c(0x00);

    setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);//0-255 tran 51.2us

    delay_ms(100);

    set_timer0(127);

    enable_interrupts(INT_TIMER0);
    enable_interrupts(GlOBAL);
    //-----------------------------------------------------------------------------

    while(1)
    {

    }
    }
    Đoạn timer0 bằng ASM
    .................... #int_TIMER0
    .................... void TIMER0_isr(void)
    .................... {
    .................... set_timer0(127);
    *
    003C: MOVLW 7F
    003D: MOVWF 01

    .................... pwm1=!pwm1;
    003E: MOVLW 01
    003F: XORWF 06,F

    .................... }
    Trong đó:
    - Lệnh MOVLW:Mất 1 chu kỳ máy
    - Lệnh MOVWF:Mất 1 chu kỳ máy
    - Lệnh XORWF:Mất 1 chu kỳ máy
    Tài liệu tham khảo lệnh asm: http://ww1.microchip.com/downloads/e...Doc/31029a.pdf

    Chương trình: timer0-pwm.zip

  • #2
    Đây là xung đo bằng osilo
    Kết quả: T=68us ( mất đi đâu 16.8 us ? )

    Attached Files

    Comment


    • #3
      Chia buồn cùng bạn, có vẻ lỗi này giống lỗi mà ngày đầu tiên tui nhập môn PIC khi cố gắng tạo ra xung 38kHz bằng timer0 và kết quả hình như là ko lên đc quá 10kHz (ko nhớ rõ lắm). Và theo như các "trưởng lão" bên PICVN nói thì đây là vấn đề do các header rồi khởi tạo gì đó (các kiểu) dẫn đến việc ngắt không thể hoạt động liên tiếp trong giới hạn nào đó (bạn có thể thử bằng cách giảm dần giá trị 127 đang có của bạn về dần 0 đến khi nào T có thay đổi thì đó gọi là ngưỡng).
      Và để khắc phục điều này, tui bắt buộc đã phải chuyển sang dùng hardware PWM của chip.
      Hy vọng giúp đc gì cho bạn!

      Comment


      • #4
        Nguyên văn bởi nhanh0112 Xem bài viết
        Chia buồn cùng bạn
        Cám ơn bác!
        Để em tìm hiểm thêm xem thế nào ?
        Last edited by luongthitu; 06-02-2013, 14:32.

        Comment


        • #5
          - Coi như vấn đề 1 này tạm bỏ qua ( gọi là vấn đề đáp ứng tần số xung bằng timer )
          - Vấn đề 2: Em tạo thêm một xung nữa bằng timer1 ( xung của timer0 giữ nguyên )


          ----------------------------đoạn chương trình tạo thêm xung bằng timer1-------------------------------------------
          #int_TIMER1
          void TIMER1_isr(void)
          {
          set_timer1(set1);
          pwm2=!pwm2;
          }
          setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);//0-65535
          enable_interrupts(INT_TIMER1);

          Trong do, em thay đổi biến set1 để thay đổi chu kỳ xung ( từ 0-65.535 ), nhưng em ko hiểu tại sao? khi thay đổi set1 thì chu kỳ xung của Timer0 cũng thay đổi theo mà ko phải là một hằng số ( mặc dùng set-timer0 cố định là 127 rồi .)

          Ví dụ:
          ban đầu em set1=65.376 thì đo được
          ==> f0 = 14.4531khz ( coi như là fix )
          ==> f1 = 14.4531khz ( đáng ra thì phải khác f0 )

          bây giờ cho set1=65.217
          ==>f0 = 20.89khz ( đã bị thay đổi )
          ==>f1 = 6.964khz

          //-------------------------------ngắt timer0 được fix cố định -----------------------------------------------
          #int_TIMER0
          void TIMER0_isr(void)
          {
          set_timer0(127);
          pwm1=!pwm1;
          }
          Last edited by luongthitu; 06-02-2013, 14:49.

          Comment


          • #6
            Các dòng VĐK cơ bản thì đã số hoạt động theo kiểu tuần tự, khi có các tác vụ ngắt nhảy vào thì nó sẽ dừng cái đó đang chạy và chuyển sang chạy trình phục vụ ngắt, thực hiện tuần tự xong trình phục vụ ngắt nó sẽ tự thoát khỏi ngắt và trở về đoạn chương trình đang chạy dở ở trên.
            Trường hợp của bạn có thể tạm mô tả thế này. Khi timer0 đang đếm thì ngắt timer1 xảy ra -> dừng timer0 -> timer1 xử lý xong -> timer0 chạy tiếp
            Như vậy timer0 đã bị dừng 1 nhịp so với thực tế, nếu chương trình timer1 phải thực hiện nhiều việc khác hoặc ngắt nhiều lần trước khi timer0 tạo ra đc 1 ngắt thì hiển nhiên timer0 sẽ bị dừng nhiều rồi.
            Cá nhân tui làm thì thường những gì cần chính xác thì mới dùng timer, còn nếu dùng nhiều tác vụ thì nên viết xen kẽ các tác vụ vào chung 1 timer đó.

            Comment


            • #7
              Nguyên văn bởi nhanh0112 Xem bài viết
              Chia buồn cùng bạn, có vẻ lỗi này giống lỗi mà ngày đầu tiên tui nhập môn PIC khi cố gắng tạo ra xung 38kHz bằng timer0 và kết quả hình như là ko lên đc quá 10kHz (ko nhớ rõ lắm). Và theo như các "trưởng lão" bên PICVN nói thì đây là vấn đề do các header rồi khởi tạo gì đó (các kiểu) dẫn đến việc ngắt không thể hoạt động liên tiếp trong giới hạn nào đó


              Em có đọc tài liệu nhưng vẫn chưa rõ là vì đâu.???
              Để tránh những vấn đề do khởi tạo của CCS thì em có viết chương trình tác động trực tiếp tới các thanh ghi.
              Nhưng xem ra cũng không an thua...

              Khó hiểu.

              Khởi tạo timer0
              TMR0 = 127;// Bo dem timer0 bat dau tu 127 toi 255
              OPTION_REG = 0b00000000;//Timer0 hoat dong o che do chia 1:2
              TMR0IE=1; //cho phep ngat timer0 hoat dong
              GIE = 1;//cho phep tat ca cac ngat
              Chương trình ngắt timer0
              #int_TIMER0
              void TIMER0_isr(void)
              {
              if(TMR0IE && TMR0IF)
              {
              //TMR0 Overflow ISR
              //Clear Flag
              TMR0 = 127;
              pwm1=!pwm1; // pwm1 la chan RB1
              TMR0IF=0;//xóa cờ ngắt
              }
              }
              Nếu đúng ra thì:
              T0 = ( 255- 127)*0.2*2 ---> uS
              Last edited by luongthitu; 16-02-2013, 12:27.

              Comment


              • #8
                Bạn xem qua bài viết này (bác namqn có giải thích qua ở thread 6) Giúp tạo xung 38kHz bằng Timer - PIC Vietnam
                Mặc dù timer2 đã đc cấu hình theo đúng yêu cầu về ngắt (tương ứng tạo ra tần số). Nhưng nếu lấy từ ngắt thì sẽ ko bao giờ đạt đc tần số yêu cầu, nên bắt buộc phải lấy từ Pwm.

                Comment


                • #9
                  Cái đầu tiên bạn phải kiểm tra lại khối dao động của PIC xem các giá trị đúng chưa, có dao động đúng 20MHz hay không.

                  Comment

                  Về tác giả

                  Collapse

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

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

                  Collapse

                  Đang tải...
                  X