WS2812全彩RGB驱动方法

这篇具有很好参考价值的文章主要介绍了WS2812全彩RGB驱动方法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一. 简介

买了一个圆形的WS2812模块玩玩,特来总结一下驱动方法,感觉对比于普通的RGB灯来说,还是有点不一样的。
踩了一些坑,也在此列出。

二. ws2812驱动

驱动方法其实很简单,就是发送一个24bit的数据即可,数据0和1的定义分别如下。
ws2812驱动程序详解,FPGA,fpga开发

三. 特别提示

  1. 它没有所谓的空闲态,如果两个24bit的数据传输时间间隔相差过大,那个第二个24bit数据,不会传递到后面的ws2812灯上,而是会更新当前ws2812灯的状态。

四. FPGA实现

整个模块的实现方式如下,欢迎关注,写的比较随便了。文章来源地址https://www.toymoban.com/news/detail-518046.html


module ws2812_driver(
	
	input				sys_clk_50M,
	input				rst_n,
	
	output			ws2812_o,
	
	
	
	//外部控制
	input				ws2812_req,			//显示请求
	output			ws2812_ack,		   //显示完成应答
	input				ws2812_reset,	   //显示复位
	output			ws2812_reset_ack, //显示复位完成
	input[7:0]		ws2812_r,			//显示的数据
	input[7:0]		ws2812_g,
	input[7:0]		ws2812_b
);



//逻辑0高低电平持续周期数
localparam	T0_H		=	6'd16;  //320ns
localparam	T0_L		=	6'd42;  //840ns


//逻辑1高低电平持续周期数
localparam	T1_H		=	6'd42;  //840ns
localparam	T1_L		=	6'd16;  //320ns

//复位持续周期数
localparam	T_RESET	=	14'd15000;//300us


localparam	S_IDLE		=		3'd0;
localparam	S_DATA		=		3'd1;
localparam	S_RESET		=		3'd2;
localparam	S_ACK			=		3'd3;



localparam	S_Sub_IDLE		=		4'd0;
localparam	S_Sub_T0_L		=		4'd1;
localparam	S_Sub_T0_H		=		4'd2;
localparam	S_Sub_T1_L		=		4'd3;
localparam	S_Sub_T1_H		=		4'd4;
localparam	S_Sub_ACK		=		4'd5;







reg[2:0]		state , next_state;
reg[3:0]		sub_state , sub_next_state;


reg[13:0]	t_cnt;				//时间计数
reg[5:0]		bit_cnt;				//发送比特位计数

reg[23:0]	color_rgb;




assign	ws2812_o = (sub_state == S_Sub_T0_L || sub_state == S_Sub_T1_L || state == S_RESET) ? 1'b0 : 1'b1;
assign	ws2812_ack = ( state == S_ACK ) ? 1'b1 : 1'b0;
always@(posedge sys_clk_50M or negedge rst_n)
begin
	if( rst_n == 1'b0 )
		state <= S_IDLE;
	else
		state <= next_state;
end


always@(*)
begin
	case(state)
	S_IDLE:
		if( ws2812_reset == 1'b1)
			next_state <= S_RESET;
		else if( ws2812_req == 1'b1)
			next_state <= S_DATA;
		else
			next_state <= S_IDLE;
	S_DATA:
		if( bit_cnt == 'd23)
			next_state <= S_ACK;
		else
			next_state <= S_DATA;
	S_RESET:
		if( t_cnt == T_RESET)
			next_state <= S_ACK;
		else
			next_state <= S_RESET;
	S_ACK:
		next_state <= S_IDLE;
	default: next_state <= S_IDLE;
	endcase 
end




always@(posedge sys_clk_50M or negedge rst_n)
begin
	if( rst_n == 1'b0 )
		t_cnt <= 8'd0;
	else if( state != next_state )
		t_cnt <= 8'd0;
		
	else if( state == S_DATA )
		if( sub_state == S_Sub_T0_L && t_cnt == T0_L)
			t_cnt <= 8'd0;
		else if( sub_state == S_Sub_T0_H && t_cnt == T0_H)
			t_cnt <= 8'd0;
		else if( sub_state == S_Sub_T1_L && t_cnt == T1_L)
			t_cnt <= 8'd0;
		else if( sub_state == S_Sub_T1_H && t_cnt == T1_H)
			t_cnt <= 8'd0;
		else
			t_cnt <= t_cnt + 1'b1;
	else if( state == S_RESET )
		t_cnt <= t_cnt + 1'b1;
	else
		t_cnt <= 'd0;

end




always@(posedge sys_clk_50M or negedge rst_n)
begin
	if( rst_n == 1'b0 )
		sub_state <= S_Sub_IDLE;
	else
		sub_state <= sub_next_state;

end


always@(*)
begin
	case(sub_state)
	S_Sub_IDLE:
		if( state == S_DATA && color_rgb[23] == 1'b1)
			sub_next_state <= S_Sub_T1_H;
		else if( state == S_DATA && color_rgb[23] == 1'b0)
			sub_next_state <= S_Sub_T0_H;
		else
			sub_next_state <= S_Sub_IDLE;
	S_Sub_T0_H:
		if( t_cnt == T0_H)
			sub_next_state <= S_Sub_T0_L;
		else if( state == S_ACK )
			sub_next_state <= S_Sub_IDLE;
		else
			sub_next_state <= S_Sub_T0_H;
	
	S_Sub_T0_L:
		if( t_cnt == T0_L && color_rgb[23] == 1'b0)
			sub_next_state <= S_Sub_T0_H;
		else if( t_cnt == T0_L && color_rgb[23] == 1'b1)
			sub_next_state <= S_Sub_T1_H;
		else
			sub_next_state <= S_Sub_T0_L;
				
	S_Sub_T1_H:
		if( t_cnt == T1_H)
			sub_next_state <= S_Sub_T1_L;
		else if( state == S_ACK )
			sub_next_state <= S_Sub_IDLE;
		else
			sub_next_state <= S_Sub_T1_H;
			
	S_Sub_T1_L:
		if( t_cnt == T1_L && color_rgb[23] == 1'b0)
			sub_next_state <= S_Sub_T0_H;
		else if( t_cnt == T1_L && color_rgb[23] == 1'b1)
			sub_next_state <= S_Sub_T1_H;
		else
			sub_next_state <= S_Sub_T1_L;
		
	default: sub_next_state <= S_Sub_IDLE;
	endcase

end





always@(posedge sys_clk_50M or negedge rst_n)
begin
	if( rst_n == 1'b0)
		color_rgb <= 24'd0;
	
	else if(state == S_DATA && sub_state == S_Sub_IDLE)
		color_rgb <= color_rgb << 1;
	else if( sub_state == S_Sub_T0_L && t_cnt == T0_L)
		color_rgb <= color_rgb << 1;
	else if( sub_state == S_Sub_T1_L && t_cnt == T1_L)
		color_rgb <= color_rgb << 1;
	else if( state == S_DATA)
		color_rgb <= color_rgb;
	else
		color_rgb <= {ws2812_g,ws2812_r,ws2812_b};
end



always@(posedge sys_clk_50M or negedge rst_n)
begin
	if( rst_n == 1'b0 )
		bit_cnt <= 6'd0;
	else if( sub_state == S_Sub_T0_L && t_cnt == T0_L )
		bit_cnt <= bit_cnt + 1'b1;
	else if( sub_state == S_Sub_T1_L && t_cnt == T1_L)
		bit_cnt <= bit_cnt + 1'b1;
	else if( state == S_ACK)
		bit_cnt <= 6'd0;
	else
		bit_cnt <= bit_cnt;

end


endmodule 

到了这里,关于WS2812全彩RGB驱动方法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【雕爷学编程】Arduino动手做(86)---4*4位 WS2812 全彩模块4

    37款传感器与执行器的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里准备逐一动手尝试系列实验,不管成功(程序走通)

    2024年02月15日
    浏览(19)
  • STM32作品设计:蓝牙彩灯V1.4(WS2812全彩、声控、光控、人体红外、小科语音控制、手机APP、蓝牙无线升级)

    @ biliblil视频链接:https://www.bilibili.com/video/BV14L411V78b/ 资料可联系作者:2809786963 实物链接:https://m.tb.cn/h.5hxssok?tk=vEQCWYHTKs0 CZ0001 1、手机APP控制亮度、颜色 2、多种显示模式:闪烁、渐变、呼吸、流水 3、拾音灯模式(随音起舞) 4、手机设置:光控模式、声控模式、声光控模式

    2024年02月11日
    浏览(46)
  • WS2812B灯带驱动实验

    KEIL5、正点原子阿波罗STM32F767开发板 过多介绍我这里不赘述了,想了解详情的可以看看手册,直接开干。 1.1、灯带连接方式 我们只要控制DIN端就好了。 1.2、传输数据方式 简单理解就是单总线发了一串数据,第一个灯拿了第一个字节的数据,第二个灯拿个第二个字节的数据,

    2024年02月08日
    浏览(16)
  • 【Verilog】FPGA驱动WS2812B点阵

    目录 1.整体框架 2.器件选择         WS2812B-64 8x8点阵: 3.手册解读         灯珠引脚:         连接方式:           数据传输方式:          数据波形构成:          数据波形持续时间: 4.模块设计         数据处理模块设计:         控制模块设

    2024年02月09日
    浏览(19)
  • (STM32笔记5)ws2812驱动开发

    ws2812 需要开发的外设:ws2812 开发环境:MDK 开发板:stm32最小系统板 杜邦线无数 一、原理阐述 (一) 这个ws2812有很多种,一个小灯、灯带,矩形像素屏等等。 这些都是DIN连接输入,DOUT连接输出,另外两个引脚是GNE和VCC   (二) 数据传输原理: 第1个WS2812B灯珠接收到了第1个

    2024年01月19日
    浏览(21)
  • [HAL]STM32 SPI+DMA驱动WS2812

    该程序是纯手敲,非Cube生成!所有代码均注释。 源码在文章后面获取 Keyword: 单线通讯、归零码、Reset、RGB顺序 RGB一共有24bit位 -相当于驱动一个灯要24bit位 -驱动若干个灯要24* n bit位,通过Reset码决定数据终止(保持) 24bit位应该如何发送? 可见: 表示低电平需要 T0H和T0L的配

    2024年02月09日
    浏览(20)
  • LL库实现SPI MDA发送方式驱动WS2812

    1,首先打卡STM32CubeMX,配置一下工程,这里使用的芯片是STM32F030F4P6。   时钟 SPI外设  SPI DMA 下载接口,这个不配置待会下程序后第二次就不好下载调试了。  工程配置,没啥说的  选择生成所有文件  将驱动都改为LL库 然后直接点击 General Code 2,初始化dma:  这里卡了一会

    2024年02月12日
    浏览(20)
  • STM32+PWM+DMA驱动WS2812彩灯模块(附源码)

    WS2812是一颗数字LED灯珠,采用单总线通讯,每颗灯珠支持24bit的颜色控制,也即RGB888,信号线通过DIN输入,经过一颗灯珠之后,信号线上前24bit数据会被该灯珠锁存,之后将剩下的数据信号整形之后通过DOUT输出 C1为VDD的滤波电容,一般大小为100NF。 WS2812.c pwm.c DMA.c main.c 需要源

    2024年02月15日
    浏览(16)
  • STM32C0开发(1)----SPI 驱动WS2812灯珠

    本文介绍了如何使用STM32微控制器,结合STM32CubeMX配置工具和SPI通讯接口,来驱动和控制WS2812 LED灯带。这是一个集硬件连接、软件配置和编程开发于一体的综合性项目,目标是实现对LED灯带颜色和亮度的精确控制。 最近在弄ST的课程,需要样片的可以加群申请:615061293 。 ht

    2024年02月04日
    浏览(17)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包