BÀI 16 : ĐẾM TỪ 0 ĐẾN 9999 SỬ DỤNG TIMER 1 PIC16F887 XC8

9:38:00 PM
Chào các bạn trong bài đăng này mình sẽ hướng dẫn các bạn đếm từ 0 đến 9999 sử dụng TIMER 1 của PIC16F887. Trong các bai đăng trước mình đã hướng dẫn các bạn lý thuyết về TIMER 1 của PIC16F887 như vậy để thực hiện được bài hôm nay thì chúng ta phải hiểu được chức năng cũng như các thanh ghi điều khiển của nó nên trước khi bắt đầu đi vào vấn đề chính thì mình sẽ nhắc lại kiến thức về TIMER 1 cho các bạn 1 tý nha !
1.  KHẢO SÁT TIMER1 CỦA PIC 16F887
Là bộ định thời/đếm 16 bit gồm 2 thanh ghi 8 bit (TMR1H và TMR1L) –  có thể đọc và ghi. Hai thanh ghi này tăng từ 0000h đến FFFFh và quay trở lại 0000h. Khi bị tràn  thì  Timer1 sẽ phát sinh ngắt, cờ báo  ngắt TMR1IF (PIR1<0>) lên mức 1. Timer1  có bit cho phép/cấm là TMR1IE (PIE1<0>).
Cấu trúc của Timer1:
cấu trúc timer 1
Khảo sát thanh ghi điều khiển Timer1:
thanh ghi T1CON
Bit 7
Bit 6
Bit 5-4  T1CKPS1:T1CKPS0: các bit lựa chọn bộ chia - Timer1 input Clock Prescale Select bits
  • 11=1:8 giá trị chia.
  • 10=1:4 giá trị chia.
  • 01=1:2 giá trị chia.
  • 00=1:1 giá trị chia.
Bit 3  T1OSCEN: bit ĐK cho phép bộ dao động Timer1 - Timer1 Oscillator Enable Control bit
  • 1= bộ dao động được phép.
  • 0= Tắt bộ dao động.
Bit 2  T1SYNC: bit ĐK đồng bộ ngõ vào xung clock bên ngoài của timer1
Khi TMR1CS = 1:
  • 1= không thể đồng bộ ngõ vào clock ở từ bên ngoài.
  • 0= đồng bộ ngõ vào clock ở từ bên ngoài.
Khi TMR1CS = 0:
Bit này bị bỏ qua. Timer1 dùng xung clock bên trong khi TMR1CS = 0.
Bit 1  TMR1CS: bit lựa chọn nguồn xung clock của timer1 
  • 1= Chọn nguồn xung clock từ bên ngoài ở chân RC0/T1OSO/T1CKI (cạnh lên).
  • 0= Chọn xung nội bên trong (FOSC/4).
Bit 0  TMR1ON: bit điều khiển Timer1
  • 1= Cho phép Timer1 đếm.
  • 0= Timer1 ngừng đếm.
a.  Timer1 ở chế độ định thời
Nếu bit TMR1CS bằng 0  thì  T1 hoạt động  định thời đếm  xung nội có tần số  bằng FOSC/4. Bit điều khiển đồng bộ T1 SYNC không bị ảnh hưởng do xung clock bên trong luôn đồng bộ.
b.  Timer1 ở chế độ đếm xung ngoại
Nếu bit TMR1CS bằng  1  thì  T1 hoạt động  đếm  xung ngoại. Xung ngoại  có 2 nguồn xung phụ 
thuộc vào bit T1OSCEN:
Nếu bit T1OSCEN bằng 1 thì T1 đếm xung ngoại từ mạch dao động của T1 - xem hình 6-9.
Nếu bit T1OSCEN bằng 0 thì T1 đếm xung ngoại đưa đến ngõ vào T1CKI - xem hình 6-10.
Hình 6-9: T1 hoạt động đếm xung ngoại từ mạch dao động T1
Timer1 tăng giá trị khi có xung cạnh lên. Counter chỉ tăng giá trị đếm sau khi nhận 1 xung cạnh xuống được minh hoạ hình 6-11.
Hình trên thì ngõ vào đang ở mức 1, counter sẽ đếm khi có xung cạnh lên.
Hình dưới thì ngõ vào đang ở mức thấp, xung cạnh lên thứ nhất thì mạch vẫn chưa đếm, xung xuống mức thấp và khi có cạnh lên thứ 2 thì counter bắt đầu đếm.
c.  Hoạt động của Timer1 ở chế độ Counter đồng bộ
Khi bit TMR1CS bằng 1 thì T1 hoạt động ở chế độ Counter:
  • Nếu bit T1OSCEN bằng 1 thì đếm xung từ mạch dao động của T1.
  • Nếu bit T1OSCEN bằng 1 thì đếm xung cạnh lên đưa đến ngõ vào RC0/T1OSO/T1CKI.
Nếu bit T1SYNC bằng 0  thì ngõ vào xung  ngoại  được đồng bộ với xung bên trong.  Ở chế độ đồng bộ, nếu CPU ở chế độ ngủ thì Timer1 sẽ không đếm vì mạch đồng bộ ngừng hoạt động. 
d.  Hoạt động của Timer1 ở chế độ Counter bất đồng bộ
Nếu bit T1SYNC bằng 1 thì xung ngõ vào từ bên ngoài không được đồng bộ. Bộ đếm tiếp tục tăng bất đồng bộ với xung bên trong. Bộ đếm  vẫn đếm khi CPU ở trong chế độ ngủ và khi tràn sẽ phát sinh ngắt và đánh thức CPU. Ngắt T1 có thể ngăn được.
e.  Đọc và ghi Timer1 trong chế độ đếm không đồng bộ
Timer T1 cho phép đọc giá trị các thanh ghi TMR1H hoặc TMR1L khi timer đang đếm xung bất đồng bộ bên ngoài. Khi ghi thì nên ngừng timer lại rồi mới ghi giá trị mong muốn vào các thanh ghi.  Nếu  ghi  mà timer đang đếm  vẫn được  nhưng có thể tạo ra một giá trị đếm không dự đoán được  hay không chính xác.
- Ảnh mô phỏng protues.

quét led sử dụng timer 1 pic16f887

- Đây là code chương trình.
#include <stdio.h>
#include <stdlib.h>
#define _XTAL_FREQ 8000000
#include <xc.h>
// CONFIG1
#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator: High-speed crystal/resonator on RA6/OSC2/CLKOUT and RA7/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled and can be enabled by SWDTEN bit of the WDTCON register)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = OFF      // RE3/MCLR pin function select bit (RE3/MCLR pin function is digital input, MCLR internally tied to VDD)
#pragma config CP = OFF         // Code Protection bit (Program memory code protection is disabled)
#pragma config CPD = OFF        // Data Code Protection bit (Data memory code protection is disabled)
#pragma config BOREN = OFF      // Brown Out Reset Selection bits (BOR disabled)
#pragma config IESO = OFF       // Internal External Switchover bit (Internal/External Switchover mode is disabled)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is disabled)
#pragma config LVP = OFF        // Low Voltage Programming Enable bit (RB3 pin has digital I/O, HV on MCLR must be used for programming)
// CONFIG2
#pragma config BOR4V = BOR40V   // Brown-out Reset Selection bit (Brown-out Reset set to 4.0V)
#pragma config WRT = OFF        // Flash Program Memory Self Write Enable bits (Write protection off)
unsigned int Count = 0;
unsigned int dem = 0,nghin,tram,chuc,donvi;
const unsigned char maled[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};
void display(void);
void main(void)
{
    TMR1 = 15535;
    T1CONbits.TMR1CS = 0;
    T1CONbits.T1CKPS1 = 1;
    T1CONbits.T1CKPS0 = 0;
    T1CONbits.T1SYNC = 1;
    T1CONbits.TMR1ON = 1;
    TRISC = 0;
    PORTC = 0;
    TRISDbits.TRISD0 = 0;
    TRISDbits.TRISD1 = 0;
    TRISDbits.TRISD2 = 0;
    TRISDbits.TRISD3 = 0;
    PORTD = 0;
    while (1)
    {
        display();
        if(PIR1bits.TMR1IF == 1)
        {
            PIR1bits.TMR1IF = 0;
            TMR1 = 15535;
            Count++;
            if(Count==3)
            {
                Count =0;
                dem++;
                if(dem==1000)
                {
                    dem=0;
                }
            }
        }
    }
}
void display (void)
{
    nghin = dem/1000;
    tram = (dem - nghin*1000)/100;
    chuc = (dem - nghin*1000 - tram*100)/10;
    donvi = dem - nghin*1000 - tram*100 - chuc*10;
    
    PORTC = maled[nghin];
    RD0=0;
    __delay_ms(5);
    RD0=1;
    
    PORTC = maled[tram];
    RD1=0;
    __delay_ms(5);
    RD1=1;

    PORTC = maled[chuc];
    RD2=0;
    __delay_ms(5);
    RD2=1;

    PORTC = maled[donvi];
    RD3=0;
    __delay_ms(5);
    RD3=1;

}
- Link download project Click here

Share this

Related Posts

Previous
Next Post »