KIT AT89S52 V3 NEW - Schematic (Sơ Đồi Nguyên Lý)

Chào tất cả các bạn!
Hiện nay cửa hàng banlinhkien.vn đã nâng câp phiên bản KIT AT89S52 V3 lên phiên bản KIT AT89S52 V3 New.
So với phiên bản củ, phiên bản mới có nhiều thay đổi về cả hình thức và chức năng.



Ngoài các chức năng cơ bản như:
Còi chip, Rơ le.
Led đơn, Led 7 thanh.
GLCD KS0108, GLCD ST7920, LCD6x2.
Phím nhấn đơn, Ma trận phím 4x4.
Eeprom 24C04.
Đồng hồ thời gian thức DS1307
Giao tiếp UART.
Cảm biến nhiệt độ DS18B20, LM35.
Mắt thu hồng ngoại 1838T.
Đo tần số của NE555.
Ngoài ra, Kit AT89S52 V3 New còn có thêm chức năng:
Chuyển đổi ADC và DAC sử dụng PCF8591. Đây là IC chuyển đổi AD, DA 8 bit, giao tiếp theo chuẩn I2C.

Với tất cả những chức năng trên Kit AT89S52 V3 New được xem là công cụ hỗ trợ học tập tốt nhất, phù hợp nhất cho những ai đang tìm hiểu, học tập về lập trình nhúng cũng như dòng vi điều khiển 8051.
Các bài học và thảo luận về Kit AT89S52 V3 New sẽ được Update liên tục trong chuyên mục: KIT AT89S52 V3 NEW tại: http://hocdientu.vn/forums/kit-at89s52-v3-new.123/
File đính kèm phía dưới là sơ đồ nguyên lý của kit, mọi người có thể tham khảo.
Tải Sơ Đồ Nguyên Lý: Schematic AT89S52 V3 New.pdf (131.4 KB)

Bài 1. [KIT AT89S52 V3 NEW] HIỂN THI LED 7 THANH

Chào các bạn!
Hôm nay, mình xin giới thiệu đến các bạn hướng dẫn điều khiển hiển thị Led 7 thanh trên Kit AT89S52 V3 New.
Thông tin về sản phẩm Kit AT89S52 V3 New các bạn có thể xem tại:
I. Sơ đồ nguyên lý khối Led 7 thanh trên Kit AT89S52 V3 New.


II. Phân Tích Mạch Nguyên Lý.
Nhìn vào sơ đồ nguyên lý ta thấy:
. Các chân dữ liệu của 8 led được nối chung với nhau và được nối tới Port 0 của 89S52 qua điện trở băng (dùng để hạn dòng cho led) có giá trị 200R. Như vậy Port 0 được sử dụng để xuất dữ liệu hiển thị.
. 8 chân anot của 8 led, được nối về cực C của các Transistor thuận (PNP), Các transistor này được điều khiển bởi các chân của Port 2 của 89S52. DO đó các chân của Port 2 được sử dụng để điều khiển cấp nguồn cho chân anot của Led 7 thanh. Mức 0: Cấp nguồn ,
Mức 1: Ngắt nguồn.
. Vậy để hiển thị 1 số ra 1 led nào đó ta làm như sau: Cấp nguồn cho chân Anot của led bằng cách xuất mức 0 ra chân điều khiển led (Các chân của Port2), Xuất dữ liệu hiển thị ra các chân dữ liệu (ở mạch trên là Port 0).
.Do các chân dữ liệu được nối chung với nhau, nên muốn hiển thị một số có 2 chữ số trở lên chúng ta sẽ phải sử dụng phương pháp quét led. Phương pháp quét led là phương pháp cho các led sáng lần lượt, trong khoảng thời gian ngắn để mắt người không phân biệt được các led sáng lần lượt. (khi 1 led sáng thì các led còn lại tắt) , đồng thời xuất dữ liệu tương ứng ra led đó.
III. Viết Chương Trình.

  1. Chương trình hiển thị số có 1 chữ số.
    Như mình đã nói ở trên, để hiển thị 1 số có chữ số ra 1 led, chúng ta cấp nguồn cho a nốt của led và xuất dữ liệu ra led đó.
    Dưới đây là chương trình hiển thị các số từ 0->9 ra led thứ 8 (tính từ trái sang, Led Q4).

    #include “At89X52.H”

    #define LED8 P2_3 //chân ddieu khien led Q4
    #define LED_DATA P0 //Port xuat du lieu hien thi Led.

    //mang chua du lieu Led 7: 0-9
    unsigned char ma_led_7[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};

    //chuong trinh con tao thoi gian tre
    void delay_ms(unsigned int time )
    {
    unsigned int i,j;
    for(i=0;i<time;i++)
    for(j=0;j<125;j++);
    }

    //chuong trinh chinh
    void main(void)
    {
    unsigned char number; //so can hien thi
    LED8=0; //cap nguon cho Led Q4
    while(1)
    {
    for(number=0;number<=9;number++) //vong lặp tăng số hiển thị từ 0-9
    {
    LED_DATA=ma_led_7[number];
    delay_ms(500);
    }
    }
    }

  2. Chương trình hiển thị số có từ 2 chữ số trở lên.
    . Để hiển thị số có từ 2 chữ số trở lên, chúng ta sử dụng phương pháp quét Led. Có 2 phương pháp để quét Led: Quét Led dùng hàm delay và Quét Led dùng ngắt timer.
    . Quét Led dùng hàm delay có nhược điểm là trong lúc quét Led để hiển thị số, chúng ta không thể làm thêm việc gì khác. Vì vậy, ở đây mình sẽ hướng dẫn các bạn sử dụng ngắt timer để quét Led.
    .Dùng ngắt timer để quét Led nghĩa là chúng ta khởi tạo giá trị cho bộ timer và cho timer hoạt động. Mỗi khi xảy ra ngắt tràn timer, trong hàm xử lý ngắt ta cho 1 Led sáng và xuất dữ liệu ra Led đó.
    .Thời gian khởi tạo cho timer phải đảm bảo thời gian xảy ra ngắt không quá lâu tránh hiện tượng nháy Led, cũng không qua nhanh, tránh hiện tượng Led sáng mờ. Thời gian này phụ thuộc vào số Led cần quét.
    . Do mỗi lần ngắt chúng ta chỉ cho sáng 1 Led, nên chúng ta cần sử dụng 1 biến để đếm số lần ngắt. Ngắt lần 1 cho Led 1 sáng, lần 2 cho Led 2 sang…và lần n cho Led n sáng. Khi đến Led n, chúng ta reset biến đếm về 0 lần ngắt tiếp theo quay lại hiển thị Led 1, rồi tiếp theo là Led 2…và Led n.
    . Một công việc nữa cần làm là chúng ta phải tách số có từ 2 chữ số trở lên ra những chữ số có chữ số để xuất ra mỗi Led trong một lần ngắt. Vị dụ số: 1234 chúng ta cần tách ra 4 số: Số hàng đơn vị (4), số hàng chục (3), số hàng trăm (2) và số hàng nghìn (1).
    Chúng ta sẽ viết 1 chương trình con nhằm mục đích tách 1 số có 4 chữ số, ra 4 số hàng đơn vị, chục, trăm, nghìn và đưa mã của led 7 thanh của 4 số này vào một mảng gồm 4 phần tử.

    //chuong trinh tach so co 4 chu so ra 4 so hàng donvi, chuc, tram, nghin
    void convert_number(unsigned int number)
    {
    char i;
    for(i=3;i>=0;i–)
    {
    buff_led[i]=ma_led_7[number%10];
    number=number/10;
    }
    }

Sau khi gọi chương trình trên, số number sẽ được tách ra chữ số, và mã led 7 cuacr các chữ số hàng nghìn, trăm, chục, đơn vị sẽ được đưa vào trong mảng buff_led. mảng buff_led gồm 4 phần tử: buff_led[0]: chứa mã của chữ số hàng nghìn, buff_led[1] chứa mã chữ số hàng trăm, buff_led[2] chứa mã chữ số hàng chục, buff_led[3] chứa mã chữ số hàng đơn vị.
Sau khi tách được các số, chúng ta sẽ đưa các mã này hiển thị ra Led tương ứng ở trong hàm ngắt ngoài 0.

//chuong trinh ngat timer 0
//Quet led, hien thi so viet trong chuong trinh ngat
void ngat_timer_0(void) interrupt 1
{
    //khoi tao gia tri lai cho cac thanh ghi
    TL0=0X78;      //Thoi gian ngat bang 5ms
    TH0=0XEC;
    TF0=0;                //XOA CO BAO TRAN
    TR0=0;                //Ngung bo timer
    //tat het cac led
    LED5=LED6=LED7=LED8=1;
    index++;                                    //tang bien dem so led
    convert_number(number);
    if(index==1)                            //neu index=1
        {
            LED5=0;                                //cap nguon cho led va
            LED_DATA=buff_led[0];
        }
    if(index==2)                            //neu index=1
        {
            LED6=0;                                //cap nguon cho led va
            LED_DATA=buff_led[1];
        }
    if(index==3)                            //neu index=1
        {
            LED7=0;                                //cap nguon cho led va
            LED_DATA=buff_led[2];
        }
    if(index==4)                            //neu index=1
        {
            LED8=0;                                //cap nguon cho led va
            LED_DATA=buff_led[3];
            index=0;                            //reset index de lap lai quet tu Led 5
        }
    TR0=1;                                        //cho Timer chay
}      

Việc đầu tiên vào chương trình ngắt là chúng ta gán giá trị lại cho 2 thanh ghi TL0, TH0.
Tại sao lại là TL0=0x78 và TH0=)xEC ?
Ở đây mình cho mỗi Led sáng khoảng 5ms, như vậy thời gian xảy ra ngắt sẽ là 5ms. Với thạch anh 12MHz, mỗi giá trị trong thanh ghi của Timer 0 tăng lên 1 đơn vị sau 1us. Do đó, để có 5ms (5000us), mình cần timer đếm 5000 lần thì sẽ xảy ra ngắt. Vậy ta sẽ có giá trị gán cho timer là: 65536-5000=60536, đổi sang số hexa: EC78.
các lệnh tiếp theo là xóa cờ tràn TF0 và cho dừng timer để chúng ta xuất giá trị hiển thị ra Led.
Biến đếm số Led (biến index) được tăng 1 đơn vị trong mỗi lần ngắt để xác định số Led cần hiển thị.
Sau đó mình gọi hàm chuyển đổi số: convert_number(number);
và sau đó là các lệnh xuất bật Led tương ứng với biến index và xuất giá trị chứa trong buff_led ra Led.
Việc khởi tạo timer và cho phép ngắt timer được thực hiển ở trong chương trình chính.
Các bạn có thể tham khảo nội dung code trong file đính kèm.

#include "AT89X52.H"

#define LED8    P2_3            //chân ddieu khien led Q4
#define LED7    P2_2
#define LED6    P2_1
#define LED5    P2_0
#define LED_DATA    P0        //Port xuat du lieu hien thi Led.

//mang chua du lieu Led 7: 0-9
unsigned char ma_led_7[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
//mang chua du lieu da tach cua so can hien thi
unsigned char buff_led[4];
unsigned int number;            //so can hien thi
unsigned char index; //bien dem so led can quet ( so lan ngat xay ra)

//chuong trinh con tao thoi gian tre
void delay_ms(unsigned int time )
{
    unsigned int i,j;
    for(i=0;i<time;i++)
        for(j=0;j<125;j++);
}

//chuong trinh tach so co 4 chu so ra 4 so hàng donvi, chuc, tram, nghin
void convert_number(unsigned int number)
{
    char i;
    for(i=3;i>=0;i--)
        {
            buff_led[i]=ma_led_7[number%10];
            number=number/10;
        }
          
}
//chuong trinh chinh
void main(void)
{

//khoi tao timer và cho phep ngat timer
TMOD=0x01;        //timer 0 che do 16 bit
TL0=0X78;    //Thoi gian ngat bang 5ms
TH0=0XEC;
TF0=0;                //XOA CO BAO TRAN
TR0=1;                //CHO TIMER CHAY

EA=1;                    //cho phep ngat toan cuc
ET0=1;                //cho phep ngat timer 0
    while(1)
        {
            number++;;  
                if(number>9999)            //cho dem tu 0-9999
                    number=0;          
            delay_ms(500);
          
        }
}

//chuong trinh ngat timer 0
//Quet led, hien thi so viet trong chuong trinh ngat
void ngat_timer_0(void) interrupt 1
{
    //khoi tao gia tri lai cho cac thanh ghi
    TL0=0X78;      //Thoi gian ngat bang 5ms
    TH0=0XEC;
    TF0=0;                //XOA CO BAO TRAN
    TR0=0;                //Ngung bo timer
    //tat het cac led
    LED5=LED6=LED7=LED8=1;
    index++;                                    //tang bien dem so led
    convert_number(number);
    if(index==1)                            //neu index=1
        {
            LED5=0;                                //cap nguon cho led va
            LED_DATA=buff_led[0];
        }
    if(index==2)                            //neu index=1
        {
            LED6=0;                                //cap nguon cho led va
            LED_DATA=buff_led[1];
        }
    if(index==3)                            //neu index=1
        {
            LED7=0;                                //cap nguon cho led va
            LED_DATA=buff_led[2];
        }
    if(index==4)                            //neu index=1
        {
            LED8=0;                                //cap nguon cho led va
            LED_DATA=buff_led[3];
            index=0;                            //reset index de lap lai quet tu Led 5
        }
    TR0=1;                                        //cho Timer chay
}          

Tải tài liệu tại đây:
hien thi 4 chu so.rar (27.6 KB)
hien thi 0-9.rar (22.8 KB)

Bài 2. [KIT AT89S52 V3 NEW] GIAO TIẾP ADC/DAC 8Bit PCF8591

Chào các bạn !
Hôm nay mình xin giới thiệu cách giao tiếp với khối ADC/DAC 8 bit PCF8591 trên KIT AT89S52 V3 NEW.
Thông tin về KIT AT89S52 các bạn có thể xem tại:

I.Sơ đồ nguyên lý khối ADC/DAC 8bit PCF8591 trên KIT AT89S52 V3 NEW.


Hai chân giao tiếp I2C được nối với P1.5 và P1.6 qua Jum P7.
Hai kênh đầu vào (ADC) được nối với biến trở VR_ADIN và cảm biến nhiệt độ LM35.
Một đầu ra (DAC) được nối với header AOUT8591.
II.Phân tích nguyên lý hoạt động.
-PCF8591 là một IC tích hợp 2 chức năng là bộ chuyển đổi tín hiệu tương tự thành số(ADC) và bộ chuyển đổi tín hiệu số thành tín hiệu tương tự(DAC) có độ phân giải 8bit,giao tiếp theo chuẩn I2C.
-Bộ chuyển đổi tín hiệu số thành tín hiệu tượng tự trên PCF8591 hoạt động như sau:
Dữ liệu số 8bit đầu vào được lưu trong thanh ghi DAC và sau đó được chuyển đổi thành các mức điện áp khác nhau nhờ bộ chuyển đổi DAC.
Bộ chuyển đổi DAC bao gồm một chuỗi các điện trở liên kết với nhau được nối với đầu vào điện áp tham chiếu bên ngoài.Thông qua các chuyển mạch ,điện áp tham chiếu Vref được chia thành 256 mức điện áp khác nhau.Dữ liệu số trong thanh ghi DAC sẽ lựa chọn chuyển mạch tương ứng giá trị được nhập vào và cho ra giá trị điện áp tương ứng trên chân DAC OUT.

Giá trị điện áp ra được tính toán theo công thức như hình dưới .

-Bộ chuyển đổi tín hiệu tương tự thành tín hiệu số trên PCF8591 hoạt động như sau:
Khi một chu kỳ chuyển đổi được kích hoạt,khối ADC sẽ tiến hành lấy mẫu tín điện áp đầu vào trên kênh tương ứng được chọn rồi lưu trữ trên chíp sau đó chuyển đổi thành số 8bit nhị phân tương ứng.
Điện áp tham chiếu bên ngoài sẽ quyết định giới hạn điện áp có thể nhận biết được.

Công thức chuyển đổi như sau :
Dout=(Vin-VAGND)/((Vref-VAGND)/256)

III.Chương trình giao tiếp.
-PCF8591 giao tiếp theo chuẩn giao tiếp I2C nên ta cần quan tâm các byte sau :
+Byte Address :
[​IMG]
3 bit A2,A1,A0 sẽ xác định địa chỉ thiết bị , ở đây 3 chân địa chỉ của PCF8591 được nối cứng xuống đất nên các giá trị A2,A1,A0 sẽ bằng 0 khi giao tiếp.
Bit R/W xác định chế độ đọc hay ghi.
+Byte Control :


Hai bit thấp xác định kênh đầu vào bộ chuyển đổi ADC của PCF8591.
Bit thứ 2 là cờ kích hoạt chế độ tự động chuyển kênh .
Hai bit 4,5 xác đinh kiểu mắc các kênh đầu vào ở dạng đơn từng kênh hay dạng so sánh.
Bit 6 là bit cho phép đầu ra bộ chuyển đổi DAC của PCF8591 được hoạt động.
-Khung truyền I2C của PCF8591 ở chế độ DAC:

Code :
void PCF8591_Write(uint8_t DA)
{
uint8_t Ack_Temp;
I2C_Start();
delay_ms(10);
I2C_Write(0x90);//byte dia chi
Ack_Temp=I2C_CheckAck();
delay_ms(10);
I2C_Write(0x40);//byte control
Ack_Temp=I2C_CheckAck();
delay_ms(10);
I2C_Write(DA);//byte du lieu
Ack_Temp=I2C_CheckAck();
delay_ms(10);
I2C_Stop();
}

-Khung truyền I2c của PCF8591 ở chế độ ADC :


Code :
uint8_t PCF8591_Read(void)
{
uint8_t Ack_Temp,Data;
I2C_Start();
delay_ms(10);
I2C_Write(0x91); //byte dia chi,che do doc
Ack_Temp=I2C_CheckAck();
Data=I2C_Read();
delay_ms(10);
I2C_Stop();
return Data;

}

Vậy từ 2 hàm này ta có thể giao tiếp với PCF8591 ở 2 chế độ ADC và chế độ DAC .

Các bạn có thể tham khảo code đầy đủ đính kèm theo.
PCF8591 KIT 89S52 V3 NEW.rar (75.3 KB)

Bài 3. [KIT AT89S52 V3 NEW ] GIAO TIẾP VỚI LCD16X2

Chào các bạn!
Hôm nay, mình xin hướng dẫn các bạn giao tiếp với LCD16X2 trên KIT AT89S52 V3 New.
Thông tin về KIT AT89S52 các bạn có thể xem tại:
I. Sơ đồ nguyên lý khối LCD16X2 trên KIT AT89X52 V3 NEW.


>.
Nhìn vào sơ đồ ta thấy, 3 chân điều khiển LCD RS, RW, EN được nối đến các chân P2.2, P2.3, P2.4 của Port 2 và 8 chân dữ liệu của LCD được kết nối đến Port 0.
>. Với cách kết nối như vậy ta có thể tùy chọn chế độ giao tiếp với LCD. Có 2 chế độ giao tiếp với LCD: giao tiếp 8 bit và giao tiếp 4 bit. Tuy nhiên với ưu điểm sử dụng ít chân điều khiển hơn nên chế độ giao tiếp 4 bit trong thực tế được sử dụng nhiều hơn. Do đó, hôm bay mình xin chia sẻ với các bạn thư viện giao tiếp 8051 với LCD16X2 ở chế độ 4 bit. Thư viện có trong file đính kèm ở phía cuối bài.
II. Sử dụng thư viện LCD16x2.
>Thư viện giao tiếp LCD16X2 với 8051 được chứa trong thư mục lcd16x2. (Các bạn giải nén ra sẽ thấy.) Trong thư mục lcd16x2 chứa 2 file:
.File header: lcd16x2.h chứa các khai báo về phần cứng như LCD kết nối đến các chân nào của 8051, và khai báo các hàm sử dụng cho LCD16x2.
.File thực thi: lcd16x2.c là file thực hiện các hàm đã khai báo trong file lcd16x2.h
.Sau khi add file lcd16x2.c vào Project và include thư viện lcd16x2.h, các bạn có thể sử dụng các hàm đã khai báo trong lcd16x2.h để giao tiếp với LCD. Các bạn lưu ý khai báo đúng chân kết nối giữa 8051 và LCD trong file lcd16x2.h để tránh các sai sót không đáng có.
>Sau đây mình xin giới thiệu cách sử dụng một số hàm cơ bản trong thư viện lcd16x2.

  1. Hàm khởi tạo LCD: void lcd1602_init (void );
    Tham biến: không.
    Giá trị trả về: không.
    Hàm khởi tạo được gọi ngay từ đầu chương trình, sau khi gọi hàm khởi tạo lcd, chúng ta mới giao tiếp được với lcd16x2.
    Cú pháp gọi hàm: lcd1602_init();
  2. Hàm xóa LCD: void lcd1602_clear(void);
    Tham biến: không.
    Giá trị trả về: không.
    Hàm này được sử dụng khi bạn muốn xóa toàn bộ ký tự hiển thị trên LCD.
    Cú pháp gọi hàm: lcd1602_clear();
    3. Hàm nhảy đến 1 vị trí bất kỳ trên LCD:
    void lcd1602_gotoxy(unsigned char x, unsigned char y);
    Tham biến: y: vị trí hàng: 0 hàng thứ nhất, 1 hàng thứ 2.
    x: vị trí của cột trong mỗi hàng: x=0: cọt thứ nhất, và x=15: cột thứ 16 (LCD16X2 có 2 hàng, mỗi hàng có 16 cột).
    Cú pháp gọi hàm: Ví dụ muốn nhảy vị trí đầu tiên của hàng đầu tiên ta gọi: lcd1602_gotoxy(0,0);
    4:
    Hàm hiển thị 1 ký tự ra LCD: void lcd1602_putchar ( unsigned int cX );
    Tham biến: Ký tự cần hiển thị.
    Giá trị trả về: không.
    Ví dụ: hiển thị chữ A ra LCD: lcd1602_putchar(‘A’);
  3. Hàm hiển thị một chuỗi ký tự ra LCD: *void lcd1602_puts (char s);
    Tham biến: Chuỗi cần hiển thị.
    Giá trị trả về: không.
    Ví dụ: hiển thị dòng chữ: banlinhkien.vn ra LCD: lcd1602_puts(“banlinhkien.vn”);

Trên đây là cách sử dụng các hàm cơ bản để giao tiếp với LDC16X2. Các bạn có thể tham khảo Project đính kèm để hiểu rõ hơn.
Chúc các bạn thành công.
Tải code bên dưới:
Lcd1602.rar (31.3 KB)

Bài 4. [KIT AT89S52 V3 NEW] GIAO TIẾP KEY4X4

Chào các bạn !
Hôm nay mình xin giới thiệu cách giao tiếp với khối ma trận phím KEY4X4 trên KIT AT89S52 V3 NEW.
Thông tin về KIT AT89S52 các bạn có thể xem tại:

I.Sơ đồ nguyên lý khối ma trận phím KEY4X4 trên KIT AT89S52 V3 NEW.


Ma trận phím 4x4 gồm có 16 nút bấm được sắp xếp theo ma trận 4 hàng, 4 cột. Các nút bấm trong cùng một hàng và một cột được nối với nhau, vì vậy ma trận phím 4x4 sẽ có tổng cộng 8 ngõ ra.
Bốn hàng của ma trận phím KEY4X4 được treo lên VCC thông qua trở treo 10k , đóng mở thông qua switch SW KEY4X4 giúp việc quét phím được ổn định hơn.
II.Phân tích nguyên lý hoạt động.
Để giao tiếp được với ma trận phím 4x4, tôi dùng phương pháp “Quét” để kiểm tra xem nút nào được bấm, cụ thể cách quét như sau (quét theo cột):
-Các chân P1.0, P1.1, P1.2, P1.3 (các hàng) được thiết lập là các chân INPUT, còn lại các chân P1.4, P1.5, P1.6, P1.7 (các cột) là các chân OUTPUT (ở mức logic ‘0’).
-Giả sử BT9 được bấm:
ØCho COL1 = 0 (COL[2…4] = 1) , kiểm tra trạng thái của các hàng:
ROWA= ROWB= ROWC= ROWD=1 : vậy kết luận không có nút được bấm trên COL1.
ØCho COL2 = 0 (COL[1,3,4] = 1) , kiểm tra trạng thái của các hàng:
ROWA=ROWB=ROWD=1, ROWC =0 : vậy kết luận có nút nằm trên hàng C, cột 2 được bấm (BT9).
ØCho COL3 = 0 (COL[1,2,4]=1) : ROWA = ROWB = ROWC= ROWD=1 : vậy kết luận không có nút được bấm trên COL3.
ØCho COL4 = 0 (COL[1,2,3]=1) : ROWA= ROWB= ROWC= ROWD=1 : vậy kết luận không có nút được bấm trên COL4.
Quét tương tự đối với những nút bấm khác.
III.Chương trình giao tiếp.
-Ta lập một ma trận 4X4 chứa mã ASCII của các kí tự được sắp xếp theo yêu cầu.
Ở đây sắp xếp theo KEY 4X4 thông dụng
#include “KEY4X4.H”
const uint8_t KEY_4X4[4][4]={ ‘1’,‘2’,‘3’,‘A’,
‘4’,‘5’,‘6’,‘B’,
‘7’,‘8’,‘9’,‘C’,
‘*’,‘0’,’#’,‘D’ };

-Như phần nguyên lý quét ta sẽ xây dựng các hàm để thực hiện quét như sau :
uint8_t KEY4X4_GetKey()
{
uint8_t temp,temp1;
temp=KEY4X4_CheckRow();
if(temp!=4)
{
delay_ms(5);
temp=KEY4X4_CheckRow();
if(temp!=4)
{
temp1=KEY4X4_ScanCol();
if(temp1!=4)
return KEY_4X4[temp][temp1];
}
}
return NO_KEY;
}

Đầu tiên ta tiến hành kiểm tra hàng phím nào được bấm trên KEY4X4 không thông qua hàm KEY4X4 CheckRow():
Hàm này tiến hành cho tất cả các cột =0(Nối GND),sau đó kiểm tra xem hàng được bấm phím.

uint8_t KEY4X4_CheckRow()
{
    KEY4X4_ROW1=KEY4X4_ROW2=KEY4X4_ROW3=KEY4X4_ROW4=1;
    KEY4X4_COL1=KEY4X4_COL2=KEY4X4_COL3=KEY4X4_COL4=0;
    if(KEY4X4_ROW1==0)
        return 0;
    else
    if(KEY4X4_ROW2==0)
        return 1;
    else
    if(KEY4X4_ROW3==0)
        return 2;
    else    if(KEY4X4_ROW4==0)
        return 3;

    return 4;
}

Giá trị trả về của hàm KEY4X4_CheckRow() là vị trí hàng có phím được bấm.
Tiếp theo ta sẽ kiểm tra xem cột nào có phím được bấm thông qua hàm quét cột KEY4X4_ScanCol():
Hàm này lần lượt cho từng cột=0(Nối GND) sau đó kiểm tra xem có hàng nào bằng =0 , nếu có bất kì hàng nào =0 thì cột đó có phím được bấm.
uint8_t KEY4X4_ScanCol(void)
{
uint8_t i;
for(i=0;i<4;i++)
{
KEY4X4_CheckCol(i);
if((KEY4X4_ROW1==0)|(KEY4X4_ROW2==0)|(KEY4X4_ROW3==0)|(KEY4X4_ROW4==0))
return i;
}
return 4;
}

Giá trị trả về của hàm KEY4X4_ScanCol() là vị trí cột có phím được bấm.
Từ vị trí hàng và cột ta sẽ đọc kí tự tương ứng phím được bấm trong bảng mã đã được tạo phía trên.
-Phần hiển thị được thực hiện trên LCD16X2 ,các bạn cần xem lại bài GIAO TIẾP LCD16X2:
http://hocdientu.vn/threads/kit-at89s52-v3-new-giao-tiẾp-vỚi-lcd16x2.2871/
Các bạn có thể tham khảo code đầy đủ đính kèm theo.
Tải code tại đây:
KEY 4X4 KIT 89S52 V3 NEW.rar (60.7 KB)

Bài 5. [KIT AT89S52 V3 NEW] ĐO TẦN SỐ TỪ KHỐI NE555

Chào các bạn !
Hôm nay mình xin giới thiệu cách giao tiếp với khối tạo xung chuẩn NE555 trên KIT AT89S52 V3 NEW.
Thông tin về KIT AT89S52 các bạn có thể xem tại:

I.Sơ đồ nguyên lý khối NE555 trên KIT AT89S52 V3 NEW.


Đầu ra của NE555 thông qua SW ON/OFF được nối với chân P34 của hàng Jum P2.
II.Phân tích nguyên lý.
-Ne555 là 1 IC dùng để tạo ra nguồn xung chuẩn .
-Tần số ra được tính theo công thức :
F=1/T=1/(C7*(2*VR_NE555+R11)*ln2)

III.Chương trình đo tần số từ NE555.
-Tần số tạo ra từ NE555 trên KIT 89S52 V3 NEW có tần số thấp nên ta tiến hành đo thời gian của 1 chu kỳ xung.Rồi từ đó tính ra tần số.
-Ở chương trình này ta sẽ dùng 2 timer của VĐK 89S52 là Timer0 và Timer1 để tiến hành đo.


+Timer0 sẽ giúp ta xác định được thời điểm một chu kỳ bắt đầu và kết thúc tại thời điểm nào.
+Timer1 sẽ giúp ta xác định thời gian một chu kỳ xung .

-Timer0 sử được cài đặt ở chế độ 3 ,nguồn cấp xung chọn từ chân T0

-Nguyên lý hoạt động chế độ 3 :
Timer0 sẽ sử dụng thanh ghi TL0 làm bộ đếm xung,TH0 làm thanh ghi chứa giá trị nạp lại.
Nguồn xung được chọn từ đầu vào chân P3.4(T0) qua bit C/T0 ở thanh ghi TMOD
Khi Timer0 bắt đầu hoạt động,mỗi khi bộ đếm TL0 xảy ra tràn thì giá trị trong thanh ghi TH0 sẽ được tự động nạp vào thanh ghi TL0,đồng thời nếu kích hoạt ngắt tràn ở timer0 thì sẽ có 1 ngắt được xảy ra.
-Dựa vào nguyên lý hoạt động timer0 ở chế độ 3 ta dễ dàng xác định thời điểm bắt đầu vào kết thúc một chu kỳ :
Ta sẽ đặt giá trị ban đầu cho TH0=255 và TL0=255 .Khi timer0 bắt đầu hoạt động nếu có một cạnh xuống của xung kích vào chân P3.4(T0) thì bộ đếm TL0 sẽ tràn ,và một ngắt sẽ sinh ra đồng thời giá trị 255 trong TH0 được tự động nạp lại vào TL0 .Tại chương trình ngắt ta sẽ tiến hành tính toán giá trị chu kỳ nhờ vào Timer 1.
void Timer0_Init(void)
{
TMOD|=0x06;//che do 8 bit autoreload ,Nguon xung dau vao T0//P34
TH0=255;
TL0=255;
ET0=1;//cho phep ngat timer0
TR0=1;//cho phep timer0 hoat dong
}
-Timer 1 sẽ được cài đặt ở chế độ 1,đầu vào bộ đếm là nguồn xung nuôi chíp :


-Nguyên lý hoạt động Timer1 ở chế độ 1:
Timer1 sử dụng thanh cặp thanh ghi TH1,TL1 làm bộ đếm 16 bit (0->65535).
Khi Timer1 bắt đầu hoạt động.Nếu có một xung vào bộ đếm sẽ tăng lên 1 giá trị .Đến khi nào giá trị bộ đếm bị tràn Timer1 sẽ bật cờ tràn TF1 ,nếu kích hoạt ngắt tràn timer1 thì sẽ có một ngắt xảy ra.
Việc cài đặt như sau :
void Timer1_Init(void)
{
TMOD|=0x10;//che do 16 bit,Nguon xung dau vao FOSC/12
ET1=1; //cho phep ngat tran timer1
TR1=1;//cho phep Timer1 hoat dong
}
-Đoạn chương trình xử lý và tính toán chu kỳ xung sẽ được đặt trong chương trình ngắt của Timer 0 và Timer1:
Chương trình ngắt Timer1 sẽ cộng dồn giá trị đếm của bộ đếm Timer1
void Interrupt_Timr1(void) interrupt TF1_VECTOR
{
Timer1_Counter+=0xffff;
}
Chương trinh ngắt Timer2 sẽ tính toán giá trị chu kỳ của xung :
void Interrupt_Timer0(void)interrupt TF0_VECTOR
{
//doc gia tri hien tai timer1
Value=(uint16_t)TH1<<8;
Value+=TL1;
Chu_Ky=Timer1_Counter-Old_Value+Value;
Old_Value=Value;
Timer1_Counter=0;
}
-Tần số được tính toán trong chương trinh chính:
Tan_So=((float)F_OSC/(float)(12*Chu_Ky));
F_OSC ở đây là tần số thạch anh
Biến Chu_Ky chứa giá trị mà bộ đếm Timer1 đếm được trong 1 chu kỳ xung.
Giá trị 12 là hệ số chia của thạch anh sau khi qua bộ tạo xung chuẩn nuôi cho chíp.

-Chương trình hiển thị giá trị tần số sử dụng LCD16x2 các bạn có thể tham khảo cách giao tiếp LCD 6x2 tại đây :
http://hocdientu.vn/threads/kit-at89s52-v3-new-giao-tiẾp-vỚi-lcd16x2.2871/

Các bạn có thể tham khảo code đầy đủ kèm theo .
Tải code tại đây: NE555 KIT 89S52 V3 NEW.rar (70.7 KB)

Bài 6. [KIT AT89S52 V3 NEW] GIAO TIẾP CẢM BIẾN NHIỆT ĐỘ LM35

Chào các bạn !
Hôm nay mình xin giới thiệu cách giao tiếp với cảm biến nhiệt độ trên KIT AT89S52 V3 NEW.
Thông tin về KIT AT89S52 các bạn có thể xem tại:

I.Sơ đồ nguyên lý mắc cảm biến nhiệt độ LM35 trên KIT AT89S52 V3 NEW.


Cảm biến nhiệt độ LM35 được kết hợp với khối ADC PCF8591 trên KIT để chuyển đổi tín hiệu tương tự từ đầu ra cảm biến LM35 thành tín hiệu số để giao tiếp với khối xử lý thông qua kênh AIN1 được kết nối bằng Jum P7.
II.Phân tích nguyên lý hoạt động.
[​IMG]

[​IMG]
-LM35 : là cảm biến nhiệt độ mạch tích hợp chính xác cao có đầu ra dạng điện áp tỉ lệ tuyến tính với nhiệt độ.
Họ cảm biến này cho ra mức thay đổi 10mV tương ứng với sự thay đổi của 1°C.


-Kết hợp với ADC PCF8591 , ta tính toán được nhiệt độ theo công thức sau:

Tempr=((Dout*(Vref-VAGND)/256)*1000)/10

Dout : Đẩu ra dạng số của ADC PCF8591
Vref : Điện áp tham chiếu của ADC PCF8591
VAGND : Điện áp đất tương tự
-Ở trên KIT 89S52 V3 NEW thì Vref=5V ,VAGND=0V ,nên ta có công thức cụ thể như sau :
Tempr=((Dout*(5/256))*1000)/10
III.Chương trình giao tiếp.
-Chương trình giao tiếp với LM35 sử dụng ADC/DAC 8 bit PCF8591 nên bạn cần tham khảo bài viết sau :
http://hocdientu.vn/threads/kit-at89s52-v3-new-giao-tiẾp-adc-dac-8bit-pcf8591.2941/
-Sử dụng công thức trên và hàm đọc giá trị Dout từ bộ chuyển đổi ADC trên PCF8591 ta dễ dàng tính được nhiệt độ:
void main(void)
{
uint8_t Lcd[16],AD_Temp;
float32_t Tempr;
LCD1602_Init();
I2C_Init();
PCF8591_Init();
LCD1602_GotoXY(2,0);
sprintf(Lcd,"MINHHA GROUP ");
LCD1602_Puts(Lcd);

    while (1)
    {
        AD_Temp=PCF8591_Read();
        Tempr=((AD_Temp*(5.0/256))*1000)/10;
        LCD1602_GotoXY(0,1);
        sprintf(Lcd,"Nhiet Do:%0.1fC    ",Tempr);
        LCD1602_Puts(Lcd);  
        delay_ms(1000);                                
    }
}

Tải code tại đây: LM35 KIT 89S52 V3 NEW.rar (81.9 KB)

Bài 7. [KIT AT89S52 V3 NEW] GIAO TIẾP IR1838T

Chào các bạn !
Hôm nay mình xin giới thiệu cách giao tiếp với cảm biến hồng ngoại IR1838 trên KIT AT89S52 V3 NEW.
Thông tin về KIT AT89S52 các bạn có thể xem tại:

I.Sơ đồ nguyên lý khối cảm biến hồng ngoại IR1838 trên KIT AT89S52 V3 NEW.


Đầu ra dữ liệu của IR1838 được nối với chân P1.1 thông qua jum chốt ở Header P7
II.Phân tích nguyên lý.

  1. Cảm biến hồng ngoại IR1838
    -Chức năng : Thu tín hiệu sóng hồng ngoại chuyển đổi thành tín hiệu dạng số .
    [​IMG]
    -Cấu tạo bên trong của IR1838 như sau :


    2.Remote hồng ngoại .
    [​IMG]
    -Chức năng : Remote là thiết bị phát sóng hồng ngoại,sử dụng để điều khiển các thiết bị từ xa.Mỗi phím bấm trên remote sẽ được mã hóa với một mã riêng biệt ,mắt thu IR1838 sẽ thu tín hiệu hồng ngoại và đưa ra dạng tín hiệu số,ta sẽ giải mã để thu được mã phím bấm tương ứng .
    -Khung truyền của remote trên như sau:
    [​IMG]
    +Bit start : thời gian mức 0 là 9ms ,thời gian mức 1 là 4ms.
    +Bit 0: thời gian mức 0 là 700us , thời gian mức 1 là 500ms.
    +Bit 1 : thời gian mức 0 là 700us , thời gian mức 1 là 1600ms.
    Khung truyền gồm : bit start ,8 bit 0 ,8 bit 1,và 8 bit dữ liệu
    III.Chương trình giao tiếp cảm biến IR1838.
    Code trong chương trinh gồm 2 hàm chính như sau :
    -Hàm con thứ nhất dùng để kiểm tra bit start của chuỗi xung hồng ngoại.
    unsigned char Check_Start(void)
    {
    unsigned char i;
    Data=1;
    if(Data==0)
    {
    delay_us(500); //delay chong nhieu
    if(Data==0);
    {
    for(i=0;i<35;i++) //Chia nho thanh 35 khoang thoi gian de xet
    {
    delay_us(200);
    if(Data==1)
    return NO_START;
    }
    while(Data==0);
    while(Data==1);
    return START;
    }

     }
     return NO_START;   
    

    }

Bit start có đặc điểm : thời gian mức 0 là 9m , mức 1 là 4ms .
Ta sẽ tiến hành kiểm tra bit start bằng cách giám sát khoảng thời gian xung thu được ở mức 0 có đúng tầm 9ms hay không .Nếu trong khoảng thời gian đó xung trở về mức cao thì đây không phải là bit start trả vể NO_START ,còn nếu xung vẫn ở mức 0 trong khoảng thời gian 9m thì ta nhận biết đây là bit start và trả về là START.
-Hàm con thứ hai có chức năng đọc dữ liệu vào nếu có bit START được phát hiện ở hàm kiểm tra bit START

unsigned char Receiver_Data(void)
{
    unsigned char Temp,Temp2,i;
    unsigned char Code=0;
    Temp=Check_Start();
    if(Temp==START)
    {
        P1_3=1;
        while(Data==0);
        //Lay 24 bit gom 8 bit 0,8 bit 1 va 8 bit du lieu vao ,bit co trong so thap nhat duoc truyen dau tien
        for(i=0;i<24;i++)
        {
            delay_us(750);
            Code>>=1;
            if(Data==1)Code|=0x80;
            while(Data==1);
            while(Data==0);
        }
        delay_ms(500);
    }
    return Code;
}

Sau khi kiểm tra đúng là có bit START được truyền đi thì ta sẽ tiến hành đọc dữ liệu vào .Trong hàm này ta sẽ tiến hành kiểm tra Bit được truyền đến là 0 hay 1 .
Như ở trên đã giới thiệu Bit 0 có mức 0 trong khoảng 700us và mức 1 trong khoảng 500us ,còn Bit 1 có mức 0 trong khoảng 700us và mức 1 trong khoảng 1600us .
Vậy bit 0 khác bit 1 ở khoảng thời gian kéo dài mức 1 . Ta sẽ tiến hành kiểm tra bit 0 hay bit 1 tại vị chí sau mức 0 tầm 750us > 500us thời gian kéo dài mức 1 của bit 0.

Các bạn có thể tham khảo code đầy đủ kèm theo .
Nguồn: http://hocdientu.vn/threads/kit-at89s52-v3-new-giao-tiep-ir1838.2920/
Tải code tại đây: main.rar (953 Bytes)

Bài 8. [KIT AT89S52 V3 NEW] ĐIỀU KHIỂN LED ĐƠN.

Chào các bạn!
Hôm nay mình xin gửi đến các bạn hướng dẫn các bạn điều khiển Led đơn trên KIT AT89S52 V3 New.
Thông tin về sản phẩm KIT AT89S52 V3 New các bạn có thể xem tại.
I. Sơ đồ nguyên lý khối Led đơn trên KIT AT89S52 V3 New.


II. Viết chương trình.
Nhìn vào sơ đồ nguyên lý trên ta thấy: Các chân katot của Led được nối với các chân Port 1 của Vi điều khiển AT89S52. Do đó: Để led sáng, chúng ta cần xuất tín hiệu có mức logic thấp (mức 0) ra các chân của Port 1, và ngược lại, để led tắt chúng ta xuất tín hiệu mức logic cao(mức 1) ra các chân của Port1.
Việc xuất tín hiệu cho các Port của 8051 bằng ngôn ngữ C khá đơn giản. Chúng ta chỉ cần dùng lệnh gán ("=") của C để thực hiện thao tác xuất tín hiệu cho các Port.
Vi dụ: để làm sáng 8 led mắc như trong sơ đồ trên chúng ta dùng lệnh:
P1=0x00;
Và để tắt 8 led, chúng ta dùng lệnh: P1=0xff;
Vậy ta có chương trình bật tắt led như sau:

//chuong trinh chính
//noi dung: bat, tat 8 led don 1 cach đồng thời.
void main(void)
{
P1=0x00;                        //bật tất cả 8 led
P1=0xff;                          //tắt tất cả 8 led
}

Vì thời gian thực hiện 1 lệnh của Vi điều khiển là rất nhanh (tính bằng us), nên nếu chỉ dùng 2 lệnh bật và tắt led như trên thì bằng mắt thường chúng ta không thể quan sát được sự thay đổi trạng thái của led.
Do vậy, để có thể quan sát được sự thay đổi trạng thái của Led, chúng ta cần gọi một chương trình tạo trễ (delay) sau mỗi lệnh bật, tắt led. Thực ra chương trình tạo trễ là chương trình cho vi điều khiển thực hiện một công việc vô nghĩa nào đó trong 1 thời gian nhất định mà người dùng muốn.
Sau đây là 1 đoạn code tạo thời gian trễ với đơn vị ms thường được sử dụng cho 8051 (với thạch anh 12MHz).

//chương trình con delay_ms
void delay_ms(unsigned int time)
{
unsigned int i,j;
for(i=0;i<time;i++)
        for(j=0;j<125;j++);
}

Mỗi khi cần tạo 1 khoảng thời gian trễ bằng bao nhiêu ms , chúng ta chỉ cần gọi hàm:
delay_ms(<thời gian trễ>);
ví dụ: mình cần trễ 500ms: delay_ms(500);
Như vậy, để cho Led nhấp nháy mà mắt người quan sát được. Chúng ta có thể thêm 2 dòng lệnh tạo trễ sau mỗi lần bật, tắt led như sau:

#include <AT89X52.H>

//chương trình con delay_ms
void delay_ms(unsigned int time)
{
unsigned int i,j;
for(i=0;i<time;i++)
        for(j=0;j<125;j++);
}

//chuong trinh chính
//noi dung: bat, tat 8 led don 1 cach đồng thời.
void main(void)
{
P1=0x00;                        //bật tất cả 8 led
delay_ms(500);          //Trễ 500 ms để quan sát led sáng
P1=0xff;                          //tắt tất cả 8 led
delay_ms(500);          //Trễ 500 ms để quan sát led tắt
}

Có 1 nhược điểm của đoạn code trên đó là khi chúng ta thay đổi chân điều khiển led sang Port khác (ví dụ Port 3 chẳng hạn), chúng ta lại phải vào hàm main để sửa P1 thành P3. Để khắc phục điều này, người ta thường sử dụng từ khóa "#define " để đặt tên cho 1 đối tượng nào đó. Khi cần sử dụng, chỉ cần gọi tên chứ không cần gọi tên Port điều khiển như ở trường hợp trên.
Khai báo #define thường được đặt ở đầu chương trình, hoặc đặt ở trong các file header (file có đuôi .h).
Chương trình trên chúng ta có thể sửa lại như sau.

#include <AT89X52.H>
#define  LED    P1

//chương trình con delay_ms
void delay_ms(unsigned int time)
{
unsigned int i,j;
for(i=0;i<time;i++)
        for(j=0;j<125;j++);
}

void main(void)
{
LED=0x00;                        //bật tất cả 8 led
delay_ms(500);          //Trễ 500 ms để quan sát led sáng
LED=0xff;                          //tắt tất cả 8 led
delay_ms(500);          //Trễ 500 ms để quan sát led bật
}

Như vậy khi chuyển sang Port 3 chúng ta chỉ cần sửa 1 lần ở đầu chương trình: #define LED P1 thành #define LED P3.
Các bạn có thể tạo 1 Project trên Keil C và coppy toàn bộ nội dung đoạn code trên vào file main.c, sau đó biên dịch và chạy thử.
Việc tạo Project mới trên Keil C các bạn có thể xem tại:
http://hocdientu.vn/threads/video-hƯỚng-dẪn-tẠo-project-vỚi-keil-c-4-cho-8051.2856/
Hoặc download code mẫu ở cuối chương trình.
Led Don.rar (14.3 KB)
Nguồn: http://hocdientu.vn/threads/kit-at89s52-v3-new-dieu-khien-led-don.2857/