Ứng dụng phép dịch bit trong lĩnh vực quảng cáo LED
Trong lập trình C cho 8051, phép toán dịch bit kết hợp với hàm làm trễ sẽ tạo ra những hiệu ứng đèn LED đầy sáng tạo, nó thường áp dụng trong lĩnh vực quảng cáo LED. Trong bài này, tôi sẽ giải thích ý nghĩa các câu lệnh dịch bit, sau đó tôi sẽ minh họa thực tế bằng mạch đèn LED để bạn đọc có thể xem và thấy được ý nghĩa của các câu lệnh này như thế nàoTrong bài viết này, tôi dùng ngôn ngữ C sử dụng với phần mềm Keil C để làm minh họa cho các bạn. Nội dung có tính chất cơ bản nên phù hợp với bạn nào đang nghiên cứu lập trình C cho vi xử lý.
Linh kiện tôi xử dụng là 89S52, nó cùng họ với 8051 nhưng đã được cải tiến khá nhiều, đặc biệt nó có khả năng nạp chương trình thông qua giao tiếp SPI rất tiện lợi.
Ta cần một đoạn code để chạy 1 bóng led đơn từ trái sang phải. Từ đó, chúng ta lại viết cho nó chạy từ phải sang trái
Đoạn code sau đây sẽ thực hiện giúp chúng ta
void led_danh_du(unsigned char delay)
{
unsigned char i=0;
Data = 0x01;
//chay tu phai sang trai
for(i=0;i<8;i++){
P0=Data;
Data <<=1; // data = data<<1
delay_ms(delay);
}
Data = 0x80;
//chay tu trai sang phai
for(i=0;i<8;i++){
P0=Data;
Data >>=1;
delay_ms(delay);
}
}
Đó là chạy từ trái sang phải, vậy còn chạy từ phải sang trái thì sao. Tương tự như trên, ta nạp giá trị 80 tức led thứ 8 và ta lại cho dịch trái. Bóng led cứ chạy qua chạy lại như thế cứ như thể đánh đu vậy phải không nào. Đặt tên nó là hiệu ứng đánh đu vậy.
Điểm mấu chốt của vấn đề nằm ở dòng code
Data <<=1;
Dòng code này đã được viết rút gọn. Để hiểu đầy đủ bạn xem dòng code sau
Data = Data<<1;
Nó có nghĩa là lấy dữ liệu Data ra và dịch dữ liệu Data qua bên trái 1 bit và lưu kết quả đó vào lại biến Data. Khi bạn đưa vào vòng lặp for thì nó sẽ lặp đi lặp lại công việc này liên tục. Từ câu này, cũng tương tự như dịch sang phải nó cũng làm việc như vậy.
Tiếp theo, tôi sẽ giới thiệu 1 hiệu ứng khác là hiệu ứng chạy lan từ phải sang trái
Nhưng trước tiên chúng ta sẽ nói qua 1 phép toán trong kỹ thuật số. Đó là phép HOẶC (OR).
Ta có 2 bit a và b và ta cần thực hiện HOẶC nó lại với nhau, theo bảng sự thật dưới đây:
a b a OR b
0 0 0
0 1 1
1 0 1
1 1 1
Dựa vào bảng trên ta rút ra quy tắc: Tổng hai bit bằng 0 khi và chỉ khi cả hai bit bằng 0 ngoài ra tổng nhận giá trị 1;
Trong Keil C phép OR được biểu diễn bằng kí hiệu |
Như vậy kết hợp với phép dịch bit từ trái sang phải hoặc từ phải sang phải, mỗi khi bit được dịch trái hoặc phải thì bit trước nó sẽ được hoặc với 1 như vậy nó sẽ tạo ra hiệu ứng lan tỏa từ phải sang trái.
void lan_toa(unsigned char delay) //sang lan dan-->>tat lan dan //right to left
{
unsigned char i=0;
Data = 0x01;
for(i=0;i<8;i++){
Data= (Data<<1)|0x01;
P0=Data;
delay_ms(delay);
}
}
Trong đoạn code này, nó sẽ chạy sáng lan từ phải sang trái.
Để nó tắt từ phải sang trái, chúng sẽ sử dụng phép đảo các giá trị.
Lúc này tất cả led đều sáng, chỉ led đầu tiên là tắt, chúng ta chỉ việc dịch sang trái và HOẶC với giá trị 0
Cũng tương tự cho việc lan từ trái sang phải, các bạn có thể tự viết cho nó chạy sáng lan và tắt lan dần từ trái sang phải.
Như vậy toàn bộ mã nguồn thể hiện như sau
#include "AT89X52.H"
unsigned char Data, dl=150;
void delay_ms(unsigned int ms)
{
unsigned int i,j;
for(i=0;i<ms;i++)
for(j=0;j<121;j++);
}
void led_danh_du(unsigned char delay)
{
unsigned char i=0;
Data = 0x01;
for(i=0;i<8;i++){
P0=Data;
Data <<=1;
delay_ms(delay);
}
Data = 0x80;
for(i=0;i<8;i++){
P0=Data;
Data >>=1;
delay_ms(delay);
}
}
void lan_toa(unsigned char delay)
{
unsigned char i=0;
Data = 0x01;
for(i=0;i<8;i++){
Data= (Data<<1)|0x01;
P0=Data;
delay_ms(delay);
}
}
void main(){
while(1){
P0= P1 = P2 = 0x00;
led_danh_du(dl);
lan_toa(dl);
}
}
Bắt đầu đoạn code chúng ta thấy dòng code đầu tiên
#include <REG52.H>
Dòng này sẽ lấy thư viện đặc tả của VXL 89S5 để chúng ta sử dụng.
Hàm làm trễ delay_ms () với 2 dòng lặp for chạy lồng ghép vào nhau, cho đến khi nào đạt đến giá trị chúng ta đã khai báo trong biến dl. Lưu ý, đoạn code này được sử dụng với thạch anh 12M, nếu bạn sử dụng thạch anh khác thì kết quả nhận được cũng khác
Linh kiện tôi xử dụng là 89S52, nó cùng họ với 8051 nhưng đã được cải tiến khá nhiều, đặc biệt nó có khả năng nạp chương trình thông qua giao tiếp SPI rất tiện lợi.
Ta cần một đoạn code để chạy 1 bóng led đơn từ trái sang phải. Từ đó, chúng ta lại viết cho nó chạy từ phải sang trái
Đoạn code sau đây sẽ thực hiện giúp chúng ta
void led_danh_du(unsigned char delay)
{
unsigned char i=0;
Data = 0x01;
//chay tu phai sang trai
for(i=0;i<8;i++){
P0=Data;
Data <<=1; // data = data<<1
delay_ms(delay);
}
Data = 0x80;
//chay tu trai sang phai
for(i=0;i<8;i++){
P0=Data;
Data >>=1;
delay_ms(delay);
}
}
Đó là chạy từ trái sang phải, vậy còn chạy từ phải sang trái thì sao. Tương tự như trên, ta nạp giá trị 80 tức led thứ 8 và ta lại cho dịch trái. Bóng led cứ chạy qua chạy lại như thế cứ như thể đánh đu vậy phải không nào. Đặt tên nó là hiệu ứng đánh đu vậy.
Điểm mấu chốt của vấn đề nằm ở dòng code
Data <<=1;
Dòng code này đã được viết rút gọn. Để hiểu đầy đủ bạn xem dòng code sau
Data = Data<<1;
Nó có nghĩa là lấy dữ liệu Data ra và dịch dữ liệu Data qua bên trái 1 bit và lưu kết quả đó vào lại biến Data. Khi bạn đưa vào vòng lặp for thì nó sẽ lặp đi lặp lại công việc này liên tục. Từ câu này, cũng tương tự như dịch sang phải nó cũng làm việc như vậy.
Tiếp theo, tôi sẽ giới thiệu 1 hiệu ứng khác là hiệu ứng chạy lan từ phải sang trái
Nhưng trước tiên chúng ta sẽ nói qua 1 phép toán trong kỹ thuật số. Đó là phép HOẶC (OR).
Ta có 2 bit a và b và ta cần thực hiện HOẶC nó lại với nhau, theo bảng sự thật dưới đây:
a b a OR b
0 0 0
0 1 1
1 0 1
1 1 1
Dựa vào bảng trên ta rút ra quy tắc: Tổng hai bit bằng 0 khi và chỉ khi cả hai bit bằng 0 ngoài ra tổng nhận giá trị 1;
Trong Keil C phép OR được biểu diễn bằng kí hiệu |
Như vậy kết hợp với phép dịch bit từ trái sang phải hoặc từ phải sang phải, mỗi khi bit được dịch trái hoặc phải thì bit trước nó sẽ được hoặc với 1 như vậy nó sẽ tạo ra hiệu ứng lan tỏa từ phải sang trái.
void lan_toa(unsigned char delay) //sang lan dan-->>tat lan dan //right to left
{
unsigned char i=0;
Data = 0x01;
for(i=0;i<8;i++){
Data= (Data<<1)|0x01;
P0=Data;
delay_ms(delay);
}
}
Trong đoạn code này, nó sẽ chạy sáng lan từ phải sang trái.
Để nó tắt từ phải sang trái, chúng sẽ sử dụng phép đảo các giá trị.
Lúc này tất cả led đều sáng, chỉ led đầu tiên là tắt, chúng ta chỉ việc dịch sang trái và HOẶC với giá trị 0
Cũng tương tự cho việc lan từ trái sang phải, các bạn có thể tự viết cho nó chạy sáng lan và tắt lan dần từ trái sang phải.
Như vậy toàn bộ mã nguồn thể hiện như sau
#include "AT89X52.H"
unsigned char Data, dl=150;
void delay_ms(unsigned int ms)
{
unsigned int i,j;
for(i=0;i<ms;i++)
for(j=0;j<121;j++);
}
void led_danh_du(unsigned char delay)
{
unsigned char i=0;
Data = 0x01;
for(i=0;i<8;i++){
P0=Data;
Data <<=1;
delay_ms(delay);
}
Data = 0x80;
for(i=0;i<8;i++){
P0=Data;
Data >>=1;
delay_ms(delay);
}
}
void lan_toa(unsigned char delay)
{
unsigned char i=0;
Data = 0x01;
for(i=0;i<8;i++){
Data= (Data<<1)|0x01;
P0=Data;
delay_ms(delay);
}
}
void main(){
while(1){
P0= P1 = P2 = 0x00;
led_danh_du(dl);
lan_toa(dl);
}
}
Bắt đầu đoạn code chúng ta thấy dòng code đầu tiên
#include <REG52.H>
Dòng này sẽ lấy thư viện đặc tả của VXL 89S5 để chúng ta sử dụng.
Hàm làm trễ delay_ms () với 2 dòng lặp for chạy lồng ghép vào nhau, cho đến khi nào đạt đến giá trị chúng ta đã khai báo trong biến dl. Lưu ý, đoạn code này được sử dụng với thạch anh 12M, nếu bạn sử dụng thạch anh khác thì kết quả nhận được cũng khác
Nhận xét
Đăng nhận xét