單片機學習(八)點陣LED的使用


參考資料:https://www.bilibili.com/video/BV1Mb411e7re?p=21

一、點陣LED的理論知識

1. 點陣屏的打開方式

默認情況下我的點陣屏是無法直接使用的,即使用了正確的代碼也無法點亮點陣屏,此時我們需要先將點陣附近的跳線帽拔掉或移動到左邊才能打開點陣屏:

image-20210823105657070

2. LED點陣簡介

  • LED點陣屏由若干個獨立的LED組成,LED以矩陣的形式排列,以燈珠亮滅來顯示文字、圖片、視頻等。LED點陣屏廣泛應用於各種公共場合,如汽車報站器廣告屏以及公告牌
  • LED點陣屏分類
    • 按顏色:單色、雙色、全彩
    • 按像素:8 * 8(開發板上的點陣)、16 * 16等(大規模的LED點陣通常由很多個小點陣拼接而成)

3. 點陣LED的結構和操作方式

示意圖:

image-20210823112235474
  1. LED點陣屏的結構類似於數碼管,只不過是數碼管把每一列的像素以“8”字型排列而已
  2. LED點陣屏與數碼管一樣,有共陰共陽兩種接法,不同的接法對應的電路結構不同
  3. LED點陣屏需要進行逐行或逐列掃描,才能使所有LED同時顯示

例如我們當前希望左上到右下的對角線的LED燈亮,而其他的燈都不亮,可以按照如下方式運行:

  1. 第一行置一,其他行都置零,同時第一列置零,其他列都置一
    即:
置一 置零
第1行 其他行
其他列 第1列
image-20210823112834830
  1. 以上的操作是第一個周期的操作,然后第二個周期則和第一個周期基本相同,只是切換了置一和置零的行和列而已,后面往復進行即可
置一 置零
第2行 其他行
其他列 第2列

通過類似這種的行掃描列掃描操作,我們即可使我們希望的LED同時發光了。

通俗地說就是:先使一行正常顯示,再使下一行正常顯示,只要速度夠快,就能看到LED同時顯示的情景了。

對應到廠商提供的原理圖:

image-20210823114229627

P00~P07用於控制列,而DPa~DPh用於控制行。

4. 74HC595模塊

為什么我們會需要了解這個模塊的相關內容呢,我們先仔細觀察一下原理圖:

image-20210823115259390

可以發現這里的8個輸出對應着LED點陣的8個行輸入,而且這個模塊是只有3個輸入端的,這說明了我們可以通過使用這個模塊,使用3個輸入即可得到LED點陣的8個行輸入了。

此外,這個圖中還包括了OE引腳,可以看到它的上面有着一個橫杠,根據b站老師的說法,這樣的寫法表示該模塊在低電平時有效,所以我們要使用這個模塊之前需要將OEGND相連,這也就是為什么我們需要先把跳線帽移動到左側才能使用LED點陣模塊。

PPT上的簡介

74HC595是串行輸入並行輸出移位寄存器,可用3根線輸入串行數據8根線輸出並行數據,多片級聯后,可輸出16位、24位、32位等,常用於IO口擴展。

串行轉並行的工作原理

image-20210823120251996
  1. 首先先設置SER的值
  2. 使用時鍾發送一個上升信號,即給SERCLK置一,則全部數據向下移動一位,SER中的數據被寫入到最上面
  3. SERCLK置零
  4. 是否夠8位數據?否:轉1;是:轉5
  5. RCLK置一,左邊的數據搬運到右邊,8個信號同時輸出,然后RCLK置零

級聯操作
如果需要更多的位數輸出,我們可以將QH'接到下一個模塊的SER,這樣即可完成不斷擴展。

二、編碼實現

1. C51中的sfr和sbit【補充知識】

  • sfr (special function register) : 特殊功能寄存器聲明
    例:sfr P0=0x80;
    聲明P0口寄存器,物理地址0x80
  • sbit (special bit) : 特殊位聲明
    例: sbit P0_1 = 0x81;sbit P0_1 = P0^1;
    聲明P0寄存器的第1位
  • 可位尋址/不可位尋址:
    在單片機系統中,操作任意寄存器或者某一位的數據時,必須給出其物理地址,又因為一個寄存器里有8位,所以位的數量是寄存器數量的8倍,單片機無法對所有位進行編碼,故每8個寄存器中,只有一個是可以位尋址的。對不可位尋址的寄存器,若要只操作其中一位而不影響其它位時,可用&=|=^=的方法進行位操作

tips:在使用寄存器中的某一位時,我們往往使用類似sbit LED = P2^0;的寫法獲取到某一位,但這種在聲明中使用到的'^'符號並不表示異或,而是進行取位。

2. 編寫74HC595的驅動程序

首先定義出三個需要使用的寄存器位

sbit RCK = P3 ^ 5;
sbit SRCLK = P3 ^ 6;
sbit SER = P3 ^ 4;

其中RCK即為原理圖中的RCLK,但由於和庫中的變量重名了,故改為RCK

然后我們需要編寫74HC595模塊的驅動程序:

void _74HC595_WriteByte(unsigned char Byte) {
    unsigned char i = 0;
    // i為計數變量,重復執行8次
    for (i = 0; i < 8; i++) {
        // 每次取第i位(從左到右),寫入到SER中
        SER = Byte & (0x80 >> i);
        // SRCLK置一,使寄存器進行移位
        SRCLK = 1;
        SRCLK = 0;
    }
    // 將八位輸入到LED的8個行輸入中
    RCK = 1;
    RCK = 0;
}

即輸入一個byte(八位)的數據,可以並行地輸入到點陣LED的8個行輸入中。

3. 編寫控制單列亮燈的程序

代碼如下:

void MatrixLED_ShowColumn(unsigned char column, unsigned char Data) {
    _74HC595_WriteByte(Data);
    // 對某列進行使能,列數為0~7
    P0=~(0x80>>column);
}

我們先將數據寫入到點陣LED的左側輸入中,然后對某列進行使能,具體的操作為使P0寄存器的某位置零,而其他位置一,因此我們可以將0x80先右移column位,然后取反,我們即可得到第column位為0的數據,接着賦值進去即可。

寫個簡單的程序進行測試:

void main(void) {
    SRCLK = 0;
    RCK = 0;
    _74HC595_WriteByte(0xF0);
    while (1) {
        MatrixLED_ShowColumn(0,0xAA);
    }
}

運行結果:

image-20210823175712713

可以看到,第0列的LED燈按照0xAA【1010 1010】進行顯示了!

4. 控制多列同時發光

image-20210823181327798

首先我們先討論一下消影的操作,當我們如果不進行消影時,段選的數據就會先寫入到上一次的選擇的位置中(在這里是指上一列),因此就會發現新列中的數據在上一列也顯示了出來

因此我們需要在每個周期的末尾加上延時位清零的操作:

void MatrixLED_ShowColumn(unsigned char column, unsigned char Data) {
    // 段選
    _74HC595_WriteByte(Data);
    // 位選
    P0 = ~(0x80 >> column);
    // 延時
    deley(50);
    // 位清零
    P0 = 0xFF;
}

這樣我們可以先將希望展示的數據寫入到數組中(8個byte數據,代表每列希望展示的數據),然后通過循環列掃描的方式展示出來:

void main(void) {
    unsigned char i;
    unsigned char Data[] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
    SRCLK = 0;
    RCK = 0;
    while (1) {
        for (i = 0; i < 8; i++) {
            MatrixLED_ShowColumn(i, Data[i]);
        }
    }
}

運行結果:

image-20210823182433693

可以看到在運行結果中第3列燈【從3開始數】沒法點亮,估計是開發板是個次品,第三列的燈都沒法點亮,現在才發現QAQ。。。

顯示心形

先設計一個心形:

image-20210823183537133

然后根據每列的數據,寫入到數組中:

unsigned char Data[] = {0x18, 0x3c, 0x7e, 0x3f, 0x3f, 0x7e, 0x3c, 0x18};

運行結果:

image-20210823183711031

5. 封裝成模塊

// MatrixLED.c
#include "MatrixLED.h"
#include <Atmel/REGX52.H>
#include "Deley.h"

sbit RCK = P3 ^ 5;
sbit SRCLK = P3 ^ 6;
sbit SER = P3 ^ 4;

void MatrixLED_Init() {
    SRCLK = 0;
    RCK = 0;
}

void _74HC595_WriteByte(unsigned char Byte) {
    unsigned char i = 0;
    for (i = 0; i < 8; i++) {
        SER = Byte & (0x80 >> i);
        SRCLK = 1;
        SRCLK = 0;
    }
    RCK = 1;
    RCK = 0;
}

void MatrixLED_ShowColumn(unsigned char column, unsigned char Data) {
    _74HC595_WriteByte(Data);
    // 對某列進行使能,列數為0~7
    MATRIX_LED_PORT = ~(0x80 >> column);
    deley(50);
    MATRIX_LED_PORT = 0xFF;
}

MatrixLED.h文件只需加上三個函數的函數聲明即可。

6. LED點陣動畫

使用字模提取工具

image-20210823185045012

我們需要先將【字節倒序】的勾去掉:

image-20210823190728496

然后點擊【新建圖像】按鈕新建圖像,選擇8和32

image-20210823185134904

我們畫出“Hello!”這樣的文本:

image-20210823190340502

然后我們點擊【取模方法】>【C51格式】即可得到圖像的編碼:

image-20210823190839523

然后我們將這些數據復制到代碼中即可:

unsigned char animation[] = {
    0x7F,0x08,0x08,0x08,0x7F,0x00,0x0E,0x15,0x15,0x15,0x08,0x00,0x7E,0x01,0x02,0x00,
    0x7E,0x01,0x02,0x00,0x0E,0x11,0x11,0x0E,0x00,0x7D,0x00,0x00,0x00,0x00,0x00,0x00
}

為了使字幕經過之后可以有一段空白,我們需要為數組的前后都加上8個0x00

unsigned char animation[] = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x7F, 0x08, 0x08, 0x08, 0x7F, 0x00, 0x0E, 0x15, 0x15, 0x15, 0x08, 0x00, 0x7E, 0x01, 0x02, 0x00,
    0x7E, 0x01, 0x02, 0x00, 0x0E, 0x11, 0x11, 0x0E, 0x00, 0x7D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

代碼編寫

MatrixLED模塊添加一個函數:

void Matrix_ShowAll(unsigned char arr[], unsigned char startIndex) {
    unsigned char i;
    for (i = 0; i < 8; i++) {
        MatrixLED_ShowColumn(i, arr[i + startIndex]);
    }
}

然后主函數:

void main(void) {
    unsigned char offset = 0, count = 0;
    unsigned char animeSize = sizeof(animation) / sizeof(unsigned char);
    MatrixLED_Init();
    while (1) {
        while (1) {
            Matrix_ShowAll(animation, offset);
            count++;
            if (count == 10) {
                count = 0;
                break;
            }
        }
        if (offset == animeSize - 8) {
            offset = 0;
        }
        offset++;
    }
}

這樣我們即可看到從左向右移動的“Hello!”字幕了!

hPy7Ix.gif


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM