Hỏi về bài Timer0 :-s

Kisses Hacker

Art Supporter
Staff member
Em đang làm bài nhấn nút 3 lần để thay đổi trạng thái LED mà làm mãi không xong :| Trên lớp các anh đã soạn code bài này, em gõ theo nhưng vẫn chưa chạy được (không chắc gõ giống hết vì hôm đó em chỉ xem được 1 phần màn hình).

Đoạn code: (nối port LED với port D).
Code:
// Description:
// PICC6
// Bai 2: Timer0

// Import
#include <htc.h>   // thu vien HTC compiler
__CONFIG(FOSC_HS & WDTE_OFF & PWRTE_ON & MCLRE_ON & CP_OFF & BOREN_OFF & IESO_OFF & FCMEN_OFF & LVP_OFF & DEBUG_OFF); // 1st config. Word
__CONFIG(BOR4V_BOR21V); // 2st config. Word
#define _XTAL_FREQ 4000000 // crystal 4Mhz

void InitPort();
void InitTimer0();

// Main program
void main()
{
	InitPort();
	InitTimer0();
	
	TMR0 = 0x00;
	while(1);
}

void InitPort()
{
	ANSEL = 0;
	ANSELH = 0;
	TRISA = 1;
	TRISD = 0;	// PORT D is output
	PORTD = 0x00;
}

void InitTimer0()
{
	T0CS = 1;	// Mode counter
	T0SE = 1;	// Increment when 1 -> 0
	PSA = 1;
	TMR0 = 253;
	T0IF = 0;
	T0IE = 1;
	GIE = 1;
}

void interrupt isr()
{
	if (T0IE && T0IF)
	{
		[COLOR="red"]__delay_ms(100);
		if (RA0 == 0)[/COLOR]
		{
			PORTD ^= 0xFF;
			TMR0 = 253;
			T0IF = 0;
		}
	}  
}
Cho em hỏi:

1. Hàm delay nằm trong chương trình ngắt để làm gì.

2. Khi có xung từ nút nhấn vào chân T0CKI, bit TMR0 tăng lên 1, khi TMR0 đến 255, tăng 1 lần nữa (xuống 0) thì bật cờ T0IF, chương trình nhảy vào ngắt để nháy đèn. Vậy tại sao trong ngắt lại có lệnh if (RA0 == 0) để kiểm tra phím nữa vậy?
 

thienminh_npn

Thành Viên PIF
Hi, cho em em nhóm nào thế?

Solution: em thử xóa dòng TMR0=0x00 trong hàm main sau InitTimer0() xem. Ý đồ của bài này là nhấn button 3 lần thì sẽ tràn thanh ghi giá trị đếm timer TMR0(253->254->255->0 : 3 pulses) thì nhảy vào ngắt, trong ngắt ta đổi trạng thái led nối vs portd. Sau khi em khởi tạo bằng InitTimer0(), em gán lại TMR0 là 0 thì có phải phải bấm 255 phát led mới đổi trạng thái k?

Hàm __delay_ms(100) là để chống rung phím. Phím sau khi bấm sẽ chuyển từ 1 sang 0, 0 sang 1 rất nhiều lần. Nếu không có delay thì chương trình ngắt chỉ chạy khoảng vài chục micro giây sau khi thoát ra sẽ gặp một chuyển trạng thái nữa nên hiều là bấm hơn một lần -> hiểu là bấm hơn một lần.

Kiềm tra lại RA0==0 cũng là để chống rung phím. Nếu nhảy vào ngắt mà ta thấy RA0 (nút) đã được bấm thì mới đảo trạng thái ngắt. Em có thể thử bỏ nó và xem kỹ năng bấm của mình có nhanh như điện không nhé.
 

danganhtuan1992

Trứng gà
Mình có vài góp ý cho đoạn code của bạn:
Trong phần InitPort, TRISA=0xff chứ không phải là 1 do thanh ghi A dài 8 bit, tương tự TRISD=0x00 chứ không phải là 0.
Trong main, bạn bỏ dòng TMR0=0 đi, vì trong InitTimer0 đã đặt TMR0=253 rồi, 253 thì nhấn 3 lần mới về lại 0.
1/2/Hàm delay trong if là để chống rung nút nhấn, kết hợp với if(RA4==0) (không phải RA0,bạn nhầm chỗ đó, do chân T0CKI là RA4, cái này bạn xem trong datasheet)
Có thêm if(RA4==0) là khi bạn nhấn phím tới lần 3 thì chương trình nhảy vào ngắt,delay 1 khoảng tg là 100ms thì bắt đầu kiểm tra nút nhấn của bạn, nếu nút bạn vẫn ỡ mức 0~đang giữ phím thì chứng tỏ bạn nhấn thực sự, mục đích là để chống rung mà thôi.
 

Kisses Hacker

Art Supporter
Staff member
Em trong nhóm 4 :D

Lệnh TMR0 = 0 trong hàm main đúng là tầm pậy rồi, vậy mà mình lại không thấy =.= Còn TRISA=0xFFTRISD=0x00, không hiểu tại sao phải để như thế thì chương trình này mới chạy. Còn code cho chớp tắt LED liên tục dùng chế độ timer và prescaler (=111) thì không cần:
Code:
// Description:
// PICC6
// Bai 2: Timer0
// Chop tat LED bang xung clock timer

// Import
#include <htc.h>   // thu vien HTC compiler
__CONFIG(FOSC_HS & WDTE_OFF & PWRTE_ON & MCLRE_ON & CP_OFF & BOREN_OFF & IESO_OFF & FCMEN_OFF & LVP_OFF & DEBUG_OFF); // 1st config. Word
__CONFIG(BOR4V_BOR21V); // 2st config. Word
#define _XTAL_FREQ 4000000 // crystal 4Mhz

// Main program
void main()
{
	ANSEL = 0;
	ANSELH = 0;
	
	T0CS = 0;
	PSA = 0;

	PS1 = 1;	
	PS2 = 1;
	PS0 = 1;	
	
	GIE = 1;
	T0IE = 1;
	T0IF = 0;
	
	TMR0 = 0;
	[COLOR="red"]
	TRISA = 1;
	TRISD = 0;[/COLOR]
	
	while(1);
}

void interrupt isr()
{
	if (T0IE && T0IF)
	{
		PORTD ^= 0xFF;
		T0IF = 0;
		TMR0 = 0;
	}
}
À 2 lệnh TMR0 = 253; T0IF = 0; phải để trong if (T0IE && T0IF) nữa mới đúng :P
 

honghiep

Cố Vấn CLB
Staff member
Em trong nhóm 4 :D

Lệnh TMR0 = 0 trong hàm main đúng là tầm pậy rồi, vậy mà mình lại không thấy =.= Còn TRISA=0xFFTRISD=0x00, không hiểu tại sao phải để như thế thì chương trình này mới chạy. Còn code cho chớp tắt LED liên tục dùng chế độ timer và prescaler (=111) thì không cần:
Code:
// Description:
// PICC6
// Bai 2: Timer0
// Chop tat LED bang xung clock timer

// Import
#include <htc.h>   // thu vien HTC compiler
__CONFIG(FOSC_HS & WDTE_OFF & PWRTE_ON & MCLRE_ON & CP_OFF & BOREN_OFF & IESO_OFF & FCMEN_OFF & LVP_OFF & DEBUG_OFF); // 1st config. Word
__CONFIG(BOR4V_BOR21V); // 2st config. Word
#define _XTAL_FREQ 4000000 // crystal 4Mhz

// Main program
void main()
{
	ANSEL = 0;
	ANSELH = 0;
	
	T0CS = 0;
	PSA = 0;

	PS1 = 1;	
	PS2 = 1;
	PS0 = 1;	
	
	GIE = 1;
	T0IE = 1;
	T0IF = 0;
	
	TMR0 = 0;
	[COLOR="red"]
	TRISA = 1;
	TRISD = 0;[/COLOR]
	
	while(1);
}

void interrupt isr()
{
	if (T0IE && T0IF)
	{
		PORTD ^= 0xFF;
		T0IF = 0;
		TMR0 = 0;
	}
}
À 2 lệnh TMR0 = 253; T0IF = 0; phải để trong if (T0IE && T0IF) nữa mới đúng :P
cái TRISA=0xFF là khai báo PORTA là đầu vào, vì ta lấy xung clock từ chân RA4
 

honghiep

Cố Vấn CLB
Staff member
Anh chị cho em hỏi: phần chống rung phím sao lại đặt trong chương trình ngắt. Vì nếu đặt như vậy thì khi vào ngắt mới chống rung phím còn khi cờ ngắt chưa bật thì xung vào counter vẫn bị ảnh hưởng bởi rung phím
 

danganhtuan1992

Trứng gà
@honghiep: à đúng rồi, mình cũng thắc mắc như bạn, mình nhấn 1-3 lần là nó đổi trạng thái, chứ không phải chính xác 3 lần, vậy là bàn phím vẫn rung :(
 

tranhieu_hcmut

Cố Vấn CLB
Staff member
a đã nói là cách chống rung này là chữa cháy thôi, nó rất là "cùi bắp". Còn muốn chống rung thật tốt, phải kết hợp cả chống rung bằng phần cứng & phần mềm. Tham khảo thêm tại google.com
 
Top