Chủ Nhật, 28 tháng 2, 2016

Bài 2: GPIO với 8051: Điều khiển led đơn.

 

 I. Mở Đầu.

Chào các bạn!

     Một trong những bài học căn bản khi các bạn bước đầu tìm hiểu về một dòng vi điều khiển nào đó là bài học về GPIO (điều khiển vào/ra với các chân của vi điều khiển). Bài học này giúp cho các bạn bước đầu cảm thấy hứng thú để tiếp tục theo đuổi niềm đam mê lập trình vi điều khiển và đây cũng là bài học cơ bản giúp các bạn hiểu về cách xuất tín hiệu/nhận tín hiệu trên các chân của vi điều khiển.
     Cũng với mục đích như vậy, hôm nay mình xin gửi đến các bạn bài viết hướng dẫn điều khiển led đơn với vi điều khiển 8051. điều khiển led đơn xin được cắt nghĩa ở đây là dùng vi điều khiển xuất tín hiệu để bật/tắt led (1 hoặc nhiều led), hoặc có thể xây dựng hiệu ứng sáng cho nhiều led tùy vào mục đích của người dùng.

II. Nguyên Lý Điều Khiển LED.

     Để điều khiển được led, ngoài kiến thức về lập trình(Software), các bạn cũng cần có kiến thức về phần cứng (Hardware) để khi nhìn sơ đồ mạch có thể hiểu được khi nào thì led sẽ sáng và khi nào led sẽ tắt. 
     Có những mạch khi xuất mức 0 (0V) ra chân của vi điều khiển thì led sáng, nhưng cũng có những mạch khi xuất mức 1(5V) ra chân của vi điều khiển thì led mới sáng. Nhưng cho dù có ở mạch nào thì để điều khiển led đơn sáng thì phải tuân thủ nguyên tắc led sáng khi có dòng điện chạy qua led, nghĩa là phải có sự chênh lệch áp giữa hai cực Anot và Katot của led. Mình xin giới thiệu 2 dạng mạch điện điều khiển led đơn dùng vi điều khiển như sau.
                                
                                   
         Hình 1.1: Led sáng khi xuất mức 0                           Hình 1.2: Led sáng khi xuất mức 1

     Mình xin giải thích sơ đồ hình 1.1. Như mình đã nói để led sáng thì cần làm sao cho có dòng điện chạy qua led, nghĩa là có sự chênh lệch áp giữa 2 cực Anot, Katot của led. Nhìn vào hình 1.1 ta thấy cực Anot của led được nối qua trở 330R lên nguồn 5V, vậy để có dòng điện chạy qua led ta cần xuất mức 0 (0V) ra chân của vi điều khiển, khi đó led sẽ sáng, và để tắt led ta sẽ xuất mức 1(5V) ra chân của vi điều khiển, khi đó sẽ không có dòng chạy qua led và led sẽ tắt. Dòng chạy qua led không được quá lớn nên chúng ta cần phải sử dụng trở hạn dòng để tránh cháy led như trên 2 sơ đồ đã cho. Sơ đồ hình 1.2 chắc mình không cần giải thích nữa :D.
     Thôi, nói lan man như vậy đủ rồi, bây giờ đi vào chủ đề chính, điều khiển led đơn với 8051. Trước hết mình xin giới thiệu sơ đồ nguyên lý mình sử dụng. Đây cũng chính là sơ đồ nguyên lý điều khiển led đơn trên Kit 8051 Basic. Chi tiết về Kit này các bạn có thể xem tại đây.

III. Viết Chương Trình.

     1. Các bạn mở Keil C và tạo một project để viết chương trình điều khiển led đơn theo sơ đồ trên. Bạn nào chưa biết tạo project với Keil C có thể tham khảo bài viết: Hướng dẫn tạo project với Keil C.
     2. Phần đầu chương trình cũng như bao chương trình C khác, mình gọi thư viện và define các macro chân điều khiển led.

//su dung thu vien
#include <at89x52 .h>
//Define macro port dieu khien led
#define  LED_PORT   P2
//Define macro chan dieu khien led
#define   LED1           P2_0
#define  LED2    P2_1
#define  LED3    P2_2
#define  LED4    P2_3
#define  LED5    P2_4
#define  LED6    P2_5
#define  LED7    P2_6
#define  LED8    P2_7

Việc sử dụng lệnh #define này giúp cho việc quản lý bảo trì code dễ hơn, ví dụ, khi bạn vẫn sử dụng chương trình này cho một mạch khác, có led nối vào chân khác của vi điều khiển, bạn chỉ cần thay thế code ở phần define này. Và việc đặt tên bằng define này cũng giúp cho người khác khi đọc code của bạn viết sẽ dễ hiểu hơn.

     3. Bật/Tắt Led trên 1 chân.

     Để bật/tắt led trên 1 chân nào đó, chúng ta xuất tín hiệu điều khiển (mức 0 hoặc 1) ra trực tiếp chân đó. Ví dụ như trên sơ đồ, led D1 được nối vào chân P2_0, vì vậy để bật led D1 sáng mình xuất mức 0 ra chân P2_0 và để tắt led D1 mình xuất mức 1 ra chân P2_0. Vì chân P2_0 được define ở trên bằng tên LED1, do đó lệnh bật tắt led trên chân này như sau.

//chuong trinh chinh
void main (void)
{
 while(1)
 {
  /*Bat led 1*/
  LED1 = 0;
  /*Tat led 1*/
  LED1 = 1;
 }
}

     Như đoạn code trên thì led sẽ sáng rồi tắt và cứ lặp lại mãi mãi như vậy (do nằm trong while(1)), nghĩa là led nhấp nháy mãi mãi. Nhưng chương trình nếu chỉ như vậy thì các bạn sẽ không quan sát được hiện tượng nhấp nháy, bởi vì led sáng/tắt trong thời gian quá nhanh (cỡ đơn vị us nên mắt người không thể quan sát được hiện tượng nhấp nháy).
     Vậy làm sao để quan sát được hiện tượng nhấp nháy led này? Có một cách mà mọi người vẫn hay sử dụng, đó là sử dụng hàm trễ (delay). Hàm trễ là hàm có chức năng ra lệnh cho vi điều khiển thực hiện một công việc gì đó nhiều lần để khi làm xong công việc đó thì kéo dài một khoảng thời gian mà người lập trình mong muốn. Ý tưởng được đưa ra ở đây là sau khi bật led sáng sẽ cho vi điều khiển làm một công việc gì đó nhiều lần bằng hàm delay, để mắt người quan sát được led sáng, sau đó tắt led và cũng gọi hàm delay, để mắt người quan sát được led tắt, vậy là quan sát được hiện tượng led nhấp nháy. Nội dung hàm delay thường được viết như sau.

/*
Function name: delay_ms
parameter in:  time delay
return:        no
*/
void delay_ms(unsigned int time)
{
 unsigned int i,j;
 for(i=0;i<time;i++)
  for(j=0;j<125;j++);
}

     Để sử dụng hàm delay_ms ở trên rất đơn giản, các bạn muốn vi điều khiển trễ (delay) một khoảng thời gian bao nhiêu ms, các bạn chỉ gọi hàm và truyền tham số là thời gian trễ bằng đơn vị ms vào hàm. Ví dụ mình muốn trễ 1s = 1000ms mình sẽ gọi hàm như sau: delay_ms(1000);
     Vì vậy để led D1 nhấp nháy với chu kì 2s(nghĩa là led sáng trong 1s và led tắt trong 1s) mình sẽ sửa lại chương trình chính như sau.

//chuong trinh chinh
void main (void)
{
 while(1)
 {
  /*Bat led 1*/
  LED1 = 0;
  delay_ms(1000);   //goi ham delay voi time = 1000ms
  /*Tat led 1*/
  LED1 = 1;
  delay_ms(1000);   //goi ham delay voi time = 1000ms
 }
}

      4. Bật/Tắt 8 Led.

     Để bật/tắt cùng lúc 8 led thì có nhiều cách, có thể các bạn dùng 8 lệnh thao tác với 8 chân để bật tắt, hoặc có thể dùng cách xuất dữ liệu ra Port. Cách dùng xuất dữ liệu ra tầng chân để điều khiển 8 led thì mình sẽ không dùng, vì nó sẽ làm dài chương trình ra, vì vậy mình sẽ sử dụng cách xuất dữ liệu ra port, cụ thể ở sơ đồ trên là xuất dữ liệu ra port P2, được define bằng tên LED_PORT.
     Lệnh xuất dữ liệu ra port P2 như sau.

LED_PORT = giá_tri; //tuong duong voi: P2 = gia_tri;
     Các bạn nên hiểu giá trị ở đây bây giờ sẽ là giá trị của 8 bit (8 chân port P2), do vậy nó sẽ có giá trị trong khoảng 0-255(hệ thập phân) hay 0x00-0xFF hệ số hexa.
     Như vậy chương trình bật/tắt 8 led được viết như sau.

//chuong trinh chinh
void main (void)
{
 while(1)
 {
  /*Bat 8 led*/
  LED_PORT = 0x00;   
  delay_ms(1000);   //goi ham delay voi time = 1000ms
  /*Tat 8 led */
  LED_PORT = 0xFF;
  delay_ms(1000);   //goi ham delay voi time = 1000ms
 }
}

     5. Xây dựng các hiệu ứng khác.

     Để xây dựng các hiệu ứng khác như 1 led sáng từ trái sang phải, hoặc phải sang trái, hoặc led sáng đuổi....Các bạn nên sử dụng 1 biến 8 bit để chứa giá trị của led, sau đó xuất giá trị của biến này ra port điều khiển led, sau đó thay đổi giá trị tùy theo hiệu ứng mình muốn và lại tiếp tục xuất ra port điều khiển led.
     Sau đây, mình xin giới thiệu các bạn đến chương trình 1 led sáng từ trái sang phải. Các hiệu ứng khác các bạn tự tìm cách thay đổi nhé.
     Ý tưởng: Dùng 1 biến 8 bit có giá trị ban đầu 0x80, nghĩa là 7 led sáng, 1 led tắt. Nhưng khi mình xuất ra port điều khiển, mình sẽ xuất giá trị đảo của biến trên. Sau đó sử dụng lệnh dịch phải bit để dịch bit 1 sang phải để tạo hiệu ứng 1 led sáng từ trái sang phải. Chương trình như sau.

//chuong trinh chinh
void main (void)
{
    unsigned char led_value = 0x80; //bien chua gia tri sang cua led
    while(1)
       {
 /*Xuat giá tri ra port de lam sang led*/
 LED_PORT = ~led_value;
 delay_ms(1000);   //goi ham delay voi time = 1000ms
 /*dich phai 1 bit*/
 led_value >>= 1;
 if(led_value == 0)
   led_value = 0x80;
       }
}

     Mình xin giải thích lại đoạn chương trình trên như sau:
     Đầu tiên, minh khai báo biến led_value  có giá trị 0x80. (Dạng nhị phân 8 bit: 1000 0000).
     Sau đó mình xuất ra P2 giá trị đảo của led_value  nghĩa là P2 = 0x7F = 0111 1111 (Led D8 sáng).
     Gọi hàm delay_ms để có thể nhìn thấy led sáng.
     Dịch phải 1 bit giá trị của biến led_value: led_value >>= 1; sau lệnh này, giá trị của led_value là:
led_value = 0x40 = 0100 0000.
     Kiểm tra xem giá trị của biến led_value có bằng 0 hay không, giá trị của biến led_value = 0 khi đã dịch phải đủ 8 lần, nếu chưa bằng 0, nhảy đến lệnh xuất giá trị đảo của biến led_value ra P2, nếu bằng 0 thì reset lại giá trị của biến led_value để chạy lại từ đầu.

     Các bạn có thể tải toàn bộ chương trình và mạch mô phỏng trên Proteus tại link sau.
http://www.mediafire.com/download/4teo6u5s5593zca/Bai_1_Led_don.rar

Chúc các bạn thành công!





1 nhận xét:
Write nhận xét
  1. Harrah's New Orleans Casino & Hotel - Mapyro
    Discover 토토사이트 and compare Harrah's 광양 출장안마 New Orleans Casino & 울산광역 출장안마 Hotel in New Orleans. Find reviews and 거제 출장샵 photos 동두천 출장안마 from 12835 visitors about

    Trả lờiXóa