WS2812B————動/靜態顯示

一,系統架構

在這里插入圖片描述

二,芯片介紹

1.管腳說明

在這里插入圖片描述

2.數據傳輸時間

在這里插入圖片描述

3.時序波形

在這里插入圖片描述

4.數據傳輸方法

在這里插入圖片描述

5.常用電路連接

在這里插入圖片描述

三,代碼展示及說明

  1. 驅動模塊
    在驅動模塊首先選擇使用狀態機,其中包括,空閑狀態,復位清空狀態,和讀數據狀態,其中空閑狀態是向fifo中寫入數據,復位清空狀態是清空ws2812b中的數據,讀數據狀態是講fifo中存的數據依次讀到ws2812b中,以這樣的流程來達到對ws2812b的控制,以下是我的驅動代碼:
/**************************************功能介紹***********************************
Date	: 
Author	: WZY.
Version	: 
Description: 這是項目的邏輯狀態機模塊
*********************************************************************************///---------<模塊及端口聲名>------------------------------------------------------
module state( input 	wire				clk		,input 	wire				rst_n	,input   wire    [23:0]      data_in ,input   wire                fifo_wr_vld,output  reg                 ws2812b_io ,output  wire                ready
);								 
//---------<參數定義>--------------------------------------------------------- //狀態機參數定義parameter IDLE = 3'b001,//空閑狀態RST  = 3'b010,//復位狀態DATA = 3'b100;//數據傳輸狀態    //---------<內部信號定義>-----------------------------------------------------reg 	[2:0]	cstate      ;//現態
reg	    [2:0]	nstate      ;//次態
wire            idle2rst    ;
wire            rst2data    ;
wire            data2idle   ;//fifoIP核參數定義
wire    [23:0]  fifo_wr_data;
wire    [23:0]  fifo_rd_data;
wire            empty       ;
wire            full        ;
wire            fifo_rd_req ;
wire            fifo_wr_req ;//復位參數定義
reg			[14:0]	cnt_rst	   	;
wire				add_cnt_rst	;
wire				end_cnt_rst	;//數據傳輸參數定義
reg			[5:0]	cnt_cyc	   	;
wire				add_cnt_cyc	;
wire				end_cnt_cyc	;reg			[4:0]	cnt_bit	   	;
wire				add_cnt_bit	;
wire				end_cnt_bit	;reg			[5:0]	cnt_num	   	;
wire				add_cnt_num	;
wire				end_cnt_num	;//****************************************************************
//                  狀態機
//****************************************************************//第一段:時序邏輯描述狀態轉移
always @(posedge clk or negedge rst_n)begin if(!rst_n)begincstate <= IDLE;end else begin cstate <= nstate;end 
end//第二段:組合邏輯描述狀態轉移規律和狀態轉移條件
always @(*) begincase(cstate)IDLE  : beginif (idle2rst) beginnstate = RST;endelse beginnstate = cstate;endendRST   : beginif (rst2data) beginnstate = DATA;endelse beginnstate = cstate;endendDATA : beginif (data2idle) beginnstate = IDLE;endelse beginnstate = cstate;endenddefault : nstate = IDLE;endcase
end
assign idle2rst  = cstate == IDLE && fifo_wr_vld;//當檢測到讀使能時由空閑狀態轉換到復位狀態
assign rst2data  = cstate == RST  && end_cnt_rst;//當復位完成后轉到數據輸入狀態
assign data2idle = cstate == DATA && end_cnt_num;//當數據輸入完成后返回空閑狀態           
//第三段:描述輸出,時序邏輯或組合邏輯皆可//****************************************************************
//                      IP核FIFO讀取
//****************************************************************           
fifo_test	fifo_test_inst (.aclr ( ~rst_n ),.clock ( clk ),.data ( fifo_wr_data ),.rdreq ( fifo_rd_req ),.wrreq ( fifo_wr_req),.empty ( empty ),.full ( full ),.q ( fifo_rd_data ),.usedw (  ));       assign fifo_wr_data = {data_in[15:8],data_in[23:16],data_in[7:0]} ;//RGB->GRB
assign fifo_wr_req = fifo_wr_vld&&~full;//當檢測到寫使能并且不為滿時拉高
assign fifo_rd_req = end_cnt_bit&& ~empty;//每次讀取計時到一個數據后并且不為空時讀出一個數據//****************************************************************
//                  復位計時
//****************************************************************    always @(posedge clk or negedge rst_n)begin if(!rst_n)begincnt_rst <= 15'd0;end else if(add_cnt_rst)begin if(end_cnt_rst)begin cnt_rst <= 15'd0;endelse begin cnt_rst <= cnt_rst + 1'b1;end end
end assign add_cnt_rst = cstate == RST;
assign end_cnt_rst = add_cnt_rst && cnt_rst == 400_000/20 - 1;//****************************************************************
//                      數據傳輸計時
//****************************************************************always @(posedge clk or negedge rst_n)begin if(!rst_n)begincnt_cyc <= 6'd0;end else if(add_cnt_cyc)begin if(end_cnt_cyc)begin cnt_cyc <= 6'd0;endelse begin cnt_cyc <= cnt_cyc + 1'b1;end end
end assign add_cnt_cyc = cstate == DATA;
assign end_cnt_cyc = add_cnt_cyc && cnt_cyc == 1200/20 - 1;always @(posedge clk or negedge rst_n)begin if(!rst_n)begincnt_bit <= 5'd0;end else if(add_cnt_bit)begin if(end_cnt_bit)begin cnt_bit <= 5'd0;endelse begin cnt_bit <= cnt_bit + 1'b1;end end
end assign add_cnt_bit = end_cnt_cyc;
assign end_cnt_bit = add_cnt_bit && cnt_bit == 24-1;always @(posedge clk or negedge rst_n)begin if(!rst_n)begincnt_num <= 6'd0;end else if(add_cnt_num)begin if(end_cnt_num)begin cnt_num <= 6'd0;endelse begin cnt_num <= cnt_num + 1'b1;end end
end assign add_cnt_num = end_cnt_bit;
assign end_cnt_num = add_cnt_num && cnt_num == 64-1;
//****************************************************************
//                      用戶接口
//****************************************************************always @(posedge clk or negedge rst_n) begincase (cstate)IDLE : ws2812b_io = 0;RST  : ws2812b_io = 0;DATA : beginif (fifo_rd_data[23-cnt_bit] == 1) beginws2812b_io = (cnt_cyc <30)?1:0;endelse  beginws2812b_io = (cnt_cyc<15)?1:0;endenddefault: ws2812b_io = 0;endcase
end//****************************************************************
//                      ready控制
//****************************************************************
assign ready = cstate == IDLE;
endmodule
  1. 數據傳輸
    接下來是數據選擇傳輸模塊,這個模塊同樣使用到了ip核以及狀態機,通過三個狀態,空閑狀態,讀數據狀態,以及延遲狀態,其中空閑狀態下,等待驅動模塊準備完成跳轉到讀數據狀態,在讀數據狀態下根據三個計數器即橫坐標,縱坐標還有偏移坐標來作為ROM的地址,依次向外讀出數據,同時驅動模塊向fifo中寫入數據,當讀取完64個數據后跳轉到等待狀態,延遲500ms后再次回到IDLE狀態并且偏移坐標+1,以此循環就可以達到動態顯示,下面是代碼展示:
/**************************************************************
@File    :   ws2812_control2.v
@Time    :   2023/08/14 10:04:56
@Author  :   WangHaodong 
@EditTool:   VS Code 
@Font    :   UTF-8 
@Function:   顯示一張圖片
**************************************************************/
module ws2812_control(input               clk             ,input               rst_n           ,output      [23:0]  pix_data        ,output              pix_data_vld    ,input               ready                   //可以接收圖像數據了
);parameter   IDLE    =   0,DATA     =   1,DELAY     =   2;reg     [2:0]   state   ;reg	[5:0] cnt_x;wire		  add_x_cnt,end_x_cnt;	reg	[4:0] cnt_y;wire		  add_y_cnt,end_y_cnt;	reg			[24:0]	cnt_delay	   	;wire				add_cnt_delay	;wire				end_cnt_delay	;reg			[5:0]	cnt_offset	   	;wire				add_cnt_offset	;wire				end_cnt_offset	;localparam	RED     =   24'hFF0000,   //紅色ORANGE  =   24'hFF8000,   //橙色YELLOW  =   24'hFFFF00,   //黃色GREEN   =   24'h00FF00,   //綠色CYAN    =   24'h00FFFF,   //青色BLUE    =   24'h0000FF,   //藍色PURPPLE =   24'h8000FF,   //紫色BLACK   =   24'h000000,   //黑色WHITE   =   24'hFFFFFF,   //白色GRAY    =   24'hC0C0C0;	  //灰色
parameter   MAX_500S =  24_999_999;wire        rom_rd_req      ;wire        rom_rd_data_vld ;reg         rom_rd_req_r1   ;reg         rom_rd_req_r2   ;/**************************************************************狀態機
**************************************************************/always@(posedge clk or negedge rst_n)if(!rst_n)state <= IDLE;else case(state)IDLE		:	if(ready)state <=DATA;DATA		:	if(end_y_cnt)state <=DELAY;DELAY       :   if (end_cnt_delay) state <= IDLE;default :	state <= IDLE;endcase
//****************************************************************
//                  延時計數器
//****************************************************************always @(posedge clk or negedge rst_n)begin if(!rst_n)begincnt_delay <= 'd0;end else if(add_cnt_delay)begin if(end_cnt_delay)begin cnt_delay <= 'd0;endelse begin cnt_delay <= cnt_delay + 1'b1;end endelse begincnt_delay <= 0;end
end assign add_cnt_delay = state == DELAY;
assign end_cnt_delay = add_cnt_delay && cnt_delay == MAX_500S;/**************************************************************圖像數據個數計數器
**************************************************************/       
//橫坐標always@(posedge clk or negedge rst_n)	if(!rst_n)								cnt_x <= 'd0;						else    if(add_x_cnt) begin				if(end_x_cnt)						cnt_x <= 'd0;  				else									cnt_x <= cnt_x + 1'b1;		end											assign add_x_cnt = state == DATA;assign end_x_cnt = add_x_cnt && cnt_x == 8 - 1;//縱坐標always@(posedge clk or negedge rst_n)	if(!rst_n)								cnt_y <= 'd0;						else    if(add_y_cnt) begin				if(end_y_cnt)						cnt_y <= 'd0;  				else									cnt_y <= cnt_y + 1'b1;		end											assign add_y_cnt = end_x_cnt;assign end_y_cnt = add_y_cnt && cnt_y == 8 - 1;//偏移量  always @(posedge clk or negedge rst_n)begin if(!rst_n)begincnt_offset <= 'd0;end else if(add_cnt_offset)begin if(end_cnt_offset)begin cnt_offset <= 'd0;endelse begin cnt_offset <= cnt_offset + 1'b1;end endend assign add_cnt_offset = end_cnt_delay;assign end_cnt_offset = add_cnt_offset && cnt_offset == 31;wire[4:0]  num_x;assign num_x = (cnt_x+cnt_offset)%32;//避免超出32的坐標限制//存放了一張圖片rom	rom_inst (.aclr       ( ~rst_n ),.address    (  cnt_y*32+num_x ),.clock      ( clk ),.rden       (rom_rd_req),.q          (pix_data));assign rom_rd_req = state == DATA;always@(posedge clk or negedge rst_n)if(!rst_n) beginrom_rd_req_r1 <= 0;rom_rd_req_r2 <= 0;endelse beginrom_rd_req_r1 <= rom_rd_req;rom_rd_req_r2 <= rom_rd_req_r1;endassign rom_rd_data_vld = rom_rd_req_r2;assign pix_data_vld = rom_rd_data_vld;//打兩拍使得讀出數據和fifo中寫入數據同步endmodule

3.仿真演示

仿真代碼:

`timescale 1ns/1nsmodule state_tb();//激勵信號定義 reg				 clk  	;reg				 rst_n	;
//輸出信號定義	 wire                    ws2812b_io ;//時鐘周期參數定義	parameter		CYCLE = 20; defparam        top_inst.ws2812_control_inst.MAX_500S = 10*CYCLE;  //模塊例化top top_inst(.clk            (clk),.rst_n          (rst_n),.ws2812b_io     (ws2812b_io)
);	//產生時鐘initial 		 clk = 1'b1;always #(CYCLE/2)  clk = ~ clk;//產生激勵initial  begin rst_n = 1'b1;#(CYCLE*2);rst_n = 1'b0;#(CYCLE*20);rst_n = 1'b1;#(CYCLE*1000000);$stop;endendmodule 

仿真結果展示:
在這里插入圖片描述

4.結果演示

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/36528.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/36528.shtml
英文地址,請注明出處:http://en.pswp.cn/news/36528.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

怎么把圖片表格轉換成word表格?幾個步驟達成

在處理文檔時&#xff0c;圖片表格的轉換是一個常見的需求。而手動輸入表格是非常耗時的&#xff0c;因此&#xff0c;使用文本識別軟件來自動轉換圖片表格可以大大提高工作效率。在本文中&#xff0c;我們將介紹如何使用OCR文字識別技術來將圖片表格轉換為Word表格。 OCR文字識…

Vue3+Element plus+pageHelper實現分頁

安裝element plus npm install element-plus --save引入 修改main.js&#xff1a; import { createApp } from vue import App from ./App.vue import ElementPlus from element-plus import element-plus/dist/index.cssconst app createApp(App) app.use(ElementPlus) ap…

15.3 【Linux】循環執行的例行性工作調度

相對于 at 是僅執行一次的工作&#xff0c;循環執行的例行性工作調度則是由 cron &#xff08;crond&#xff09; 這個系統服務來控制的。剛剛談過 Linux 系統上面原本就有非常多的例行性工作&#xff0c;因此這個系統服務是默認啟動的。另外&#xff0c; 由于使用者自己也可以…

棧和隊列--受限制的線性表

目錄 和隊列的定義和特點 1.1棧的定義和特點、 1.2隊列的定義和特點 1.3棧和隊列的應用 2.棧的表示和操作的實現 2.1棧的類型定義 2.2順序棧的表示和實現 2.2.1初始化 2.2.2入棧 2.2.3出棧 2.2.4取棧頂元素 2.3鏈棧的表示和實現 2.2.1初始化 2.2.2入棧 2.2.3出棧…

Java-運算符和控制語句(下)(基于c語言的補充)

輸出到控制臺 System.out.println(msg); // 輸出一個字符串, 帶換行 System.out.print(msg); // 輸出一個字符串, 不帶換行 System.out.printf(format, msg); // 格式化輸出 從鍵盤輸入 使用 Scanner 讀取字符串/整數/浮點數 首先需要導入util包 自動導入util包 這里把回車看…

如何選擇最佳的文件傳輸協議?(FTP、TFTP、Raysync)

在數字化時代&#xff0c;通過互聯網傳輸文件是一項常見的任務。因此&#xff0c;選擇適合您企業需求的文件傳輸協議非常重要。 文件傳輸協議是發送方和接收方之間的一套規則和信息。它的作用就像網絡兩端都能理解的一種語言&#xff0c;使得數據可以正確輸出并帶有正確的文件…

【高頻面試題】JVM篇

文章目錄 一、JVM組成1.什么是程序計數器2.什么是Java堆&#xff1f;3.能不能介紹一下方法區(元空間&#xff09;4.你聽過直接內存嗎5.什么是虛擬機棧6.垃圾回收是否涉及棧內存&#xff1f;7.棧內存分配越大越好嗎&#xff1f;8.方法內的局部變量是否線程安全&#xff1f;9.什么…

NIO 非阻塞式IO

NIO Java NIO 基本介紹 Java NIO 全稱 Java non-blocking IO&#xff0c;是指 JDK 提供的新 API。從 JDK1.4 開始&#xff0c;Java 提供了一系列改進的輸入/輸出的新特性&#xff0c;被統稱為 NIO&#xff08;即 NewIO&#xff09;&#xff0c;是同步非阻塞的。NIO 相關類都被…

01-Spark環境部署

1 Spark的部署方式介紹 ? Spark部署模式分為Local模式&#xff08;本地模式&#xff09;和集群模式&#xff08;集群模式又分為Standalone模式、Yarn模式和Mesos模式&#xff09; 1.1 Local模式 Local模式常用于本地開發程序與測試&#xff0c;如在idea中 1.2 Standalone模…

PAT 1039 Course List for Student

個人學習記錄&#xff0c;代碼難免不盡人意。 Zhejiang University has 40000 students and provides 2500 courses. Now given the student name lists of all the courses, you are supposed to output the registered course list for each student who comes for a query. …

netty學習分享 二

操作系統IO模型與實現原理 阻塞IO 模型 應用程序調用一個IO函數&#xff0c;導致應用程序阻塞&#xff0c;等待數據準備好。如果數據沒有準備好&#xff0c;一直等待….數據準備好了&#xff0c;從內核拷貝到用戶空間,IO函數返回成功指示。 當調用recv()函數時&#xff0c;系…

釉面陶瓷器皿SOR/2016-175標準上架亞馬遜加拿大站

親愛的釉面陶瓷器皿和玻璃器皿制造商和賣家&#xff0c;亞馬遜加拿大站將執行SOR/2016-175法規。這是一份新的法規&#xff0c;規定了含有鉛和鎘的釉面陶瓷器和玻璃器皿需要滿足的要求。讓我們一起來看一看&#xff0c;為什么要實行SOR/2016-175法規&#xff1f;這是一個保護消…

yolo源碼注釋3——模型配置文件

代碼基于yolov5 v6.0 目錄&#xff1a; yolo源碼注釋1——文件結構yolo源碼注釋2——數據集配置文件yolo源碼注釋3——模型配置文件yolo源碼注釋4——yolo-py 模型配置文件一般放在 models 文件夾下的 XXX.yaml 文件中&#xff0c;以 yolov5s.yaml 為例&#xff1a; # YOLOv…

使用SpringAop切面編程通過Spel表達式實現Controller權限控制

目錄 參考一、概念SpEL表達式 二、開發引入包定義注解定義切面定義用戶上下文 三、測試新建Service在方法上注解新建Service在類上注解運行 參考 SpringBoot&#xff1a;SpEL讓復雜權限控制變得很簡單 一、概念 對于在Springboot中&#xff0c;利用自定義注解切面來實現接口…

opencv實戰項目 手勢識別-手勢音量控制(opencv)

本項目是使用了谷歌開源的框架mediapipe&#xff0c;里面有非常多的模型提供給我們使用&#xff0c;例如面部檢測&#xff0c;身體檢測&#xff0c;手部檢測等。 手勢識別系列文章 1.opencv實現手部追蹤&#xff08;定位手部關鍵點&#xff09; 2.opencv實戰項目 實現手勢跟蹤…

8月14日,每日信息差

1、FF正式交付首輛FF 91 2.0 Futurist Alliance給塔尖用戶 2、消息稱iPhone SE 4設計基于iPhone 14&#xff0c;但仍是后置單攝像頭 3、阿聯酋力推電動汽車發展。該政策將作為一個監管框架&#xff0c;明確電動汽車充電站等基礎設施建設的標準&#xff0c;并推動全國標準統一…

Jay17 2023.8.12日報

8.12 今天做了2題&#xff0c;CTFshow 紅包挑戰8&#xff08;PHP create_function()&#xff09;和BUU [RoarCTF 2019]Easy Java&#xff08;web.xml泄露&#xff09;。 此外一直在打NepCTF&#xff0c;出了一題&#xff08;ez_java_checkin&#xff09;簡單了解了java中shri…

Kafka消息隊列學習(一)

文章目錄 概述核心概念生產者示例同步 / 異步發送消息生產者參數配置ack-確認機制retries - 重試次數compression_type - 消息壓縮類型 分區機制分區策略 消費者消息有序性提交和偏移量偏移量提交方式手動提交 高可用設計 SpringBoot集成Kafka基本使用傳遞對象消息 概述 核心概…

HTTP之cookie基礎學習

目錄 Cookie 什么是Cookie Cookie分類 Cookie版本 Cookie工作原理 Cookie詳解 創建cookie cookie編碼 cookie過期時間選項 Cookie流程 Cookie使用 會話管理 個性化信息 記錄用戶的行為 Cookie屬性 domain選項 path選項 secure選項 cookie…

帶著問題學習分布式系統

寫在前面 聽過很多道理&#xff0c;卻依然過不好這一生。 看過很多關于學習的技巧、方法&#xff0c;卻沒應用到自己的學習中。 隨著年紀變大&#xff0c;記憶力越來越差&#xff0c;整塊的時間也越來越少&#xff0c;于是&#xff0c;越來越希望能夠更高效的學習。學習是一種習…