Thứ Tư, 28 tháng 11, 2018

Bài 11. PIC 18F450 Timer/Counter


Giới thiệu

Bộ định thời trong bộ vi điều khiển được sử dụng để giới thiệu độ trễ, đếm các sự kiện, tạo ra dạng sóng và cũng cho việc tạo PWM.
Sự chậm trễ trong vi điều khiển có thể được gây ra bởi một trong hai cách -
  1. Cung cấp độ trễ bằng phần mềm (thông qua mã sử dụng vòng lặp). Tuy nhiên, một sự chậm trễ được cung cấp theo cách này buộc vi điều khiển đặt tất cả các tài nguyên của nó để xử lý các vòng lặp, và do đó ngăn chặn việc thực thi mã.
  2. Cung cấp độ trễ bằng bộ hẹn giờ trong vi điều khiển. Trong phương pháp này, sự chậm trễ được cung cấp bằng cách tải một số đếm trong bộ đếm thời gian. Vì vậy, khi ngắt thời gian được tạo ra, việc thực thi hiện tại sẽ chuyển sang ISR để phục vụ nhiệm vụ. Nhưng khi không có bộ đếm thời gian gián đoạn nó sẽ thực hiện một nhiệm vụ khác. Vì vậy, chúng ta có thể nói nó là loại chức năng không chặn.
Hãy để chúng tôi thảo luận về bộ đếm thời gian trong vi điều khiển PIC18F4550.
PIC18F4550 có 4 bộ hẹn giờ tích hợp sẵn
  • Timer0: 16 bit
  • Timer1: 16 bit
  • Timer2: 8 bit
  • Timer3: 16 bit
Trong số bốn bộ đếm thời gian trong PIC18F4550, chúng ta sẽ thảo luận ở đây Timer1. Việc làm việc của phần còn lại của bộ đếm thời gian là như nhau. Để tạo thời gian trễ bằng Timer1, chúng tôi phải tính thời gian mong muốn.
 
Làm thế nào để tính toán đếm cho Timer?
Hãy lấy một ví dụ. Giả sử chúng ta phải tạo ra độ trễ 1 ms có tần số dao động 8 MHz của PIC18F4550. Để làm điều này, chúng ta cần tìm chu kỳ của chu trình chỉ dẫn.
Fosc = 8 MHz
Bộ đếm thời gian PIC18F4550 sử dụng tần số như sau:
          FTIMER = \ frac {Fosc} {4}
FTIMER = 8 MHz / 4 = 2 MHz
Tần số 2 MHz này được cấp cho bộ định thời PIC.
Sau đó, để tìm khoảng thời gian sẽ được bộ đếm thời gian thực hiện để tăng số lượng,
          Khoảng thời gian = \ frac {1} {FTIMER}
Khoảng thời gian = 1/2 MHz = 0,5 chúng tôi
Do đó, sau mỗi 0,5 lần thời gian chúng tôi trôi qua, giá trị bộ đếm thời gian sẽ được tăng thêm 1.
Để tìm số lượng cần thiết cho sự chậm trễ 1 ms,
Đếm = Thời gian trễ / hẹn giờ mong muốn
           Đếm = \ frac {Trì hoãn mong muốn} {Timer Period}
Đếm = 1 ms / 0,5 chúng tôi = 2000
Trước khi chúng ta tải số này trong bộ đếm thời gian, trước tiên chúng ta cần trừ nó từ 65536. Lý do chúng ta cần trừ nó là bởi vì bộ đếm thời gian là 16-bit. Vì thế,
65536 - đếm = 65536 - 2000 = 63536
Chuyển đổi số này thành hex, chúng ta nhận được 0xF830 . Tải giá trị hex này trong thanh ghi TMR1 Timer1 tức là. TMR1 là thanh ghi 16 bit được sử dụng để tải số đếm cho Timer1.

PIC18F4550-Timer1-đếm-dạng sóng
PIC18F4550 Tạo dạng sóng sử dụng bộ hẹn giờ

Ngắt Timer1

Thanh ghi TMR1 được tăng lên từ giá trị được nạp này với giá trị cao nhất là 0xFFFF. Sau khi tràn xảy ra trong thanh ghi, nó đặt lại thành 0 và cờ ngắt tràn TMR1IF được thiết lập.
PIC18F4550 Timer làm việc
PIC18F4550 Timer làm việc
Các thanh ghi TMR1H và TMR1L cũng có thể được sử dụng riêng lẻ để tải số đếm trong Timer1. Đây là cả hai thanh ghi 8 bit.
Để sử dụng Timer1 trong PIC18F4550, thanh ghi điều khiển và trạng thái được sử dụng. Hãy để chúng tôi hiểu thêm về các thanh ghi này của Timer1 trong PIC18F4550.
T1CON : Timer1 Control Register
  • Nó được sử dụng để cấu hình Timer1 và cũng để khởi động Timer1.
PIC18F4550 Timer1 kiểm soát đăng ký
RD16 : bit kích hoạt chế độ đọc / ghi 16 bit
1 = Cho phép đọc / ghi Timer1 trong một thanh ghi 16 bit là TMR1.
0 = Cho phép đọc / ghi Timer1 trong hai thanh ghi 8 bit là TMR1H và TMR1L
T1RUN : Timer1 trạng thái đồng hồ hệ thống bit
1 = Đồng hồ thiết bị bắt nguồn từ bộ dao động Timer1
0 = Đồng hồ thiết bị có nguồn gốc từ một nguồn khác; nó có thể là bộ dao động nội bộ hoặc bộ dao động tinh thể bên ngoài.
T1CKPS1: T1CKPS0 : Timer1 đầu vào đồng hồ trước quy mô bit
Các bit này chia đồng hồ cho một giá trị trước khi nó được áp dụng cho Timer1 làm đồng hồ.
11 = 1: 8 giá trị quy mô trước
10 = 1: 4 giá trị trước quy mô
01 = 1: 2 giá trị quy mô trước
00 = 1: 1 giá trị quy mô trước
T1OSCEN : Timer1 dao động cho phép bit
1 = Bật bộ dao động Timer1.
0 = Tắt bộ dao động Timer1.
T1SYNC : Timer1 bit đồng bộ đầu vào đồng hồ bên ngoài
Khi TMR1CS = 0
Timer1 sử dụng bộ dao động xung nhịp bên trong. Vì vậy, bit này được bỏ qua.
Khi TMR1CS = 1
1 = Không đồng bộ hóa đầu vào đồng hồ bên ngoài.
0 = Đồng bộ hóa đầu vào đồng hồ bên ngoài.
TMR1CS : Timer1 chọn nguồn đồng hồ bit
1 = Đồng hồ ngoài từ RC0 / T1OSO / T13CKl
0 = Đồng hồ bên trong (F osc / 4)
Bit này thường được sử dụng để đếm các sự kiện. Để sử dụng Timer1 làm bộ đếm, hãy đặt TMR1CS = 1.
TMR1ON : Timer1 ON bit
1 = Bắt đầu Timer1.
0 = Dừng Timer1.
Sau khi Timer1 khởi tạo, nó liên tục giám sát cờ ngắt TMR1IF được thiết lập khi Timer1 tràn. TMR1IF nằm trong PIR1register như hình dưới đây.  
PIR1: Đăng ký ngắt ngoại vi
PIC18F4550 Đăng ký ngắt ngoại vi
Đăng ký PIR
TMR1IF: Cờ ngắt tràn Timer1
       0 = Lỗi tràn đăng ký Timer1 không xảy ra
       1 = Đã xảy ra tràn đăng ký Timer1
TMR2IF: Cờ ngắt tràn Timer2
CCP1IF: Chụp / So sánh Cờ ngắt
SSPIF: Cờ ngắt cổng nối tiếp đồng bộ chính
RCIF và TXIF: Đây là cờ ngắt liên lạc nối tiếp
ADIF: Cờ ngắt chuyển đổi A / D
SPPIF: Thẻ ngắt đọc / ghi cổng song song trực tuyến

Các bước lập trình PIC18F4550

  1. Cấu hình thanh ghi T1CON.
  2. Xóa cờ ngắt TMR1IF Timer1.
  3. Tải số đếm trong TMR1 16 bit hoặc TMR1H (byte cao hơn) và TMR1L (byte thấp hơn).
  4. Đặt TMR1ON để bắt đầu hoạt động Timer1.
  5. Đợi TMR1IF = 1. Đặt bit này thành '1' cho biết rằng đếm đếm Timer1 từ 0xFFFF đến 0x0000.

Thí dụ

Hãy để chúng tôi tạo ra một sự chậm trễ của 1 ms bằng cách sử dụng Timer1.
#include "osc_config.h"  /* Configuration header file */
#include <pic18f4550.h>  /* Contains PIC18F4550 specifications */

#define Pulse LATB    /* Define Pulse as LATB to output on PORTB */

void Timer1_delay();

void main()
{
    OSCCON=0x72;    /* Configure oscillator frequency to 8MHz */
    TRISB=0;     /* Set as output port */
    Pulse=0xff;    /* Send high on PortB */
    
    while(1)
    {
        Pulse=~Pulse;    /* Toggle PortB at 500 Hz */ 
        Timer1_delay();   /* Call delay which provide desired delay */    
    }   
}

void Timer1_delay()
{
    /* Enable 16-bit TMR1 register, No pre-scale, internal clock,timer OFF */
    T1CON=0x80;  

    TMR1=0xf830;  /* Load count for generating delay of 1ms */
    T1CONbits.TMR1ON=1;   /* Turn ON Timer1 */
    while(PIR1bits.TMR1IF==0);  /* Wait for Timer1 overflow interrupt flag */
    TMR1ON=0;     /* Turn OFF timer */
    TMR1IF=0;     /* Make Timer1 overflow flag to '0' */
}

Bộ đếm thời gian sử dụng ngắt

Tạo độ trễ của 1 ms bằng cách sử dụng ngắt
Sử dụng Timer1 bằng cách gọi một gián đoạn dịch vụ thường xuyên (ISR) loại bỏ việc bỏ phiếu liên tục của cờ TMR1IF. Ngoài ra, vi điều khiển có thể thực hiện các tác vụ khác cho đến khi xảy ra gián đoạn. Để sử dụng ISR để tạo trễ bằng Timer1, ba bit cần được kích hoạt - hai bit trong thanh ghi INTCON và một trong thanh ghi PIE.
INTCON : Đăng ký kiểm soát ngắt
Đăng ký kiểm soát ngắt PIC18F4550
Đăng ký INTCON
Hai bit - GIE và PEIE - trong thanh ghi INTCON, như được hiển thị ở trên, cần phải được kích hoạt.
GIE: Global Interrupt Enable
Bật ngắt toàn cầu cho ISR để tạo chậm trễ.
PEIE: Ngắt ngoại vi cho phép
Đối với một số ngắt ngoại vi như TMR1IF, TMR2IF và TXIF, chúng ta phải kích hoạt bit PEIE cùng với bit GIE.
Bit thứ ba tức là TMR1IE trong thanh ghi PIE1 có thể được sử dụng để kích hoạt cờ ngắt Timer1 (TMR1IF).
PIE1 : Kích hoạt ngắt ngoại vi
Kích hoạt ngoại vi PIC18F4550
Đăng ký PIE
TMR1IE : Timer1 tràn đột ngột cho phép Bit
 1 = Bật ngắt tràn TMR1
 0 = Tắt ngắt dòng TMR1
Lưu ý: Trong khi tạo ra một sự chậm trễ bằng cách sử dụng ISR, chương trình mất nhiều thời gian hơn để chuyển sang ISR. Do đó, để tránh điều này, chúng ta phải tăng số lượng để bù lại thời gian trễ.

Các bước lập trình PIC18F4550 lập trình bằng cách sử dụng ngắt

  1. Kích hoạt GIE, PEIE, TMR1IE.
  2. Cấu hình thanh ghi T1CON.
  3. Xóa cờ ngắt TMR1IF Timer1.
  4. Tải số đếm trong TMR1 16 bit hoặc TMR1H (byte cao hơn) và TMR1L (byte thấp hơn).
  5. Đặt TMR1ON để bắt đầu hoạt động Timer1.
  6. Khi TMR1IF = 1, mã sẽ chuyển sang ISR để thực hiện nó và sau khi kiểm soát thực hiện trở lại chương trình chính.
Chương trình
#include <pic18f4550.h>
#include "Configuration_Header_File.h"

void Timer1_start();

#define Pulse LATB

void main()
{ 
    OSCCON=0x72; /* Configure oscillator frequency to 8MHz */
    TRISB = 0;   /* Set as output Port */
    Pulse = 0xff;   /* Send high on PortB */
    Timer1_start();
    
    while(1);
    
}
/***************Interrupt Service Routine for Timer1******************/
void interrupt Timer1_ISR()
{
    
    TMR1=0xF856;
    Pulse = ~Pulse;   /* Toggle PortB at of 500 Hz */   
    PIR1bits.TMR1IF=0;  /* Make Timer1 Overflow Flag to '0' */
}

void Timer1_start()
{
    GIE=1;  /* Enable Global Interrupt */
    PEIE=1;    /* Enable Peripheral Interrupt */
    TMR1IE=1;  /* Enable Timer1 Overflow Interrupt */
    TMR1IF=0;
    
    /* Enable 16-bit TMR1 register,no pre-scale,internal clock, timer OFF */
    T1CON=0x80;  

    TMR1=0xF856; /* Load Count for generating delay of 1ms */
    TMR1ON=1;  /* Turn ON Timer1 */
}


Code mô phỏng
Tệp đính kèm


1 nhận xét:

  1. cho mình hỏi trên code chỗ nào là chọn bộ chia v ad

    Trả lờiXóa