Welcome & Happy Holidays!
Trang 1 của 5 123 ... CuốiCuối
Kết quả 1 đến 10 của 46
  1. #1
    Ngày tham gia
    Sep 2015
    Bài viết
    0

    Timer và cách tính thông số cài đặt cho timer.

    Đầu tiên là mình xin nói về timer0 cho các dòng 16F/18F. Ta nhìn vào sơ đồ khối chung sau:
    - Từ trái sang phải, ta thấy vào bộ mux (bộ chọn kênh) có 2 nguồn xung đó là Fosc/4 và T0CKI pin. Ở đây mình chỉ đề cập đến Timer0 với bộ Fosc/4 còn nguồn xung T0CKI pin rất ít sử dụng. Tiếp theo sau khi qua bộ mux thì nó lại rẽ ra 2 đường. Một đường là đi trực tiếp vào bộ mux thứ 2. Tức là xung nguồn từ Fosc/4 vào bao nhiêu thì vào bộ mux thứ 2 cũng bấy nhiêu. Đường thứ 2 là qua bộ prescaler. Vậy Prescaler là gì???. Nó là bộ chia tần hay còn gọi là tham số cho bộ chia của timer. Tham số này được cài đặt bởi người dùng theo các tùy chọn định trước. Tương ứng với tham số prescaler được chọn, mỗi lần tăng của timer sẽ được quy định như sau:

    Xung vào timer = Xung nguồn / Prescaler​
    - Vậy xung vào timer là gì??? Xung vào timer tức là tần số lệnh - Fcy. Cứ mỗi 1 tần số lệnh thì bộ đếm timer0 sẽ tăng lên 1 đơn vị. Giả sử nếu ta khai báo đi đường 1, tức ko qua bộ prescaler thì 1 xung nguồn (tần số máy - Fosc) = xung vào timer (tần số lệnh -Fcy).
    - Giả sử nếu ta khai báo xài prescaler là 1:256 chẳn hạn. Thì tức là bộ đếm timer0 sẽ tăng lên 1 sau 256 chu kỳ lệnh. Ý nói rằng phải có 256 xung vào thì sẽ có 1 xung ra.

    - Timer0 của dòng 18F có thể hoạt động ở chế độ 8 bit(0-255) hoặc 16 bit(0-65535)
    Nguyên lý hoạt động của timer0 như sau: Nếu ở chế độ 16bit. Khi có một xung timer clock thì bộ đếm TMR0L sẽ tăng lên 1 đơn vị. VD hiện tại là 358 sau khi có thêm 1 timer clock thì giá trị của nó là 359. Đến khi nào giá trị của TMR0L = 65535, và nhận tiếp 1 giá trị thì nó sẽ trở về 0, đồng thời sẽ bật cờ ngắt TIR0IF lên. Lúc này chương trình ngắt Timer0 sẽ chạy. Cờ ngắt này phải được xóa đi sau khi chạy xong chương trình ngắt để lần ngắt sau nó được bật lên lại.

    - Cách tính thông số cài đặt cho timer:

    Timer bắt đầu = 2^số bít timer - 1 - timer*(Fosc/(4*Prescaler))

    VD: Ta cần tạo thời gian là 1s với phần cứng sử dụng thạch anh 25Mhz, xài chế độ 16 bit, prescaler = 256 như sau:

    Timer bắt đầu = 2^16 - 1 - 1s*(25000000/4*256)) = 41120.93. Ta làm tròn số này thành 41121.

    - Ta lấy số này để cài đặt bộ đếm.
    +Nếu sử dụng MPLAB C18 thì dùng lệnh WriteTimer0(41121);
    +Nếu sử dụng CCSC thì dùng lệnh Set_timer0(41121);

    Lưu ý:
    1. Ở PIC16F877a/16F887 thì timer0 sẽ ko có chế độ 16bit, chỉ có chế độ 8 bit (0-255) thôi. Nên nếu xài chế độ 16bit thì chuyển sang timer1 với câu lệnh Set_timer1(41121);. Công thức trên tính chung cho cả timer0,1,2,3.

    2. Prescaler ta chọn sao cho giá trị timer bắt đầu phải là con số dương. Tức là 2^16 khi trừ vế sau phải ra con số dương, nếu ra số âm là sai, lúc đó ta phải chọn prescaler khác. Prescaler cho timer0 là 8bit nên có các giá trị sau: 2, 4, 8, 16, 32, 64, 128, 256.

    - Nhiều bạn tới đây sẽ hỏi. Công thức trên từ đâu ra. Mình sẽ giải thích cụ thể như sau:
    + Như ta đã biết trong PIC: Tcy = 4*Tosc => Fcy = Fosc/4
    - Do đã đi qua bộ Prescaler nên Fcy = Fosc/(4*Prescaler). Tức trong 1 tần số lệnh ta mất Fcy = Fosc/(4*Prescaler) Hz. 1 lần đếm lên của timer mất Tcy = 1/(Fosc/(4*Prescaler)) s. Mà để tính khoảng xung nhịp từ timer bắt đầu đến (2^16 - 1) thì ta phải lấy timer mong muốn chia cho Tcy. Nên ta lấy timer/[1/(Fosc/(4*Prescaler))] = timer*(Fosc/(4*Prescaler)).
    - Cuối cùng thì ta chỉ việc lấy con số cao nhất là (2^16 - 1) - timer*(Fosc/(4*Prescaler)) là ra con số cài đặt để bắt đầu đếm.

    - Kết luận: Trên đây là mình đã hướng dẫn cách tính thông số cài đặt cho timer. Vì trước giờ thấy nhiều bạn cứ máy móc gán prescaler là 8 hay 16 chẳn hạn và số cài đặt timer bắt đầu đếm cũng lấy đại từ code khác mà ko hiểu dc con số ấy được tính từ đâu ra. Như vậy sau này mọi người đều có thể set timer với mọi giá trị bất kỳ được rồi. Muốn bao nhiêu s cũng được. Nhưng do thạch anh ta sử dụng là 25Mhz khi chia cho 4*Prescaler thì chắc chắn sẽ bị lẻ và làm tròn. Nên tại 1 thời gian nhất định thì đúng là 1s thật, nhưng một thời gian sau nó sẽ ko còn đúng nữa. Nhất là làm về đồng hồ số chẳng hạn, ta khắc phục bằng cách sử dùng 1 thạch anh real time 32768Khz - 2^15. Nên chia cho 4*Prescaler đảm bảo ko bao giờ ra số lẻ. Nhưng mà thạch anh real time này chỉ xài cho timer1 tại chân T1OSC thôi. Timer0 ko được đâu nhé

    - Vào đây hoặc xem ở # 7 trong topic này để xem hướng dẫn cách xài Timer0 trên MPLAB C18.

    - Lần đầu tiên mình đăng bài trên diễn đàn này, nên có gì sai sót mong các bạn góp ý và bỏ qua cho.
    Chúc các bạn vui vẻ và thành công trong cuộc sống. ^^

  2. #2
    Ngày tham gia
    Jan 2016
    Bài viết
    8
    Bài viết rất hay, mong bạn tiếp tục phát huy. Kể có ví dụ demo thì tốt bạn nhỉ?

  3. #3
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Trích dẫn Gửi bởi sgesvn
    Bài viết rất hay, mong bạn tiếp tục phát huy. Kể có ví dụ demo thì tốt bạn nhỉ?
    Mai em sẽ post ví dụ và mô phỏng lên, giờ đuối òi. Ngủ sớm thôi

  4. #4
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    PIC18F timer0 mới có 16bits, PIC16F thì timer0 đào đâu 16bits, và PIC thì thường dùng thạch anh chia hết cho 4, dòng 16F tối đa là 20Mhz external crystal còn 18F tối đa 48Mhz thì phải ( nếu nhớ nhầm thì sr nha )

  5. #5
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Trích dẫn Gửi bởi demon52
    PIC18F timer0 mới có 16bits, PIC16F thì timer0 đào đâu 16bits, và PIC thì thường dùng thạch anh chia hết cho 4, dòng 16F tối đa là 20Mhz external crystal còn 18F tối đa 48Mhz thì phải ( nếu nhớ nhầm thì sr nha )
    Hi, trong phần lưu ý em có nói mà anh.
    • Ở PIC16F877a thì timer0 sẽ ko có chế độ 16bit, chỉ có chế độ 8 bit (0-255) thôi. Nên nếu xài chế độ 16bit thì chuyển sang timer1 với câu lệnh set_timer1(41121);​
    Cái này em chỉ bày cách tính công thức thôi, nên em mới ghi chung chung cho 2 dòng như thế.

  6. #6
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    ok bạn, mình ko đọc bài kĩ, chỉ nhìn thấy dòng ghi timer0 có 2 chế độ 8 và 16b là trả lời rồi )

  7. #7
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Nay mình sẽ hướng dẫn cách xài timer0 chế độ 16bit cho PIC18F4620 dùng MPLAB C18. Còn với dòng PIC16F điển hình như 16F877a/887 dùng CCSC thì mình thấy đã có quá nhiều project mẫu trên diễn đàn rồi. Chỉ cần tính toán thông số đưa vào là xong.
    - Đầu tiên là các bạn mở MPLAB IDE 8.85, chắc chắn là bạn đã cài ngôn ngữ C18 vào. Chọn Project -> Project Winrar -> Chọn con PIC 18F4620 -> Next
    Bước 2: Chỗ Active Toolsuite chọn Microchip C18 toolsuite, phía dưới là bạn phải chọn đúng đường dẫn file mpasmwin.exe, mplink.exe, v.v -> Next.
    Bước 3: bạn phải tạo 1 Project, tạo 1 thư mục, đặt tên cái Project của bạn, chẳn hạn trong trường hợp này thư mục tên là DemLed7DoanTimer0, còn tên project là Timer0.mcp chẳn hạn -> Next
    Bước 4: Next và Finish.
    - Mình nghĩ chắc ko cần hình minh họa tạo project đâu nhỉ.
    - Tiếp theo các bạn chọn New File, viết đại 1 cái gì vào đó rồi ta mới save lại được. Save vào cùng thư mục Project nảy mình tạo luôn nha. Với tên là "main.c"
    - Phía bên trái chỗ Source File, bạn click phải lên đó chọn Add Files, tìm đến file main.c nảy mình tạo, nhấn open để add file main.c vào Source File.
    - Giờ thì ta bắt đầu viết chương trình DemLed7DoanTimer0


    Mã:
    #include <p18c***.h>
    #include <delays.h>
    #include <timers.h> // Thu vien timers
    // CONFIGURAION
    #pragma config    OSC        =    HS    // FOSC = 25MHz
    #pragma config    FCMEN    =    OFF
    #pragma config    IESO    =    OFF
    #pragma config    PWRT    =    OFF
    #pragma config    BOREN    =    OFF
    // Bien Toan Cuc
    unsigned char BangMaAnodChung[10] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
    unsigned int Timer0BatDau    = 65535 - 1*(25000000/(4*128));
    unsigned char BaoHieu= 0;
     
    // Chuong Trinh Ngat
    #pragma interrupt ISR_Ngat
    void ISR_Ngat(void)
    {
        BaoHieu = BaoHieu + 1;
     
        WriteTimer0 (Timer0BatDau); // cap nhat lai gia tri ban dau cua Timers0
        INTCONbits.TMR0IF    = 0;// phai xoa co ngat khi ket thuc chuong trinh ngat
    }
     
     
    // Chuong Trinh Con
    void HienThiLed7Doan(unsigned int Dem)
    {
        unsigned char Chuc, DonVi;
     
        // Tinh Toan
        Chuc = Dem / 10;
        DonVi = (Dem % 10) / 1;
     
        // Hien thi don vi
        LATE    =    0b00000001; // Kich chan E0
        LATD    =    BangMaAnodChung[DonVi]; // Nap font vao PORT D
        Delay1KTCYx(50);
     
        // Hien thi chuc
        if (Chuc > 0)
        {
            LATE    =    0b00000010; // Kich chan E1
            LATD    = BangMaAnodChung[Chuc]; //Nap font vao PORT D
            Delay1KTCYx(50);
        }
    }
     
    #pragma code interrupt_vector = 0x08
    void int_function(void)
    {
        _asm
            GOTO    ISR_Ngat
        _endasm
    }
     
    #pragma code
     
    // Main
    void main(void)
    {
        TRISD    =    0x00;    // Cho phep PortD out --> xuat du lieu ra Led7 doan
        TRISE    =    0x00;    // Cho phep PortE out --> chan kich cho Led7 doan
     
        RCONbits.IPEN    =    0;// Su dung 1 muc ngat
        INTCONbits.GIE    =    1;// Bat ngat toan cuc
        INTCONbits.PEIE =    1;// Tat ngat ngoai vi
     
        OpenTimer0(TIMER_INT_ON & T0_16BIT & T0_SOURCE_INT & T0_PS_1_128);
        // Su dung ngat Timers0, che do 16 bit, nguon xung thach ach Fosc/4, prescaler = 128
     
        WriteTimer0 (Timer0BatDau);
        while (1)
        {
            if(BaoHieu <= 99)
            HienThiLed7Doan(BaoHieu);
            else
            BaoHieu = 0;
        }
    }
    - Mô phỏng trên Proteus.




    - Mình có đính kèm file code và mô phỏng. Hy vọng mọi người hiểu rõ hơn về Timer0 cũng như cách xử lý và làm việc của ngắt Timer0. Thân chào mọi người

  8. #8
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    • bạn ơi cho mih hỏi với công thức nay :​Timer bắt đầu = 2^số bít timer - 1 - timer*(Fosc/(4*Prescaler))

      mih cần tạo thời gian là 1s với phần cứng sử dụng thạch anh 4mhz, chế độ 8 bit,mih sử dụng 1 trong những bộ chia tần prescaler từ 1:2,1:4,1:8,1:16,1:32,1:64,1:128,1:256 vào công thức trên kết quả âm. (ở đây mih sử dụng pic 16f84a)​

  9. #9
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Trích dẫn Gửi bởi toanhnam
    • bạn ơi cho mih hỏi với công thức nay :​Timer bắt đầu = 2^số bít timer - 1 - timer*(Fosc/(4*Prescaler))

      mih cần tạo thời gian là 1s với phần cứng sử dụng thạch anh 4mhz, chế độ 8 bit,mih sử dụng 1 trong những bộ chia tần prescaler từ 1:2,1:4,1:8,1:16,1:32,1:64,1:128,1:256 vào công thức trên kết quả âm. (ở đây mih sử dụng pic 16f84a)​
    Với phần cứng mà ko thay đổi được thì chỉ còn cách thay đổi phần mềm. Con này mình mới tra datasheet thì chỉ có timer0 8 bit. Như bạn nói thì prescaler bạn thử hết mà vẫn âm. Vậy thì mình chỉ còn 1 cách tạo ra 1s là cho nó vào vòng lặp.
    - Bạn lấy timer = 50ms. Bạn phải lặp 20 lần như thế để nó là 1s. Như vậy ta có timer = 50/1000. Bạn thay vào công thức trên tính ra Timer cần cài đặt là ~ 60. Cứ mỗi lần sinh ra ngắt timer thì nó tăng lên 1, rồi lại reset timer0 về giá trị ban đầu. Đủ 20 lần tức s thì ta set 1 biến gì đó lên 1 để thực hiện chương trình ta làm.
    - Tất nhiên với cách này bạn sẽ thấy con số 60 này đã dc làm tròn. Mà ta lại lặp đến 20 lần. Sinh ra 1s sẽ ko chuẩn cho lắm. Tạm chấp nhận được với 1s kiểu này thôi Mình nghĩ bạn nên dùng con pic khác có timer 16 bit xài 1s cho chuẩn 1 tý.
    - Ko biết các cao nhân khác có ý gì hay hơn ko nhỉ
    Thân.

  10. #10
    Ngày tham gia
    Feb 2016
    Bài viết
    0
    mình đang dùng pic 18f4550 để điều khiển động cơ RC... mình cần dùng timer0 và ngắt timer0. nhưng mình chưa bik ji! có ai hướng dẫn cách lập trình dùng mplab c18 zùm với!

 

 
Trang 1 của 5 123 ... CuốiCuối

Quyền viết bài

  • Bạn Không thể gửi Chủ đề mới
  • Bạn Không thể Gửi trả lời
  • Bạn Không thể Gửi file đính kèm
  • Bạn Không thể Sửa bài viết của mình
  •  
Múi giờ GMT +7. Bây giờ là 04:47 AM. Diễn đàn sử dụng vBulletin® Phiên bản 4.2.5.
Bản quyền của 2018 vBulletin Solutions, Inc. Tất cả quyền được bảo lưu.
Ban quản trị không chịu trách nhiệm về nội dung do thành viên đăng.