Showing posts with label PIC16F877A XC8. Show all posts
Showing posts with label PIC16F877A XC8. Show all posts

BÀI 39 : ĐO NHIỆT ĐỘ DS18B20 HIỂN THỊ LCD PIC16F887 XC8

9:26:00 PM Add Comment
DS18B20 là IC cảm biến nhiệt độ, chỉ bao gồm 3 chân, đóng gói dạng TO-92 3 chân rất nhỏ gọn.
ds18b20
DS18B20 giao tiếp thông qua giao thức 1 dây dẫn với vi xử lý.
Đặc điểm chính của DS18B20 như sau:
+ Cung cấp nhiệt độ với độ phân giải 12bit.
+ Ngưỡng nhiệt độ rộng: -10°C đến 125°C
+ Sai số cho phép: ±0.5°C
+ Có chức năng cảnh báo nhiệt khi nhiệt độ vượt ngưỡng cho phép. Người dùng có thể lập trình chức năng này cho DS18B20. Bộ nhớ nhiệt độ cảnh báo không bị mất khi mất nguồn.
+ Cảm biến nhiệt độ DS18B20 có mã nhận diện lên đến 64-bit, vì vậy bạn có thể kiểm tra nhiệt độ với nhiều IC DS18B20 mà chỉ dùng 1 dây dẫn duy nhất để giao tiếp với các IC này.
Với DS18B20 bạn hoàn toàn có thể tạo cho mình mạch cảm biến nhiệt độ theo ý muốn.
- Đây là ảnh mô phỏng protues.
ds1820b pic16f877a xc8
- Đây là code chương trình.
/*
 * File:   DS18_20.c
 * Author: Lam 3 Ngon
 * My blog http://xcvn.blogspot.com
 * Created on April 26, 2016, 8:57 PM
 */
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#define _XTAL_FREQ 4000000
#define RS RD2
#define EN RD3
#define D4 RD4
#define D5 RD5
#define D6 RD6
#define D7 RD7
#include "lcd.h"
#include "1wire.h"

// CONFIG
#pragma config FOSC = XT        // Oscillator Selection bits (XT oscillator)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = OFF      // Brown-out Reset Enable bit (BOR disabled)
#pragma config LVP = OFF        // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)

void delay(unsigned int t)

while(--t)
    __delay_ms(1);
}
//**************************************************************************/
void main(void)
{
    Convert_Temperature();   
    TRISD = 0X00;
    float Temp = 0;
    char S[20];
    Lcd_Init();
    Lcd_Set_Cursor(1,2);
    Lcd_Write_String("SENSOR DS18B20"); 
    Lcd_Set_Cursor(2,3);
    Lcd_Write_String("BY LAM 3 NGON");
    delay(2000);  
    Lcd_Clear();
while(1)
{
    Convert_Temperature();
    Temp = Read_Temperature_DS18B20();
    sprintf(S,"Temperatura:%2.1f",Temp);
    Lcd_Set_Cursor(1,1);     
    Lcd_Write_String(S);
    delay(1000);
}

}
- Link download project : Click here

CHIA SẼ CÁCH TÍNH TOÁN TẠO XUNG TIMER

11:41:00 PM Add Comment
Chào các bạn hôm nay mình sẽ chia sẽ cho các bạn cách tính toán tạo xung cho timer 0, 1, 2 để giúp các bạn tiết kiệm thời gian trong việc tính toán và chia sẽ thêm cho các bạn 1 phần mềm cũng rất hữu ích đó là phần mềm đọc giá trị điện trở.
Link download phần mềm và tài liệu : Click here

BÀI 38 : LED MATRIX 8X32 PIC16F877A XC8

1:14:00 AM 1 Comment
- Ảnh mô phỏng protues.
led matrix 8x32 pic16f877a
- Code chương trình.
#include <stdio.h>
#include <stdlib.h>
#define _XTAL_FREQ 20000000
#include <xc.h>
// BEGIN CONFIG
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT enabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = ON // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)

#define ds PORTCbits.RC0
#define st PORTCbits.RC1
#define sh PORTCbits.RC2
unsigned char khung_du_lieu[32];
unsigned char socot,sohang,tocdo,maled;
unsigned char g,h,a;

//------------------------------------------------------ du lieu cot luu vao ROM------------------------------------------
const unsigned char codedu_lieu_cot[]={
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0xff,0xff,0x60,0x30,0x18,0x0C,0xFF,0xFF,///////////////N
0x00,0x00,0x00,
0x7E,0xFF,0xC3,0xC3,0xCB,0xCB,0xEF,0x6E,///////////////G
0x00,0x00,0x00,
0x7E,0xFF,0xC3,0xC3,0xC3,0xC3,0xFF,0x7E,//////////////O
0x00,0x00,0x00,
0x7E,0xFF,0xC3,0xC3,0xC3,0xC3,0xEF,0x6E,//////////////C
0x00,0x00,0x00,
0xff,0xff,0x03,0x03,0x03,0x03,0x03,0x03,///////////////L
0x00,0x00,0x00,
0x1f,0x3f,0x6c,0xcc,0xcc,0x6c,0x3f,0x1f,///////////////A
0x00,0x00,0x00,
0xff,0xff,0x60,0x30,0x30,0x60,0xff,0xff,//////////////M
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
void tonghop(void);
void delay_ms(unsigned int ms);
void load(unsigned int u);
void main(void)
{
  TRISD = 0X00;
  TRISC = 0X00;
  PORTD=0xff;
  PORTC=0x00;
  while(1)
   {
     tonghop();
   }
}

void delay_ms(unsigned int ms)
{
  unsigned int i;
  unsigned char j;
  for(i=0;i<ms;i++)
     for(j=0;j<120;j++);
}

void load(unsigned int u)
{
  unsigned char i;
  for(i=0;i<32;i++)
   {
     khung_du_lieu[i]=codedu_lieu_cot[u];
u++;
   }
}

void tonghop(void)
{
    unsigned char i;
    for(socot=0;socot<106;socot++) //73+32=105 la so phan tu du_lieu_cot
 {
   load(socot);
   for(tocdo=0;tocdo<10;tocdo++)// delay
     {
    a=0xfe;
        h=0x80;
    for(sohang=0;sohang<8;sohang++)
  {
    st=0;
    for(i=0;i<32;i++)
  {
    sh=0;
    g=khung_du_lieu[i];
if((g&h)==h) ds=1;
else         ds=0;
sh=1;
  }
st=1;
h=h>>1;
PORTD=a;
delay_ms(1);
PORTD=0xff;
a=(a<<1)+1;
  }
}
   }
}
- Link download project Click here

BÀI 37 : LED MATRIX 8X16 PIC16F877A XC8

7:37:00 PM Add Comment
Chào các bạn trong bài đăng trước mình đã hướng dẫn các bạn về LED matrix 8x8 rồi hôm nay tiếp tục với LED matrix 8x16 sử dụng PIC16F877A và trình biên dịch Mplab XC8 để viết và biên dịch code.
LED matrix được ghép từ 2 LED matrix 8x8 bao gồm 16 hàng và cột như hình bên dưới :
 led matrix 8x16
Với LED matrix 8x8 thì rất dễ dàng cho việc giao tiếp của chúng ta nhưng đối với LED matrix 8x16 thì khó hơn nhiều. Bởi vì số hang và cột của LED matrix 8x16 nhiều hơn 8x8 nên việc quét hành và cột cũng khó hơn. Cách đơn giản nhất là dùng 1 PORT để xuất dữ liệu ra hàng và dùng 2 PORT để xuất dữ liệu ra cột nếu làm như vậy thì vẫn được nhưng không tối ưu nên ở đây mình sẽ sử dụng IC 74HC595 để tiết kiệm chân cho Vi Điều Khiển. Nếu ai chưa biết cấu tạo và cách hoạt động của IC 74HC595 thì xem lại Tại Đây. Chúng ta sẽ có sơ đồ kết nối như hình bên dưới :
 
- Đây là ảnh mô phỏng protues.
led matrix 8x16 pic16f877a

- Đây là code chương trình.
/*
 * File:   8x16.c
 * Author: Lam 3 Ngon
 * My blog http://xcvn.blogspot.com
 * Created on April 30, 2016, 8:32 AM
 */
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#define _XTAL_FREQ 4000000

// CONFIG
#pragma config FOSC = XT        // Oscillator Selection bits (XT oscillator)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = OFF      // Brown-out Reset Enable bit (BOR disabled)
#pragma config LVP = OFF        // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)

unsigned const font[] = {
65, 127, 127,  65,  64,  96, 112,   0, //'L'
124, 126,  19,  19, 126, 124,   0,   0, //'A'
127, 127,  14,  28,  14, 127, 127,   0, //'M'
0,   0,   0,   0,   0,   0,   0,   0, //' '
34,  99,  73,  73, 127,  54,   0,   0, //'3'
0,   0,   0,   0,   0,   0,   0,   0, //' '
127, 127,   6,  12,  24, 127, 127,   0, //'N'
28,  62,  99,  65,  81, 115, 114,   0, //'G'
28,  62,  99,  65,  99,  62,  28,   0, //'O'
127, 127,   6,  12,  24, 127, 127,   0, //'N'
0,   0,   0,   0,   0,   0,   0,   0, //' '
0,   0,   0,   0,   0,   0,   0,   0, //' '
};


void main() 
{
unsigned scroll, refresh, col;
TRISB = 0x00;  
TRISC = 0x00;  
PORTB = 0x00;  
PORTC = 0x00;  
   while(1)
   {
    for(scroll=0;scroll<96;scroll++)
    { //font. 12 x 8[8x8 matrix] = 104.
     for(refresh=0;refresh<20;refresh++)
     {  
      PORTCbits.RC0 = 1; PORTCbits.RC0 = 0; PORTCbits.RC1 = 1; PORTCbits.RC3 = 1; PORTCbits.RC3 = 0; 
      for(col=0;col<16;col++) // 16 hang va cot
      { 
      PORTB =~ font[col + scroll];
      __delay_us(300);  
      PORTCbits.RC0 = 1; PORTCbits.RC0 = 0; PORTCbits.RC1 = 0; PORTCbits.RC3 = 1; PORTCbits.RC3 = 0;
      }
     }
    }
   }
}
- Link download project Click here

BÀI 36 : LED MATRIX 8X8 PIC16F877A XC8

5:32:00 PM 6 Comments
1. Sơ đồ chân Led ma trận 8x8


led matrix 8x8
Hình 1: Led ma trận 8x8

2. Câu tạo bên trong của LED matrix 8x8.
Hình 2: Sơ đồ chân và sơ đồ kết nối bên trong led ma trận.
3. Code hiển thị chữ A lên led ma trận
/*
 * File:   matrix_8x8.c
 * Author: Lam 3 Ngon
 * My blog http://xcvn.blogspot.com
 * Created on April 20, 2016, 9:17 AM
 */
#include <stdio.h>
#include <stdlib.h>
#define _XTAL_FREQ 4000000
#include <xc.h>
// CONFIG
#pragma config FOSC = XT        // Oscillator Selection bits (XT oscillator)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = OFF      // Brown-out Reset Enable bit (BOR disabled)
#pragma config LVP = OFF        // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)
const unsigned char FontA[8] = {0xff,0x01,0x00,0xf6,0xf6,0x00,0x01,0xff}; 
// lay ma tu duoi len 8 - 4 - 2 - 1
// sang la 0 tat la 1
void main()
{
unsigned char i;
unsigned char cnt;
unsigned char j;
    TRISB = 0X00;
    TRISD = 0X00;
while(1)
{
for(i=0;i<7;i++)
{
PORTB = FontA[i];
PORTD = 0x01<<i;
__delay_ms(1);
PORTD = 0x00;
}           
    }
}
- Giải thuật để quét LED matrix là chúng ta sẽ quét lần lượt theo từng hàng và cột nha ! Như các bạn thấy đoạn code trên chúng ta sử dụng phương pháp này để quét sao đó xuất kết quả ra PORT !
Nếu thời gian quét đủ nhanh, ta thấy các led dường như sáng liên tục tạo nên chữ như hình bên dưới.
Hình một số font chữ trên led ma trận:

Font 5x7 cho led ma trận;
 
Đây là ảnh mô phỏng trên phần mềm protues.
led matrix 8x8 pic16f877a
- Lý do mình không làm trên LED matrix 5x7 cho ví dụ này là vì LED matrix nào cũng giống nhau cả muốn hiển thị thì phải quét theo hàng và cột thôi. 
- Mình sẽ giải thích chương trình 1 tý :
const unsigned char FontA[8] = {0xff,0x01,0x00,0xf6,0xf6,0x00,0x01,0xff};
đoạn code trên là mã của chữ A. Và cách tính để có được mã này như sau : Mặc định sáng là  và tắt là 1 như vậy hàng đầu tiên là 0xff, hàng thứ 2 từ dưới tính lên là 0x01 các hàng còn lại thương tự.
Và tiếp theo chúng ta có đoạn code này dùng để xuất dữ liệu ra hàng và cột như sau :
for(i=0;i<7;i++)
{
PORTB = FontA[i];
PORTD = 0x01<<i;
__delay_ms(1);
PORTD = 0x00;
}   
Ở đây chúng ta có 8 hàng và 8 cột nên cho vòng for chạy 8 lần và mỗi lần thì PORTD sẽ dịch sang 1 như vậy cho đến hết 8 hàng.

BÀI 35 : GIAO TIẾP KEYPAD 4X4 PIC16F877A XC8

6:21:00 AM 9 Comments
I. Keypad 4x4.
Keypad là một "thiết bị nhập" chứa các nút nhấn cho phép người dùng nhập các chữ số, chữ cái hoặc ký hiệu vào bộ điều khiển. Keypad không chứa tất cả bảng mã ASCII như keyboard và vì thế keypad thường được tìm thấy trong các thiết bị chuyên dụng. Các nút nhấn trên các máy tính điện tử cầm tay là một ví dụ về keypad. Số lượng nút nhấn của một keypad thay đổi phụ thuộc vào yêu cầu ứng dụng. Trong bài này tôi giới thiệu cách điều khiển của một loại keypad đơn giản, keypad 4x4.
Gọi là keypad 4x4 vì keypad này có 16 nút nhấn được bố trí dạng ma trận 4 hàng và 4 cột. Cách bố trí ma trận hàng và cột là cách chung mà các keypad sử dụng. Cũng giống như các ma trận LED, các nút nhấn cùng hàng và cùng cột được nối với nhau, vì thế với keypad 4x4 sẽ có tổng cộng 8 ngõ ra (4 hàng và 4 cột). Mô hình Keypad 4x4 được thể hiện trong hình 1.
keypad 4x4
Hình 1.
Hình ở trên là hình mô phỏng trên phần mềm protues mình chụp lại để các bạn hình dung nó như thế nào thôi ! Còn thực chất thì nó được cấu tạo như sau :
keypad 4x4
Có rất nhiều cách khác nhau để làm bài này các bạn thích làm theo cánh bào thì làm. Như trong hình trên thì chúng ta sẽ thấy các chân C1 - C4 sẽ nối với mức 0 từ chân Vi Điều Khiển, và các chân từ R1- R4 sẽ được nối với trở và nối vào mức 1 của Vi Điều khiển ! Và chúng ta sẽ quét theo hàng và cột giống như 1 mảng vậy !
- Đây là ảnh mô phỏng protues.

giao tiếp với keypad 4x4 pic16f877a

- Đây là code chương trình.
#include <stdio.h>
#include <stdlib.h>
#define _XTAL_FREQ 20000000
#define RS RD1
#define EN RD0
#define D4 RD4
#define D5 RD5
#define D6 RD6
#define D7 RD7
#include <xc.h>
#include "lcd.h"
#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = ON       // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF        // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)
//#define set_port_kbd PORTB // Change if port is different
// Define pins
// Define pins
#define RowA RB0
#define RowB RB1
#define RowC RB2
#define RowD RB3
#define C1 RB4
#define C2 RB5
#define C3 RB6
#define C4 RB7

#define Keypad_PORT PORTB
#define Keypad_PORT_Dir TRISB
void InitKeypad(void);
char GetKey(void);
void main(void) {
     TRISD = 0x00;
     PORTD   = 0;
     Lcd_Init();
     Lcd_Set_Cursor(1,1);
     Lcd_Write_String("By LAM 3 NGON");
     Lcd_Set_Cursor(2,1);
     Lcd_Write_String("KeyPad Control...");
     __delay_ms(1000);
     Lcd_Clear();
     Lcd_Set_Cursor(1,1);                  
     Lcd_Write_String("Enter Key");
     Lcd_Set_Cursor(2,1);
     Lcd_Write_String("");
char Key = 'n'; // Variable to store pressed key value
InitKeypad(); // Initialize Keypad pins
while(1)
{
Key = GetKey(); // Get pressed key from keypad
Lcd_Write_Char(Key); // Update LCD with current key value
}
}
// Function name: InitKeypad
void InitKeypad(void)
{
Keypad_PORT    = 0x00; // Set Keypad port pin values zero
Keypad_PORT_Dir = 0xF0; // Last 4 pins input, First 4 pins output

// Enable weak internal pull up on input pins
OPTION_REG &= 0x7F;
}



// Function name: READ_SWITCHES
// Scan all the keypad keys to detect any pressed key.
char READ_SWITCHES(void)
{
RowA = 0; RowB = 1; RowC = 1; RowD = 1; //Test Row A

if (C1 == 0) { __delay_ms(250); while (C1==0); return '7'; }
if (C2 == 0) { __delay_ms(250); while (C2==0); return '8'; }
if (C3 == 0) { __delay_ms(250); while (C3==0); return '9'; }
if (C4 == 0) { __delay_ms(250); while (C4==0); return '/'; }

RowA = 1; RowB = 0; RowC = 1; RowD = 1; //Test Row B

if (C1 == 0) { __delay_ms(250); while (C1==0); return '4'; }
if (C2 == 0) { __delay_ms(250); while (C2==0); return '5'; }
if (C3 == 0) { __delay_ms(250); while (C3==0); return '6'; }
if (C4 == 0) { __delay_ms(250); while (C4==0); return 'x'; }

RowA = 1; RowB = 1; RowC = 0; RowD = 1; //Test Row C

if (C1 == 0) { __delay_ms(250); while (C1==0); return '1'; }
if (C2 == 0) { __delay_ms(250); while (C2==0); return '2'; }
if (C3 == 0) { __delay_ms(250); while (C3==0); return '3'; }
if (C4 == 0) { __delay_ms(250); while (C4==0); return '-'; }

RowA = 1; RowB = 1; RowC = 1; RowD = 0; //Test Row D

if (C1 == 0) { __delay_ms(250); while (C1==0); return 'C'; }
if (C2 == 0) { __delay_ms(250); while (C2==0); return '0'; }
if (C3 == 0) { __delay_ms(250); while (C3==0); return '='; }
if (C4 == 0) { __delay_ms(250); while (C4==0); return '+'; }

return 'n';           // Means no key has been pressed
}


// Function name: GetKey
// Read pressed key value from keypad and return its value
char GetKey(void)           // Get key from user
{
char key = 'n';              // Assume no key pressed

while(key=='n')              // Wait untill a key is pressed
key = READ_SWITCHES();   // Scan the keys again and again

return key;                  //when key pressed then return its value

}
- Link download project Click here

BÀI 34 : GIAO TIẾP VỚI KEYPAD 3X4 PIC16F877A XC8

12:28:00 AM 2 Comments
I. Keypad 3x4 (Keypad - Phone).
Keypad là một "thiết bị nhập" chứa các nút nhấn cho phép người dùng nhập các chữ số, chữ cái hoặc ký hiệu vào bộ điều khiển. Keypad không chứa tất cả bảng mã ASCII như keyboard và vì thế keypad thường được tìm thấy trong các thiết bị chuyên dụng. Các nút nhấn trên các máy tính điện tử cầm tay là một ví dụ về keypad. Số lượng nút nhấn của một keypad thay đổi phụ thuộc vào yêu cầu ứng dụng. Trong bài này tôi giới thiệu cách điều khiển của một loại keypad đơn giản, keypad 3x4.
Gọi là keypad 3x4 vì keypad này có 12 nút nhấn được bố trí dạng ma trận 4 hàng và 3 cột. Cách bố trí ma trận hàng và cột là cách chung mà các keypad sử dụng. Cũng giống như các ma trận LED, các nút nhấn cùng hàng và cùng cột được nối với nhau, vì thế với keypad 3x4 sẽ có tổng cộng 8 ngõ ra (4 hàng và 3 cột). Mô hình Keypad 3x4 được thể hiện trong hình 1.
keypad - phone
- Hình dạng ngoài thực tế của nó như hình bên dưới.

- Đây là ảnh mô phỏng protues.
giao tiếp với keypad pic16f877a
- Đây là code chương trình.
#include <stdio.h>
#include <stdlib.h>
#define _XTAL_FREQ 8000000
#define RS RB2
#define EN RB3
#define D4 RB4
#define D5 RB5
#define D6 RB6
#define D7 RB7
#include <xc.h>
#include "lcd.h"
#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = ON       // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF        // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF        // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF        // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)
#define HEATER PORTAbits.RA1
#define FAN PORTAbits.RA2
#define ON 1
#define OFF 0
void ADCinit(void);
int kbd_getc();
//#define set_port_kbd PORTB // Change if port is different
#define row1port RD0
#define row2port RD1
#define row3port RD2
#define row4port RD3
#define col1port RD4
#define col2port RD5
#define col3port RD6
//#define col4port PORTBbits.RB7   //if a 4x4 keypad is used

unsigned char  const number[10] = {0,1,2,3,4,5,6,7,8,9};
char const keypad[] =
{
    '1',   '2',  '3',
    '4',   '5',  '6',
    '7',   '8',  '9',
    '*',   '0',  '#',
    0xFF
};
char key,old_key;
//unsigned char stringKey[10],stringKeyActual[10];
unsigned long keypress;
void main(void) {
     TRISB = 0x00;
     TRISD   = 0XF0;
     Lcd_Init();
     Lcd_Set_Cursor(1,2);
     Lcd_Write_String("DEMO KEYPAD 3X4");
     Lcd_Set_Cursor(2,3);
     Lcd_Write_String("BY LAM 3 NGON");
     __delay_ms(2000);
     Lcd_Clear();
     while (1){
       keypress = kbd_getc();
       if(keypress!=0xFF)
       {
          Lcd_Write_Char(keypress ) ;
       }
}
}
int kbd_getc(){
    // This routine returns the first key found to be pressed during the scan.
    char key = 0, row;
    for( row = 0b00000001; row < 0b00010000; row <<= 1 )
    {
        {   // turn on row output
            row1port = (row & 0x0001)>>0;
            row2port = (row & 0x0002)>>1;
            row3port = (row & 0x0004)>>2;
            row4port = (row & 0x0008)>>3;
            __delay_ms(1);
        }
        // read colums - break when key press detected
        if( col1port )break;  key++;
        if( col2port )break;  key++;
        if( col3port )break;  key++;
        //if( col4port )break;  key++;
     }
    row1port = 0;
    row2port = 0;
    row3port = 0;
    row4port = 0;
    if (key!=old_key){
      old_key=key;
      return keypad[ key ];
    }
    else
    return keypad[ 0x0C ];
}
- Link download project Click here