Bài tập buổi 5: Timer 0

Manhdd

Cố Vấn CLB
Staff member
Bài tập về timer 0 của các bạn như sau:
- Basic level: sử dụng timer 0 với nguồn xung clock (nút nhấn) nối vào chân T0CKI (RA4), thay đổi trạng thái của led sau mỗi 3 lần nhấn nút.
- Intermediate level: Tạo 1 chương trình với 3 mode chạy led (ví dụ, mode1,2: sample1, sample2 của BT4, mode 3: led random). Thay đổi mode mỗi khi T0CKI được kích. Mode có thể thay đổi khi chạy xong mode cũ hoặc thay đổi ngay lập tức (pro hơn ;) )
- Pro level: Phối hợp module led với module led 7 đoạn làm thêm, thực hiện cùng lúc 2 công việc: chạy led đủ kiểu trên module led và đếm số trên module led 7 đoạn mỗi 1s (0,1, 2..., 9, 0, ...). Module led 7 đoạn có thể khỏi cần vẽ layout, các bạn mua test board lỗ và linh kiện rồi chú ý hàn vô là được, nhớ gắn trở phân cực cho mỗi thanh led 7 đoạn.

Các bạn nén các file : .c .hex lại rồi nộp tới email: pif.picc5@gmail.com với cú pháp sau ở chủ đề thư:
[C5..] [BT..] [N..] _Họ tên_ ...​
Ví dụ: [C5A] [N1] [BT5] _ Dương Lập Đức _ .... (...: có thể ghi thêm nội dung gì đó)
Danh sách nhóm xem tại đây . Danh sách này có kèm phần điểm danh bài tập của các bạn. Chúng ta sẽ tổng kết lại và loại bớt các bạn không nộp bài tập vào buổi 7.

Buổi sau (buổi 6), các bạn sẽ được giới thiệu về timer1, ngắt ngoài, về một số mạch chức năng (ma trận nút nhấn, ma trận led, ..). Các bạn tham khảo datasheet sơ sơ trước, không nhiều đâu. Nhiệm vụ quan trọng nữa là chuẩn bị module thạch anh ngoài cho timer 1. Thạch anh này là thạch anh đồng hồ 32768 Hz, mắc tương tự như thạch anh trên main PIC: module có đầu vào là header GND, đầu ra là 2 header nối với 2 chân thạch anh; 2 chân thạch anh gắn 2 tụ 22p kéo xuống GND, thân thạch anh cũng được "bắt" (hay hàn) với GND để chống nhiễu. Mạch này các bạn có thể hàn dễ dàng trên test board lỗ, 15 phút là xong.

Buổi 7 (17/12) cũng là buổi cuối cùng của chúng ta trong học kì này. Thời gian nghỉ của các bạn rất dài nên bọn mình sẽ cho các bạn lập nhóm (2-3 bạn) để làm mini project giữa khoá. Các bạn sẽ có điều kiện để tự tổng hợp và phát triển những kiến thức từ đầu tới lúc đó. Từ bây giờ, hãy bắt đầu hình dung ra project của mình và người làm việc chung nhé!

P/S: Đính kèm là các tài liệu cần thết (code mẫu, hình linh kiện, mạch chức năng, ...)
 

Attachments

nguyenhongduc_nc

Thành Viên PIF
Các anh (chị) cho em hỏi về Phần Timer0,
Trong TUT có nói về chức năng Counter của Timer0 nhưng em chưa hiểu rõ lắm về phần Counter này,có phải nó vẫn dùng TMR0 để cài đặt ban đầu đúng ko??
ANh(chị) nào có ví dụ nào về chức năng này thì post lên để em có thể hiểu rõ về nó dc ko?
EM xin cám ơn
 

nguyenhongduc_nc

Thành Viên PIF
Ah ,nếu anh(chị) có file timer0_main(giống trong TUT ) cho em xin với..để tham khảo.....Em xin cám ơn
 

Manhdd

Cố Vấn CLB
Staff member
Counter chính là phần BT Basic level cho các bạn đó. Counter khác timer cơ bản là ở nguồn xung clock, còn lại thì gần y chang.
- Timer dùng nguồn xung Clock 4MHz/4 = 1 MHz của PIC, tăng giá trị thanh ghi TMR0 mỗi 1 us, từ đó, ta định thì được khoảng thời gian: nếu đặt TMR0 ban đầu là 0, thì Timer sẽ tràn mỗi 256 us, Con trỏ chương trình (PC / Program Counter) tự nhảy vào ngắt và thực hiện công việc của chúng ta (Đảo led, etc..)
- Counter dùng nguồn xung clock ngoài, nối vào chân T0CKI (RA4 => set iput), cạnh lên hay cạnh xuống do bit T0CS quyết định. Mỗi khi có xung (nhấn nút nhấn tạo 1 cạnh xuống và 1 cạnh lên), TMR0 tăng lên 1. Nếu TMR0 ban đầu là 250, timer sẽ tràn sau 6 lần nhấn nút.
Vì timer chỉ đếm tối đa đến 256 us, một bộ chia tần prescaler được sử dụng (khi PSA=0) để tăng khoảng thời gian tối đa mà timer 0 đếm được. Presacler chia tần số tối đa được 256 lần (khi PS2 = PS1 = PS0 =1), khi đó timer 0 đếm tối đa đến 256*256 us thì tràn. Thường thì chế độ counter không dùng prescaler (đếm 256*256 lần nhấn nút :)) ).

Về sample code cho timer 0, các bạn xem trong file đính kèm ở trên, khá đầy đủ rồi.
 

nguyenhongduc_nc

Thành Viên PIF
bạn ơi cho mình hỏi,hàm interrupt isr() ở đâu vậy(nằm ở file nào)..làm sao có thể thay đổi cấu hình cho nó.Mình xin cám ơn
 

Manhdd

Cố Vấn CLB
Staff member
Hàm Interrupt service routines này chả nằm ở file nào cả, nó là 1 hàm đặc biệt theo qui định của Hitech PIC. Khi có 1 ngắt bất kì xảy ra, con trỏ chương trình sẽ nhảy đến hàm này. Trong hàm, cần có thao tác kiểm tra cờ ngắt để biết ngắt nào đã gọi hàm.
Ở mức sâu hơn, hàm này tương ứng với vector ngắt duy nhất 0004h trong bộ nhớ.
 

saiya

Thành Viên PIF
em cho build code trên mà sao nó hiện lỗi này vậy:
Error [192] E:\MACH DIEN TU\TEST MPLAB\123.c; 51.1 undefined identifier "ANSEL"
Error [192] E:\MACH DIEN TU\TEST MPLAB\123.c; 52.1 undefined identifier "ANSELH"
 

hd2711

Trứng gà
bạn cho mình hỏi là từ code timer.c bạn send mail, mình sửa lại 2 dòng config cho hợp vs phiên bản dùng, buil nó báo lỗi Error [939] ; . no file arguments
, lỗi này là bị j vậy bạn?
 

nguyenhongduc_nc

Thành Viên PIF
Em viết code ở phần inter level,khi cho chạy thử thì vẫn ok,nhưng khi nhấn tới mode 2 thì nó ko quay trở về mode 0,Mọi người xem giúp em với


#include <htc.h>
__CONFIG(XT & WDTDIS & PWRTEN & MCLREN & UNPROTECT & SWBOREN & IESODIS & FCMDIS & LVPDIS & DEBUGDIS); //1st config. Word

__CONFIG(BORV21); //2st config. Word

#define _XTAL_FREQ 4000000 //t?n s? th?ch anh 4Mhz
#define HANG_SO 123
int chaser;
int i;
void delay_1s()
{
int k=0;
for (k;k=10;k++) __delay_ms(10);
}
void main(void)
{
ANSEL=0;
ANSELH=0; //T?t c? các port là digital
TRISA=0xff;//port A la INPUT
TRISB=0; //Port B LA OUT PUT
PORTB=0xff;
T0CS=1;//CHON DAO dong external
T0SE=1;//ngat canh xuong
PSA=1;//ko CHON BO CHIA TAN
GIE=1;
TMR0=0Xff;//nhan 3 cai
T0IF=0;//XOA CO NGAT
T0IE=1;//CHO PHEP NGAT TOAN CUC
while(1);
}
void interrupt isr()
{
if (T0IE && T0IF)
{
while(1)
{
PORTB=0xff;
__delay_ms(100);
PORTB=0x00;
__delay_ms(100);
//kiem tra lan 1
if( RA4==0)
{
__delay_ms(20);
if (RA4==1)
{
//chay mode 2
while(1)
{
RB1^=1;
__delay_ms(100);
RB1^=1;
__delay_ms(100);
//kiem tra lan 2
if( RA4==0)
{
__delay_ms(20);
if (RA4==1)
{
//chay mode 3
while(1)
{
T0IF=0;//xoa co ngat timer0
TMR0=0xff;// dat lai gia tri timer 0
i=0;
chaser=0xfe;
while (i<8)
{
PORTB=chaser;
chaser=chaser<<1;
__delay_ms(100);
i++;
}
i=0;
chaser=0x7f;
while (i<8)
{
PORTB=chaser;
chaser=chaser>>1;
__delay_ms(100);
i++;
}

}//ket thuc while
}//ket thuc mode 3
}//ket thuc kiem tra 2
}//ket thuc mode 2
}
}//ket thuc kiem tra 1
}
}
};
 

nguyenhongduc_nc

Thành Viên PIF
Anh(chị) có thể nói rõ hơn cho em biết về sơ đồ nguyên lí của bài pro level dc ko..Nếu có sơ đồ nguyên lí thì up lên cho em tham khảo với,Em xin cám ơn
 

saiya

Thành Viên PIF
bạn cho mình hỏi là từ code timer.c bạn send mail, mình sửa lại 2 dòng config cho hợp vs phiên bản dùng, buil nó báo lỗi Error [939] ; . no file arguments
, lỗi này là bị j vậy bạn?
bạn chưa "add file to project"
 

Manhdd

Cố Vấn CLB
Staff member
Led 7 đoạn cũng như led thường, có điều đóng góp lại thôi. File gif trong tutorials mà mình đính kèm đã cho biết rõ cấu trúc 8 con led bên trong 2 loại led 7 đoạn rồi. Bạn nối led 7 đoạn cũng như led thường, cần 1 đầu vào PIC, gắn trở hạn dòng, 1 đầu lên VCC hay xuống GND, tuỳ loại. Mình không post trực tiếp nguyên lý là để các bạn tự suy nghĩ, phát triển.
Bạn tìm trên google hình ảnh với từ khoá Led 7 seg, sẽ thấy rất nhiều nguyên lý, tiêu biểu như hình này hoặc hình này . Mạch Led 7 đoạn thường có BJT điều khiển để hạn dòng, bữa sau mình sẽ nói tới. Trong khuôn khổ bài tập này chưa cần thiết.
 

Manhdd

Cố Vấn CLB
Staff member
@quan: hix, chương trình bạn viết lạ quá, mình chưa thấy ai để while(1) trong ngắt bao giờ (Mà bạn lại bảo chạy rồi ??). Mình đang bận, không kiểm tra code của bạn hết được.
Hàm main bạn còn nguyên vòng while chả làm gì kìa. Theo ý mình là các bạn nên cho hàm main thực hiện các mode, interrupt chỉ có nhiệm vụ thay đổi biến thứ tự mode thực thi thôi.
 

nguyenhongduc_nc

Thành Viên PIF
Các anh(chị) có đoạn code giải inter và pro level của timer 0 này không.Up lên cho em tham khảo với....
 

Manhdd

Cố Vấn CLB
Staff member
- Con trỏ chương trình sẽ nhảy đến interrupt isr() ngay sau khi cờ ngắt được set lên 1.
- Các bài tập này mình chỉ mới nghĩ ra, là ví dụ để các bạn tự luyện viết code, không phải khuôn mẫu để bạn làm theo. Mỗi người có hướng viết code của riêng mình. Gợi ý: Intermediate level: cần 1 biến toàn cục chứa thứ tự mode; Pro level: chỉ đơn giản là xuất điện áp ra led 7 đoạn mỗi khi timer tràn. Ai tìm được giải thuật gì hay có thể đưa lên để mọi người tham khảo :d
 

Jan

Trứng gà
Vậy sau khi nhảy vào interrupt isr() thì con trỏ sẽ nhảy về ĐẦU vòng lặp while hay là nhảy về lệnh ĐANG THỰC THI GIỮA chừng???
 

Manhdd

Cố Vấn CLB
Staff member
Vậy sau khi nhảy vào interrupt isr() thì con trỏ sẽ nhảy về ĐẦU vòng lặp while hay là nhảy về lệnh ĐANG THỰC THI GIỮA chừng???
Nhảy về chỗ đang thực hiện đó bạn!
 

Jan

Trứng gà
vậy thì khi nhảy ra interrupt isr() thì nó quay về thực hiện cho hết trạng thái đang chạy. Vậy thì trạng thái mới không được chuyển ngay mà phải đợi chạy xong trạng thái đang chạy. Có cách nào khi nhấn nút thì interrupt isr() thực hiện và khi thoát ra thì nó sẽ không chạy tiếp trạng thái cũ mà chuyển lập tức sang trạng thái mới không???
Đây là 1 đoạn chương trình của em.

#include <htc.h>
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
__CONFIG(XT & WDTDIS & PWRTEN & MCLREN & UNPROTECT & SWBOREN & IESODIS & FCMDIS & LVPDIS & DEBUGDIS); //1st config. Word

__CONFIG(BORV21); //2st config. Word

#define _XTAL_FREQ 4000000 //t?n s? th?ch anh 4Mhz

unsigned int kich=-1;

///////////////////////////////////////////////
void timer0_counter()
{
T0CS = 1;
T0SE = 0;

PSA = 1;

// PS2 = 1;
// PS1 = 1;
// PS0 = 1;

GIE = 1;
T0IF = 0;
T0IE = 1;

TMR0 = 0xFF;
}
////////////////////////////////////////////////
////////////////////////////////////////////////
void __delay_ms2(int n)
{
for (int i=0;i<n;i++) __delay_ms(10);
}
////////////////////////////////////////////////
////////////////////////////////////////////////
void main(void)
{
ANSEL=0;
ANSELH=0; //T?t c? các port là digital
TRISB=0x00; //8 pins PortB là output
PORTB=0xFF; //Xu?t m?c “1”
// TRISA1=1;
// TRISA2=1;

timer0_counter();

while(kich==-1) wait();
PORTB=0xFF; //Xu?t m?c “1”
while(1)
{
switch (kich%6)
{
case 0:
mode1();
__delay_ms2(50);
break;
case 1:
mode2a();mode2b();
break;
case 2:
mode4a();mode3b();
break;
case 3:
mode5();
break;
case 4:
mode6();
break;
case 5:
mode7();
__delay_ms2(100);
break;
}
}
} //end void main
///////////////////////////////////

void interrupt isr()
{
if (T0IE&&T0IF)
{
kich+=1;
T0IF = 0;
TMR0 = 0xFF;
}
}
hàm wait() và mode...() là đủ kiểu chạy của led. Hơi dài nên em không đưa lên.

Có cách nào để khi nhấn nút thì hàm mode cũ sẽ ngừng chạy và lập tức nhảy vào hàm mode khác không anh
 
Top