You are on page 1of 13

1 Timer-Counter0

1 Timer 0
Timer là hàm tạo trễ thời gian giống như hàm delay()
__delay_ms(5): trễ 5 ms
a): Sử dụng T0 tạo ra hàm phát hiện khoảng thời gian 1 ms
TMR0 thanh ghi 8 bit chứa giá trị đếm TIMER0. Thạch anh sử dụng tần số 20Mhz , chu kì máy
trong 1 s là 20M/4 =5M chu ki máy tương ứng 1ms có 5000 chu kì máy .Vì timer0 sử dụng 8 bit
nên thanh ghi TMR0 chưa giá trị từ 0-255 giá trị nên ta phải sử dụng bộ chia . ta sử dụng bộ chia
32 thì số lần đếm = 5000/32=156 lần đếm ở đây ta không thể dùng bộ chia 2,4,8,16 vì số lần
đếm vượt quá 255 Vậy nên dùng từ bộ chia 32 trở đi, vậy ta cần nạp 1 giá trị trước cho timer
cho tới khi nó tràn(đếm tới 255) thì đủ 156 lần đếm với bộ chia 32 ta cần nạp giá trị ban đầu
cho timer0 là 255-156=100 vào TMR0
Timer thì dùng xung nội , counter dùng xung ngoại
void delay_timer0_1ms(unsigned int time)
{
while (time--) //lặp lại time lần 1ms.
{
OPTION_REGbits.T0CS = 0; //Dùng xung nội
OPTION_REGbits.PSA = 0; //Dùng bộ chia timer0
OPTION_REGbits.PS2 = 1;
OPTION_REGbits.PS1 = 0;
OPTION_REGbits.PS0 = 0; //Chọn bộ chia 1:132
TMR0 = 100; //Đặt giá trị cho TMR0
while(!INTCONbits.TMR0IF); //Đợi cờ tràn
INTCONbits.TMR0IF = 0; //Xóa cờ tràn
}
}
Vd: Muốn tạo trễ 5ms sử dụng timer0 thì khai báo hàm delay_timer0_1ms(5)
Muốn tạo trễ 10ms sử dụng timer0 thì khai báo hàm delay_timer0_1ms(10)
VD Hiện thị số 0902 lên Led 7 thanh sử dụng timer 0
**Code:

#include <pic.h>
#include <pic16f877a.h>
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#define _XTAL_FREQ 20000000
#define c1 RC0;
#define c2 RC1;
#define c3 RC2;
#define c4 RC3;

unsigned char Anode[10] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80,0x90};
void delay_timer0_1ms(unsigned int time)
{
while (time--) //lặp lại time lần 1ms.
{
OPTION_REGbits.T0CS = 0; //Dùng xung nội
OPTION_REGbits.PSA = 0; //Dùng bộ chia timer0
OPTION_REGbits.PS2 = 1;
OPTION_REGbits.PS1 = 0;
OPTION_REGbits.PS0 = 0; //Chọn bộ chia 1:132
TMR0 = 100; //Đặt giá trị cho TMR0
while(!INTCONbits.TMR0IF); //Đợi cờ tràn
INTCONbits.TMR0IF = 0; //Xóa cờ tràn
}
}

void hienthi()
{
c1=0;PORTB=Anode[0]; delay_timer0_1ms(5);c1=1;
c2=0;PORTB=Anode[9]; delay_timer0_1ms(5);c2=1;
c3=0;PORTB=Anode[0]; delay_timer0_1ms(5); c3=1;
c4=0;PORTB=Anode[2]; delay_timer0_1ms(5); c4=1;
}
void main(void)
{
TRISB=0x00;//cong B là đầu ra
TRISC=0x00;// cong C là đau ra
while(1)
{
hienthi()

}
Bài 2: Sử dụng T1 tạo ra hàm phát hiện khoảng thời gian 1 ms
Timer 1 gồm 16 bit
TMR1H và TMR1L là 2 thanh ghi chứa giá trị đếm TIMER0. Thạch anh sử dụng tần số 20Mhz ,
chu kì máy trong 1 s là 20M/4 =5M chu ki máy tương ứng 1ms có 5000 chu kì máy .Vì timer1sử
dụng 16 bit nên timer1 chứa giá trị từ 0-60536 giá trị nên ta phải sử dụng bộ chia 1 :1 thì số lần
đếm = 5000/1=5000 lần đếm, ở đây ta có thể dùng bộ chia 2,4,8 thỏa mãn vì k vượt quá 60536 .
Ta nạp giá trị TMR1H:TMR1L =65536-5000=60536.Ban đầu ta đưa giá trị 60536 vao 8 bit cao
cua thanh ghi TMR1H sau đó dịch về 8 bit thấp. Sau đó xóa đi 8 bit cao va giữ lại 8 bit thấp nạp
vào thanh ghi TMR1L cho timer họat động

Code
void delay_timer1_1ms(unsigned int time)

{
while(time--)// so lan lap lai time lan
{

TMR1H=60536>>8;// dua gia tri 60536 vao 8 bit cao cua thanh ghi TMR1H sau do
dich ve 8 bit thap
TMR1L=60536&0X00FF;// xoa di 8 bit cao va giu lại 8 bit thap nap vao thanh ghi
TMR1ON=1;// bật timer1
while(!TMR1IF);// dợi cờ tràn =1
TMR1IF=0;// xóa cờ tràn
TMR1ON=0;// timer1 ngừng đếm
TMR1CS=0;// dùng xung nội
// dùng bộ chia tỷ lệ 1:1
T1CONbits.T1CKPS1=0;
T1CONbits.T1CKPS0=0;
}
}
VD Muốn tạo trễ 5ms sử dụng timer1 thì khai báo hàm delay_timer1_1ms(5)
2 Counter0
Dùng để đếm giá trị khi có tác động vào bên ngoài, xung tác động được lấy từ chân RA4/T0CK1,
giá trị đếm sẽ được lưu trong thanh ghi TMR0, khi tràn timer (tối đa 255 giá trị thì TMR0 trở về
giá trị ban đầu do người lập trình mong muốn)
Counter0 có thể đếm tối đa từ 0 đến 255
Ví dụ1: chương trình chính đếm 100 sản phẩm hiển thị LED 7 thanh sử dụng counter0:

*Code:
#pragma config FOSC = HS
#pragma config WDTE = OFF
#pragma config PWRTE = OFF
#pragma config BOREN = OFF
#pragma config LVP = OFF
#pragma config CPD = OFF
#pragma config WRT = OFF
#pragma config CP = OFF
#include <xc.h>
#include <pic.h>
#include<pic16f877a.>
#include <stdio.h>
#include <stdlib.h>
#define c1 RC0;
#define c2 RC1;

#define_XTAL_FREQ2000000

unsigned char Anode[10] = {0xC0 , 0xF9 , 0x0A4 , 0xB0 , 0x99 ,


0x92 ,0x82 , 0xF8 , 0x80 , 0x90 };

int dem=0;
void hien_thi(int dem)
{ int chuc , donvi;
chuc =dem/10;
donvi = dem%10;

c1=0;PORTB=Anode[chuc]; __delay_ms (10);c1=1;


c2=0;PORTB=Anode[donvi];__ delay_ms(10);c2=1;
}
void main(void)
{
TRISA4 = 1; //RA4 là đầu vào
TRISB = 0;
TRISC0 = 0;
TRISC1 = 0;
OPTION_REGbits.T0CS = 1 ; // dem xung ngoai
OPTION_REGbits.PSA = 1 ; // chon bo chia WDT

while(1)
{ dem= TMR0; // Gan gia tri dem cho TMR0
hien_thi(dem); // Hien thị ra led 7
thanh if(dem == 100) // đếm 100 sp
{
dem= 0;

}
}
}
Giải thích: ⇨ Khi có sản phẩm sẽ tác động xung (tín hiệu) vào chân RA4
làm tăng TMR0 , sau đó gán biến “dem” bằng giá trị TMR0 và hiển thị ra
LED 7 thanh
 Khi có sản phẩm tác động chân RA4 có tín hiệu (tùy vào loại cảm biến)
🡺 Couter nhận và tăng biến TMR0 lên 1 lần , sau đó gán giá trị TMR0 cho
biến “dem” , chương trình chính thực hiện hiển thị “dem”.
 TMR0 lên đến 100 thì quay về 0 (giá trị tối đa tùy chỉnh trong phạm vi 8
bit)

Ví dụ :viết chương trình chính đếm 100 sản phẩm hiển thị LCD sử dụng counter0:
Dưới đây là chương trình chính, cần coppy thư viện LCD

Code:
#pragma config FOSC = HS

#pragma config WDTE = OFF

#pragma config PWRTE = OFF

#pragma config BOREN = OFF


#pragma config LVP = OFF

#pragma config CPD = OFF

#pragma config WRT = OFF

#pragma config CP = OFF

#include <xc.h>

#include <pic.h>

#include <pic16f877a.h>

#include <stdio.h> #include <stdlib.h>

#define _XTAL_FREQ 20000000

[..Thư viện LCD..]

void main(void)

unsigned char b[3], dem =0;

TRISA4= 1;//RA4 là đầu vào

TRISD = 0x00;// cong D la dau ra

OPTION_REGbits.T0CS=1; //dem xung ngoai

OPTION_REGbits.PSA=1; // chon bo chia WDT

TMR0=0;

Lcd_Init();

while(1)

sprintf(b,"san pham:%d",dem);

Lcd_Set_Cursor(1,1);

Lcd_Write_String(b);

dem = TMR0; // Gan gia tri dem cho TMR0


if(dem == 100)

TMR0=0;

dem=0;

Counter1:
Dùng để đếm giá trị khi có tác động vào bên ngoài, xung tác động được lấy từ chân
RC0/T1CK1, giá trị đếm sẽ được lưu trong thanh ghi TMR1, khi tràn timer (tối đa 2^16 giá trị
thì TMR1 trở về giá trị ban đầu do người lập trình mong muốn)
Cuonter1 có thể đếm từ 0 đến 2^16

!!!!!!!!Counter1 chỉ khác counter 0 khi khởi tạo, thuật toán như nhau!!!!!!!!

Ví dụ: chương trình chính đếm 1000 sản phẩm sử dụng counter 1 hiển
thị LCD:
**CODE
#pragma config FOSC = HS

#pragma config WDTE = ON

#pragma config PWRTE = ON

#pragma config BOREN = OFF

#pragma config LVP = OFF

#pragma config CPD = OFF

#pragma config WRT = OFF

#pragma config CP = OFF

#define _XTAL_FREQ 20000000

#include <xc.h> #include <pic.h>

#include <pic16f877a.h>

[…thư viện LCD..]

void main(void)

unsigned char b[20];

unsigned int dem = 0;

T1CONbits.TMR1CS = 1; //chọn nguồn xung clock từ bên ngoài ở chân RC0/T1OSO/T1CKI (cạnh lên)

T1CONbits.T1SYNC = 0; // đồng bộ ngõ vào clock từ bên ngoài

T1CONbits.TMR1ON = 1; // Cho phép timer1 đếm

TRISC0 = 1;// RC0 la dau vao

TRISD = 0x00;// cong D la dau ra

Lcd_init();

while (1)

sprintf(b,"san pham:%d",dem);
Lcd_Set_Cursor(1,1);

Lcd_Write_String(b);

dem=TMR1;// gan dem cho TMR1

if(dem>=1000) // chỉ đếm tối đa 1000 roi quay lại 0

dem=0;

Ví dụ: chương trình chính đếm 1000 sản phẩm sử dụng counter 1 hiển
thị LED 7 thanh

**CODE:
#pragma config FOSC = HS

#pragma config WDTE = ON

#pragma config PWRTE = ON

#pragma config BOREN = OFF


#pragma config LVP = OFF

#pragma config CPD = OFF

#pragma config WRT = OFF

#pragma config CP = OFF

#define _XTAL_FREQ 20000000

#include <xc.h>

#include <pic.h>

#include <pic16f877a.h>

#define c1 RC0;

#define c2 RC1;

#define c3 RC2;

#define c4 RC3;

const unsigned Anode[10] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90};

int TMR1=0;

void hien_thi (int dem)

int ng,tr,ch,dv;
ng=dem/1000;
tr=dem%1000/100;
ch=dem%1000%100/10;
dv=dem%10;
c1=0;PORTB=Anode[ng];__delay_ms(5);c1=1;
c2=0;PORTB=Anode[tr];__delay_ms(5);c2=1;
c3=0;PORTB=Anode[ch];__delay_ms(5);c3=1;
c4=0;PORTB=Anode[dv];__delay_ms(5);c4=1;
}

void main()
{

T1CONbits.TMR1CS = 1; //chọn nguồn xung clock từ bên ngoài ở chân RC0/T1OSO/T1CKI (cạnh lên)

T1CONbits.T1SYNC = 0; // đồng bộ ngõ vào clock từ bên ngoài

T1CONbits.TMR1ON = 1; // Cho phép timer1 đếm

TRISB =TRISD= 0;// cong B la dau ra

TRISC0=1;//RCO la dau vao

while (1)

hien_thi(dem);

dem=TMR1;

if(dem>=1000) // chỉ đếm tối đa 1000 roi quay lại 0

TMR1=0;

dem=0;

You might also like