Chào các bạn.
Mình không biết phương pháp này các bạn biết chưa, hoặc đã ai post chưa. Nhưng đó là mình suy nghĩ và code ra chứ không hề copy ý tưởng hay code của ai khác
.
Phương pháp dựa trên dùng ngắt Timer0 dùng cho PIC16F887 do đó sẽ rất là tối ưu, tất nhiên có thể dùng cho tất cả các loại PIC và vi điều khiển khác.
Cấu tạo của Keypad:
Nội dung của phương pháp này như sau, rất đơn giản giống tư tưởng của các phương pháp scan truyền thống:
B1. Cho các cột = 1
B2. Đọc các hàng, nếu hàng nào = 1, thì sau khoảng 10 đến 15ms thì lại đọc tiếp. Nếu vẫn = 1 thì à, đúng là phím bấm rồi, ke ke. Như vậy xác định được hàng nào rồi nha. Cho vào biến row_num.
B3. Cho row_num = 1, đọc các cột xem, cột nào = 1 thì đó là cột bấm đó, gán vào biến col_num. Chờ khi phím nhả thì gọi hàm thực hiện theo từng phím key_function();
Rất đơn giản như thế nhưng mình thực hiện rất tối ưu, các bạn có thể tham khảo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | void scanKeypad(void){ unsigned char i; // Define i as register later // if state 0 then set column to 1, and see the change of row switch(progress){ case 0: // set all column (4 low bit) as output, and row as input, and write '1' to column tris_keypad = 0xF0; port_keypad |= 0x0F; // if value of row diffirent than 0,then set progress to 1 // and set Tcycle = 10 if ((port_keypad & 0xF0) != 0) { // Determine next state progress = 1; cycle_1 = 10; }else{ progress = 0; }; break; // Progress 1, check after 10 ms case 1: cycle_1--; // when cycle_1 = 0,then check again if(cycle_1 == 0){ if ((port_keypad & 0xF0) != 0) { // Determine which row equal 1 for(i = 7; i>3; i--){ if ( (port_keypad & (1<<i)) != 0){ row_num = i-3; break; }; }; //Determine next state progress = 2; }else{ progress = 0; // Start state }; }; break; // Progress 2, to determind the column case 2: //Set row tris to 0, // row_num corespond to (row_num + 3) bit in port_keypad tris_keypad ^= 1 << (row_num + 3); // clear tris bit of row to 0, as output tris_keypad |= 0x0F; // Set all pin of column as input(0 to 3) port_keypad != 1 << (row_num + 3); for(i = 0;i<4;i++){ if ( (port_keypad & (1<<i)) != 0){ col_num = i+1; break; }; }; // Wait for user release key while ((port_keypad & (1<<i)) != 0); // Do all function of keypad after scan sucessfully key_function(); //Determind the next state progress = 0; //cycle_2 = 0xFF; break; default: break; }; }; |
Bài toán của mình chỉ thực hiện sau khi nhấn phím nên mình mới chờ khi nhả phím. Còn để xác định phím hold hay là nhấn thì dùng thêm process thứ 3, sau thời gian khoảng 250ms nữa hoặc hơn tùy bạn, kiểm tra lại trạng thái của phím bấm đó, nếu thấy vẫn = 1 thì tức là trạng thái hold, còn lại là trạng thái nhấn phím.
Các biến được dùng trong hàm quét phím có thể được khai báo bằng Macro và khai báo biến global.Mình dùng các thanh ghi làm biến, các bạn chú ý dùng để không trùng vào các module đang dùng.
1 2 3 4 5 6 7 8 9 | //Define for keypad on PORTD #define port_keypad PORTD #define tris_keypad TRISD #define progress TXREG //process variable #define row_num TMR1L // Index of row #define col_num CCPR2L // Index of column #define cycle_1 CCPR2H // 10ms</td> |
Vậy chỉ cần thay PORTD bằng bất kì port nào khác mà keypad nối vào là được.
Còn hàm key_function() dùng để thực hiện các lệnh của phím, tùy các bạn.
1 2 3 4 5 6 7 8 9 10 11 | void key_function(void){ switch(row_num){ case 1: switch(col_num){ case 1: //Key 1 case 2: // Key 2 case 3: // Key 3 …………………. } } |
Chú ý: các bạn gọi hàm này trong hàm ngắt của Timer, bao nhiêu ms hay ns là tùy bạn.
Update 30/01/2009
Sửa lại code với tag pre cho đẹp, vì cái lúc trước quên không cho tag vào mà chỉ cho vào 1 table nên không đọc hiểu được code.
Chúc các bạn thành công.
Các bài viết liên quan:
- Cẩm nang ngữ pháp tiếng Hàn Quốc thực dụng (file .pdf) Chào các bạn. Anh Juhuvn đã tổng hợp lại các bài viết của chị MeoMeo để cho qui củ hơn nên mình lấy sang đây luôn cho các bạn. Chào các bạn, Do mục Tổng hợp ngữ pháp tiếng Hàn thực dụng (Tổng hợp ngữ pháp tiếng Hàn thực dụng) của bạn MeoMeo đã quá [...]...
- Tổng hợp ngữ pháp tiếng Hàn thực dụng - 1 to 6 Chào các bạn. Mấy nay hăng hái vào diễn đàn Hội sinh viên Vietnam tại Hàn Quốc (VASK) thấy có một loạt bài giới thiệu ngữ pháp thực dụng của chị Meo nên muốn giới thiệu cho các bạn chúng ta ai đang học tiếng Hàn biết đường tìm mà đọc. Link: http://vsak.vn/vn/forum/showthread.php?t=1197 Xin phép [...]...
- Chuyển ma trận GF sang ma trận bình thường để xử lý dữ liệu Theo ý anh admin thì tôi viết bài này với mục đích là giúp ai đang và sẽ nghiên cứu mã hóa FEC xử lý dữ liệu của ma trận Galois field. Mã hóa FEC (Foward Error Control) hay còn gọi là Eror control Coding-là một mã hóa sửa lỗi được sử dụng khá nhiều [...]...
- Tổng hợp ngữ pháp tiếng Hàn thực dụng - 49 to 60 49. Mẫu câu '-(으)려고 하다' : Mẫu câu `-(으)려고 하다' được dùng với động từ bao gồm cả `있다'. Mẫu câu này để diễn tả một dự định của chủ ngữ. Tuy nhiên, mẫu câu này được dùng giới hạn cho ngôi thứ nhất và ngôi thứ hai. Cách dùng với ngôi thứ ba sẽ [...]...
- Tổng hợp ngữ pháp tiếng Hàn thực dụng - 23 to 33 23.Đuôi từ '-아(어/여) 보다' Nghĩa gốc của '보다' là "xem, nhìn thấy".' Đuôi từ '-아(어/여)보다' được dùng để chuyển tải ý nghĩa 'thử làm một việc gì đó'. Ví dụ : 이 구두를 신어 보세요. Hãy mang thử đôi giày này xem. 전화해 보세요. Hãy thử gọi điện thoại xem. 여기서 기다려 보세요. Hãy thử [...]...
- Tổng hợp ngữ pháp tiếng Hàn thực dụng - 34 to 48 34. Đuôi từ kết thúc câu ' -(으)ㄹ까요?' - Đuôi từ '-(으)ㄹ까요?' được sử dụng để điễn tả ý câu hỏi ý kiến người khác, về hành động sẽ thực hiện. Trong trường hợp này, chủ ngữ trong câu luôn luôn là ngôi thứ nhất số ít hoặc số nhiều. Ví dụ : 우리 거기에서 [...]...




{ 11 comments… read them below or add one }
có ai không giúp mình với mình sắp thi rui ma không biết thế nào về C cả……………………cảm ơn trước
chào anh hải, em đang có một số thắc mắc về cách gán giá trị cho các biến trong hàm ngắt,xin a chỉ rõ cho e ,
vd: đây là dùng ngắt timer 2
2CON=0X04; /// chỗ này e không biết tại sao lại gán giá trị nay
T2MOD=0X00; // và thêm chỗ này nưa
TH2=0XFC;
RCAPCH=0XFC;
TL2=0X18;
RCAPCL=0X18;
ET2=1;
TR2=1;
e không hiểu tại sao lại có địa chỉ này ,trong khi đó địa chỉ bit thanh ghi cua TCON
sbit IT0 = 0×88;
sbit IE0 = 0×89;
sbit IT1 = 0x8A;
sbit IE1 = 0x8B;
sbit TR0 = 0x8C;
sbit TF0 = 0x8D;
sbit TR1 = 0x8E;
sbit TF1 = 0x8F;
và địa chỉ của TMOD là:
#define T0_M0_ 0×01
#define T0_M1_ 0×02
#define T0_CT_ 0×04
#define T0_GATE_ 0×08
#define T1_M0_ 0×10
#define T1_M1_ 0×20
#define T1_CT_ 0×40
#define T1_GATE_ 0×80
#define T1_MASK_ 0xF0
#define T0_MASK_ 0x0F
Cho em hỏi ý nghĩa của lệnh này với:
if ((port_keypad & 0xF0) != 0) {
// Determine next state
progress = 1;
cycle_1 = 10;
}else{
progress = 0;
};
Đó là nhiều lệnh mà em, em không hiểu cụ thể lệnh nào hả em ?
Xin lỗi, em copy mà sao bị thiếu mất chữ, cụ thể là & trong câu lệnh sau:
if ((port_keypad & 0xF0) != 0)
Em không hiểu mệnh đề if này có ý nghĩa gì?
Ủa, sao kỳ vậy, rõ ràng em copy nguyên câu lệnh của anh mà sao khi post lên thì chữ & lại biến đâu mất. Để em gõ lại vậy:
Đây là câu lệnh em thấy: if((post_keypad & ; 0xF0) !=0).
Chào em.
Đó là dấu and đó: & . Do anh post lên cái wordpress nó hiểu nhầm thành thế thôi em.
Chúc em thành công.
anh bắc ơi sao chương trình lại thiếu vậy.anh có thể post hết lên được không ạ.?
cho mình các bạn chỉ dùm tý nhen
mình dùng p3 đưa dự liệu vào
còn p0,p1,p2 là quét cột
mình chỉ biết quét 8 cột còn nhiều cột hơn mình chưa làm có gì mong các bạn chỉ dùm
sơ đồ ngyên lys như sau
chương trình này viết 8×8 (cootx hàng) còn viết 16 cột hay 24 cột thì điều chỉnh như thế nào mong các bạn chỉ dùm do mới bắt đầu học nên chưa biết
mình muốn p0,p1,p2 quét cột còn dự liệu đưa vào hàng p3
#include
sfr p0 = 0×80; // quet cot
sfr p1 = 0×90;// quet cot
sfr p2 = 0xa0; // quet cot
sfr p3 = 0xb0;// du lieu vao hang
// ham tre
void delay(long timer)
{
while(timer–);
}
// khai bao bien
unsigned char kytu1[9];// mang 9 phan tu chua cac gia tri cot ra p2
char k=0,k1=0; // bien xac dinh cac gia tri
// ma hoa
void mahoa(unsigned char x)
{
switch(x)
{
case 0: // dau trang
{
kytu1[0]=0xff;kytu1[1]=0xff;kytu1[2]=0xff;kytu1[3]=0xff;kytu1[4]=0xff;kytu1[5]=0xff;kytu1[6]=0xff;kytu1[7]=0xff;kytu1[8]=0xff;
break;
}
case 1: //chu t
{
kytu1[0]=0xfe;kytu1[1]=0xfe;kytu1[2]=0xfe;kytu1[3]=0×00;kytu1[4]=0×00;kytu1[5]=0xfe;kytu1[6]=0xfe;kytu1[7]=0xfe;kytu1[8]=0xff;
break;
case 2:// chu h
{
kytu1[0]=0xff;kytu1[1]=0×00;kytu1[2]=0xe7;kytu1[3]=0xe7;kytu1[4]=0xe7;kytu1[5]=0xe7;kytu1[6]=0xe7;kytu1[7]=0×00;kytu1[8]=0xff;
break;
}
case 3: // chu A
{
kytu1[0]=0xff;kytu1[1]=0×03;kytu1[2]=0xed;kytu1[3]=0xee;kytu1[4]=0xee;kytu1[5]=0xed;kytu1[6]=0×03;kytu1[7]=0xff;kytu1[8]=0xff;
break;
}
case 4: // chu N
{
kytu1[0]=0×00;kytu1[1]=0xfe;kytu1[2]=0xfb;kytu1[3]=0xf7;kytu1[4]=0xef;kytu1[5]=0xdf;kytu1[6]=0x3f;kytu1[7]=0×00;kytu1[8]=0xff;
break;
}
case 5: // chu H
{
kytu1[0]=0xff;kytu1[1]=0×00;kytu1[2]=0xe7;kytu1[3]=0xe7;kytu1[4]=0xe7;kytu1[5]=0xe7;kytu1[6]=0xe7;kytu1[7]=0×00;kytu1[8]=0xff;
break;
}
case 6: // chu L
{
kytu1[0]=0xff;kytu1[1]=0×00;kytu1[2]=0x7f;kytu1[3]=0x7f;kytu1[4]=0x7f;kytu1[5]=0x7f;kytu1[6]=0xff;kytu1[7]=0xff;kytu1[8]=0xff;
break;
}
case 7: // chu IE
{
kytu1[0]=0×00;kytu1[1]=0xff;kytu1[2]=0×00;kytu1[3]=0×66;kytu1[4]=0×66;kytu1[5]=0×66;kytu1[6]=0×66;kytu1[7]=0xff;kytu1[8]=0xff;
break;
}
case 8: // chu U
{
kytu1[0]=0xff;kytu1[1]=0×80;kytu1[2]=0x7f;kytu1[3]=0x7f;kytu1[4]=0x7f;kytu1[5]=0x7f;kytu1[6]=0×80;kytu1[7]=0xff;kytu1[8]=0xff;
break;
}
case 9: //dautrang
{
kytu1[0]=0xff;kytu1[1]=0xff;kytu1[2]=0xff;kytu1[3]=0xff;kytu1[4]=0xff;kytu1[5]=0xff;kytu1[6]=0xff;kytu1[7]=0xff;kytu1[8]=0xff;
break;
}
}
}
}
// ham quet led ma tran_ hien thi dich
void hienthido(void)
{
unsigned char n,m,lap;
unsigned char quet[8]={0×80,0×40,0×20,0×10,0×08,0×04,0×02,0×01};
// cac phan tu quet hang
for (m=0;m<8;m++) // dich hien thi
{
for(lap=0;lap<20;lap++)// lap hien thi ,cho chay nhanh hay cham
{
for (n=0;n<8;n++) // quet led cot p1
{
if((n+m)7) // hien thi kytu thu 2
{
mahoa(k+1);
p0 = quet[n];
p3 = kytu1[n+m-8];
delay(30);
}
}
p1 =0×00;
p2 =0×00;
p0 =0×00;
p3 =0xff;
}
}
}
// ham chinh
void main(void)
{
while(1)
{
hienthido();
k=k+1;
if(k==9)k=0;
}
}
Chào em.
Anh nghĩ là chương trình này được viết cho 89C52 đúng không? Bởi vì 89C51 chỉ có Timer0 và Timer1 thôi (nếu a nhớ k lầm).
Vì vậy nên em đọc lại các Header file dành cho 89C52 xem nhé.
Chúc em thành công.