Trong hướng dẫn trước của chúng tôi, chúng tôi đã tìm hiểu về Nhấp nháy đèn LED bằng vi điều khiển PIC và xây dựng mạch tương tự trên bảng Perf. Sau đó, chúng tôi sử dụng PICkit 3, ICSP và MPLAB IPE để kết xuất chương trình lên bảng Perf của chúng tôi. Bây giờ, trong hướng dẫn này, chúng ta sẽ tự nâng cao khả năng sử dụng nhiều chân hơn trên vi điều khiển PIC. Chúng tôi sẽ sử dụng 7 đầu ra (LED) và một Đầu vào. Đối với hướng dẫn này, chúng tôi sẽ sử dụng bảng Perf cũ (hiển thị bên dưới) và sẽ thêm các thanh berg để kéo các chân cần thiết lên bảng LED thứ hai. Ở phần cuối của hướng dẫn này, chúng ta sẽ Tạo chuỗi đèn LED nhấp nháy bằng cách sử dụng vi điều khiển PIC PIC16F877A và sẽ học cách sử dụng nhiều đầu vào và đầu ra, một số điều cơ bản về vòng lặp 'for' và gọi hàm.
Bảng LED không là gì khác ngoài một bảng hiệu suất khác, trên đó chúng tôi sẽ hàn đèn LED với một Điện trở giới hạn dòng điện (hiển thị bên dưới). Chúng tôi cũng sẽ thêm một nút bấm để bắt đầu nhấp nháy đèn LED tuần tự.
Sơ đồ mạch:
Bộ vi điều khiển PIC PIC16F877A LED nhấp nháy Mã trình tự và giải thích hoạt động:
Mã hoàn chỉnh đã được cung cấp bên dưới (kiểm tra ở cuối), ở đây chúng tôi sẽ lấy nó từng dòng một. Mã này sẽ bắt đầu phát sáng các đèn LED theo cách tuần tự khi nhấn nút nhấn. Để hiểu các trình tự, vui lòng xem video ở cuối hướng dẫn. Tôi khuyên bạn nên so sánh đầu ra được hiển thị trong video với mã bên dưới và cố gắng hiểu chương trình.
Chúng ta hãy xem xét từng dòng mã. Vài dòng đầu tiên là để thiết lập các bit cấu hình đã được giải thích trong hướng dẫn trước, vì vậy tôi đang bỏ qua chúng ngay bây giờ. Cách tốt nhất để hiểu bất kỳ chương trình nào là bắt đầu từ hàm main ( void main () ), vì vậy hãy làm điều đó
TRISB0 = 1; // Hướng dẫn MCU rằng chân PORTB 0 được sử dụng làm đầu vào cho nút. TRISD = 0x00; // Hướng dẫn MCU rằng tất cả các chân đều là đầu ra PORTD = 0x00; // Khởi tạo tất cả các chân thành 0
Từ TRIS được sử dụng để xác định xem chân có đang được sử dụng làm đầu vào / đầu ra hay không và từ PORT được sử dụng để làm cho chân cắm Cao / Thấp. Dòng TRISB0 = 1 sẽ làm cho chân thứ 0 của PORT B làm đầu vào. Đây sẽ là nút bấm của chúng tôi. Các dòng TRISD = 0x00; PORTD = 0x00; sẽ biến tất cả các chân của cổng D làm Đầu ra và gán giá trị ban đầu là LOW cho các chân đó.
Vì chúng tôi đã nói rằng B0 được sử dụng làm đầu vào, chúng tôi sẽ kết nối một đầu của nút nhấn với chân B0 và đầu kia với đất. Sau đó, bất cứ khi nào chúng ta nhấn nút, chốt sẽ được giữ tiếp đất như thể hiện trong sơ đồ kết nối ở trên. Nhưng để điều này xảy ra, chúng ta phải sử dụng một điện trở kéo lên để chốt sẽ được giữ ở mức cao khi nút không được nhấn. Một điện trở kéo lên là một cái gì đó như thế này.
Nhưng MCU PIC của chúng tôi có một điện trở kéo lên yếu bên trong có thể được kích hoạt bằng phần mềm theo cách đó giúp tiết kiệm rất nhiều rắc rối (khi nhiều nút được kết nối).
Một điện trở kéo lên yếu là gì?
Có hai loại điện trở kéo lên, một là kéo lên yếu và kéo lên mạnh. Điện trở kéo lên yếu có giá trị cao và do đó cho phép dòng điện yếu chạy qua và điện trở kéo lên mạnh có giá trị thấp do đó cho phép dòng điện mạnh chạy qua. Tất cả MCU hầu hết sử dụng điện trở kéo lên yếu. Để kích hoạt điều này trong MCU PIC của chúng tôi, chúng tôi phải xem xét bảng dữ liệu của chúng tôi cho OPTION_REG (thanh ghi tùy chọn) như được hiển thị trong ảnh chụp nhanh bên dưới.
Như được hiển thị, bit 7 xử lý điện trở kéo lên yếu. Nó nên được làm bằng không để kích hoạt nó. Điều này được thực hiện bởi OPTION_REG <7> = 0 . Điều này đặc biệt giải quyết với bit 7 để các bit khác về giá trị mặc định của nó. Với điều này, chúng ta vào vòng lặp while, nơi nó kiểm tra xem nút có được nhấn hay không bằng cách sử dụng if (RB0 == 0). Nếu điều kiện được thỏa mãn, chúng ta gọi hàm của chúng ta với các tham số 1, 3, 7 và 15.
sblink (1); // FUNCTION CALL 1 với tham số 1 sblink (3); // FUNCTION CALL 3 với tham số 3 sblink (7); // FUNCTION CALL 7 với tham số 7 sblink (15); // FUNCTION CALL 4 với tham số 15
Tại sao chúng ta sử dụng các hàm?
Các hàm được sử dụng để giảm số dòng trong mã của chúng tôi. Đây là điều mà hầu hết chúng ta đều biết. Nhưng tại sao chúng ta cần giảm số lượng dòng, đặc biệt là khi nói đến lập trình MCU. Các lý do là không gian hạn chế trong bộ nhớ chương trình của chúng tôi. Nếu chúng tôi không tối ưu hóa mã đúng cách, chúng tôi có thể hết dung lượng bộ nhớ. Điều này sẽ hữu ích khi chúng ta viết các trang mã dài.
Bất kỳ hàm nào sẽ có một hàm Định nghĩa ( sblink (int get) trong trường hợp của chúng ta) và một hàm Gọi ( sblink (1) trong trường hợp của chúng ta). Việc khai báo hàm là tùy chọn, để tránh nó, tôi đã đặt định nghĩa hàm trước khi gọi hàm vào hàm chính của mình.
Tham số hàm là giá trị sẽ được truyền từ lệnh gọi hàm đến định nghĩa hàm. Trong trường hợp của chúng ta, các giá trị nguyên (1, 3, 7, 15) là các tham số được truyền từ lệnh gọi hàm và biến "get" nhận giá trị của các tham số vào định nghĩa hàm để xử lý chúng. Một hàm có thể có nhiều hơn một tham số.
Khi hàm được gọi, các dòng dưới đây trong định nghĩa hàm sẽ được thực thi.
for (int i = 0; i <= 7 && RB0 == 0; i ++) {PORTD = get << i; // LED di chuyển Left Sequence __delay_ms (50); } for (int i = 7; i> = 0 && RB0 == 0; i--) {PORTD = get << i; // LED di chuyển Left Sequence __delay_ms (50); }
Bây giờ dòng này có vẻ là kỳ lạ: PORTD = get << i . Tôi sẽ giải thích những gì đang thực sự xảy ra ở đây.
"<<" là một toán tử dịch trái sẽ dịch chuyển tất cả các bit sang vị trí bên trái của nó. Bây giờ khi chúng ta gọi hàm sblink (int get) với tham số '1' là sblink (1), nó sẽ tạo giá trị của 'get' là 1, trong hệ nhị phân là 0b00000001. Do đó dòng này sẽ giống như PORTD = 0b00000001 << i .
Giá trị của "i" sẽ thay đổi từ 0 đến 7 vì chúng ta đã sử dụng 'vòng lặp for ' for (int i = 0; i <= 7 && RB0 == 0; i ++). Giá trị của 'i' từ 0 đến 7 sẽ thay đổi kết quả như sau:
Như bạn có thể thấy, chúng tôi đã BẬT một đèn LED tại một thời điểm (từ trái sang phải) bằng cách giữ TẮT phần còn lại. 'Vòng lặp for' tiếp theo cho (int i = 7; i> = 0 && RB0 == 0; i--) , cũng sẽ làm tương tự nhưng lần này đèn LED sẽ được BẬT từ phải sang trái theo một chuỗi, khi chúng tôi bắt đầu từ 7 và giảm xuống 0. Chúng tôi đã sử dụng độ trễ 200ms để có thể hình dung đèn LED đang BẬT và TẮT.
Bây giờ khi chúng ta truyền giá trị 3 trong hàm sblink (int get) , vì vậy hàm sblink (3) sẽ được thực thi, làm cho giá trị của 'get' là 0b00000011, do đó kết quả trên PORTD sẽ là:
Vì vậy, bây giờ lần này hai đèn LED sẽ được bật bất kỳ lúc nào bằng cách sử dụng sblink (3). Tương tự đối với sblink (7) và sblink (15), ba và bốn đèn LED sẽ BẬT theo thứ tự. Khi điều này hoàn tất, chúng tôi sẽ làm cho tất cả các đèn LED được bật bằng cách sử dụng dòng PORTD = 0xFF . Kiểm tra Video dưới đây để biết đầy đủ các Minh chứng.
Hy vọng bạn đã hiểu mã và do đó đã học được cách sử dụng các hàm, vòng lặp 'for' và 'while' để có được kết quả đầu ra mong muốn. Bây giờ bạn có thể điều chỉnh xung quanh mã để có được chuỗi đèn LED nhấp nháy khác nhau. Hãy tiếp tục biên dịch mã của bạn và kết xuất nó vào MCU của bạn và tận hưởng kết quả đầu ra. Bạn có thể sử dụng phần bình luận nếu bạn gặp khó khăn ở đâu đó. Tôi cũng đã đính kèm các tệp mô phỏng và chương trình ở đây.
Vậy là xong, trong hướng dẫn tiếp theo, chúng ta sẽ học cách sử dụng bộ định thời PIC16F877A thay vì sử dụng các hàm trễ. Bạn có thể duyệt qua tất cả các hướng dẫn về vi điều khiển PIC tại đây.