普冉PY32系列(十三) SPI驅動WS2812全彩LED

来源:https://www.cnblogs.com/milton/archive/2023/12/10/17892606.html
-Advertisement-
Play Games

WS2812 是一種集成了控制器的全彩LED, 常見單體尺寸為50mm * 50mm, 4個PIN, 分別是 VCC, GND, DIN, DOUT, 工作電壓3.7V-5.3V, 電流16mA. 市面上出售的大都是製作成條狀, 環狀或矩陣的成品. 供電電壓有5V和12V兩種, 前者因為電壓低, 如... ...


目錄

WS2812/WS2812B

WS2812 是一種集成了控制器的全彩LED, 常見單體尺寸為50mm * 50mm, 4個PIN, 分別是 VCC, GND, DIN, DOUT, 工作電壓3.7V-5.3V, 電流16mA. 市面上出售的大都是製作成帶狀, 環狀或矩陣的成品. 供電電壓有5V和12V兩種, 前者因為電壓低, 如果長度較長, 每隔兩三百顆需要外接電源補電.

WS2812的特點就是全彩並且是單線串列介面, 只需要一個IO就可以對彩燈實現全部控制.

介面通信格式

WS2812/WS2812B LED 使用 24 bit 數據調節 RGB 色彩, 每個 bit 都是通過(一個高電平 + 一個低電平)表示的.

根據手冊

  • 0 表示為一個短的(0.35 µs)高電平加一個長的(0.90 µs)低電平
  • 1 表示為一個長的(0.90 µs)高電平加一個短的(0.35 µs)低電平
  • 單個 bit 信號周期, 高低電平時長合計為 1.25 µs
  • 發送超過 24 bit 信號後, 之前輸入的信號會依次傳遞給串列的下一個 WS2812 LED
  • 控制器發送數據前需要保持低電平超過 50 µs(又稱為 RESET), 用於通知 WS2812 開始接收數據.

根據上面的信息, 對單顆LED發送數據, 需要的時間為
\(24 × 1.25 µs + 50 µs = 80 µs\)
對於8顆LED, 需要的時間為
\(8 × 24 × 1.25 µs + 50 µs = 290 µs\)

實際的通信時間間隔要求

當傳輸信號時, 高低電平時間間隔如果不符合手冊要求, 差距較大時LED會不工作(不亮), 在間隔接近但是不完全滿足時, LED會出現顯示錯亂, 色彩亂跳等.

Tim “cpldcpu” 做過一系列實驗 https://cpldcpu.wordpress.com/2014/01/14/light_ws2812-library-v2-0-part-i-understanding-the-ws2812/ 驗證過時間間隔的邊界, 發現這些要求實際上相當寬鬆:

  • 觸發RESET只需要 9 µs (比手冊要求的 50 µs 小很多)
  • 一個 bit 的周期至少需要 1.25 µs, 但是不能超過 9 µs, 因為這樣容易觸發RESET
  • 0 的高電平時間, 手冊要求是 0.35 µs, 實際上可以短至 62.5 ns , 但是不能長於 0.50 µs
  • 1 的高電平時間, 手冊要求是 0.65 µs, 實際上長度可以幾乎跨越整個 bit 周期, 但是不能短於 0.625 µs

SPI驅動時的bit數選擇

對於輸出固定長度的電平組合, SPI是最簡單的方式. 可以使用 SPI, 通過控制其中的數據值與 WS2812 通信, 而時間間隔控制則需要通過控制 SPI 的時鐘以及每次發送的 bit 數量實現, 根據Controlling WS2812(B) leds using STM32 HAL SPI 的計算, 通過對比多種 bit 數的時間要求, 發現使用 bit 數越多, 相容性越好, MCU越容易實現. 因此可以使用預設的 8bit SPI 通信.

對於 PY32F002A/PY32F003/PY32F030, 因為最高頻率是48MHz, 所以當SPI分頻為8, 16時, 分別對應 6MHz, 3MHz, 在工作範圍內; 對於 PY32F040/PY32F071/PY32F072, 最高頻率是72MHz, 當SPI分頻為8, 16, 32時, 分別對應 9MHz, 4.5MHz, 2.25MHz, 都在工作範圍內.

SPI 驅動 WS2812

對應不同的LED數量, 需要調整下麵代碼中WS2812_NUM_LEDS的值, 這裡使用的是一個8x8的點陣, 因此設為64. 註意這個ws2812_buffer實際上非常占記憶體, 對於數量超過64的LED燈帶(矩陣), 需要考慮其它的實現.

頭文件 ws2812_spi.h

#include "main.h"

#define WS2812_NUM_LEDS 64
#define WS2812_SPI_HANDLE Spi1Handle

#define WS2812_RESET_PULSE 60
#define WS2812_BUFFER_SIZE (WS2812_NUM_LEDS * 24 + WS2812_RESET_PULSE)

extern SPI_HandleTypeDef WS2812_SPI_HANDLE;
extern uint8_t ws2812_buffer[];

void ws2812_init(void);
void ws2812_send_spi(void);
void ws2812_pixel(uint16_t led_no, uint8_t r, uint8_t g, uint8_t b);
void ws2812_pixel_all(uint8_t r, uint8_t g, uint8_t b);

函數實現 ws2812_spi.c

#include <string.h>
#include "ws2812_spi.h"

#define WS2812_FILL_BUFFER(COLOR) \
    for( uint8_t mask = 0x80; mask; mask >>= 1 ) { \
        if( COLOR & mask ) { *ptr++ = 0xfc; } \
        else { *ptr++ = 0x80; }}

uint8_t ws2812_buffer[WS2812_BUFFER_SIZE];

void ws2812_init(void) {
    memset(ws2812_buffer, 0, WS2812_BUFFER_SIZE);
    ws2812_send_spi();
}

void ws2812_send_spi(void) {
    HAL_SPI_Transmit(&WS2812_SPI_HANDLE, ws2812_buffer, WS2812_BUFFER_SIZE, HAL_MAX_DELAY);
}

void ws2812_pixel(uint16_t led_no, uint8_t r, uint8_t g, uint8_t b) {
    uint8_t * ptr = &ws2812_buffer[24 * led_no];
    WS2812_FILL_BUFFER(g);
    WS2812_FILL_BUFFER(r);
    WS2812_FILL_BUFFER(b);
}

void ws2812_pixel_all(uint8_t r, uint8_t g, uint8_t b) {
    uint8_t * ptr = ws2812_buffer;
    for( uint16_t i = 0; i < WS2812_NUM_LEDS; ++i) {
        WS2812_FILL_BUFFER(g);
        WS2812_FILL_BUFFER(r);
        WS2812_FILL_BUFFER(b);
    }
}

使用 PY32F0 驅動 WS2812

具體的SPI初始化可以參考文章結尾的示例代碼, 根據各自環境的工作頻率不同, 需要控制SPI的時鐘周期在工作範圍之內

對於開啟PLL運行在48MHz的PY32F002A/003/030, 使用8分頻

static void APP_SPIConfig(void)
{
  LL_SPI_InitTypeDef SPI_InitStruct = {0};
  LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

  //...
  /* The frequency after prescaler should be below 8.25MHz */
  SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV8;
  //...
}

對於 PY32F040/071/072, 工作在HSI 24MHz, 使用4分頻

static void APP_SPI_Config(void)
{
  Spi1Handle.Instance               = SPI1;
  /* The frequency after prescale should be below 8.25MHz */
  Spi1Handle.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
  //...
}

示例代碼中, 通過迴圈依次修改像素點的RGB值演示LED全彩效果

  ws2812_pixel_all(r, g, b);
  ws2812_send_spi();
  while (1)
  {
    i = (i + 1) % WS2812_NUM_LEDS;
    ws2812_pixel(i, r++, g++, b++);
    ws2812_send_spi();
    LL_mDelay(20);
  }

完整的示例代碼通過以下鏈接查看

註意事項

要註意自己使用的 WS2812 的供電電壓是 5V 還是 12V, 不要和 PY32F0 的供電混在一起. WS2812 數量多了之後電流是很大的, 對 5V 8x8 的矩陣實測工作電流在 500mA 以上, 如果是 16x16 的矩陣, 電流會超過 2A. 這麼大的電流最好單獨供電.

參考


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在此之前,先來回顧元編程當中的一個重要概念。 template<typename _Tp, _Tp __v> struct integral_constant { static constexpr _Tp value = __v; typedef _Tp value_type; typedef in ...
  • Qt是一種C++編程框架,用於構建圖形用戶界面(GUI)應用程式和嵌入式系統。Qt由Qt公司(前身為Nokia)開發,提供了一套跨平臺的工具和類庫,使開發者能夠輕鬆地創建高效、美觀、可擴展的應用程式。其被廣泛用於開發桌面應用程式、嵌入式系統、移動應用程式等。無論是初學者還是經驗豐富的開發者,Qt都為... ...
  • 這是scikit-learn數據載入系列的最後一篇,本篇介紹如何載入外部的數據集。 外部數據集不像之前介紹的幾種類型的數據集那樣,針對每種數據提供對應的介面,每個介面載入的數據都是固定的。而外部數據集載入之後,數據的欄位和類型是不確定的。 簡單來說,我們在實際的數據分析工作中,用到的是外部數據集載入 ...
  • 因為畢設是CPU的低功耗設計,所以開始看cpu,打算還是先從這個tinyriscv學起,昨天把環境下好了,第一步是用git去clone代碼,這個首先要下載git,然後在目標文件夾滑鼠右鍵,選擇“open git bush here”,再輸入項目的url,就可以了。方法不難。b站有詳細教程 接下來是安 ...
  • C++預設有效位數 C++ 預設有效位數為 6 位,指數位和小數位共用。超過有效位數時,只輸出前 6 位,且第六位四捨五入運算。 cout << 12345.54555 << "\n"; // 輸出 12345.5 cout << 12345.55555 << "\n"; // 輸出 12345.6 ...
  • 重覆的操作令手工測試苦不堪言,於是自動化測試出現了!作為web應用里最出名的自動化測試工具,selenium讓web應用的測試輕鬆了很多。今天我們就來簡單的介紹一下一些簡單的selenium瀏覽器操作。接下來我們就來看看python怎麼操作瀏覽器的吧! 1、打開指定的網頁地址 我們使用seleniu ...
  • IHostedService 介面在.NET Core中的主要用途是定義應用程式生命周期內運行的後臺服務。這些服務可以執行初始化、長時間運行的任務、定期運行的任務等。通過實例,我們可以演示如何使用 IHostedService 來實現一個簡單的網路檢測服務,並記錄日誌。 首先,我們需要創建一個實現  ...
  • 痞子衡嵌入式半月刊: 第 87 期 這裡分享嵌入式領域有用有趣的項目/工具以及一些熱點新聞,農曆年分二十四節氣,希望在每個交節之日準時發佈一期。 本期刊是開源項目(GitHub: JayHeng/pzh-mcu-bi-weekly),歡迎提交 issue,投稿或推薦你知道的嵌入式那些事兒。 上期回顧 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...