ws2812C驱动示例主控芯片为HC32F460系列
这款LED灯最神奇的地方在于控制线只有一根,即单个IO既可以控制一个以及多个灯的亮灭和RGB颜色,当我第一次接触这个的时候,小小的质疑了二进制的状态,直到我看完协议之后,发现是时序上的串行,才豁然开朗。
多位(几个LED就是几位)通过引脚级联,接一个LED的DOUT引脚到另一个LED的DIN引脚,通过这种级联的方式,只需要使用一个IO口(单片机引脚)就能控制尽可能多的LED。
每个LED都集成了一颗驱动芯片在里面,让我们的LED变得智能和寻址,每一个内部都有恒流驱动,所以LED颜色非常一致,即使电压有小幅抖动,电压变化也是一样的。
不需要外部电阻——限流电阻,使LED灯的布局设计变得简单。
单线通信,能够最大限度的减少单片机IO口的压力,另外这款RGB灯使用了WS2812B(WS2812C跟B的01码的高低电平持续时间是一样的)驱动芯片,让外围电路只需要一颗电容就能够满足电路需求,从而最大可能的让电路变得简单优美。
特点
智能反接保护,电源反接不会损坏IC;
IC控制电路与LED点光源公用一个电源;
控制电路与RGB芯片集成在一个5050封装的元器件中,构成一个外控像素点;
内置信号整形电路,任何一个像素点收到信号后经过波形整形再输出,保证线路波形畸变不会累加;
内置上电复位和掉电复位电路;
每个像素点的三基色颜色可实现256级亮度显示,完成16777216种颜色的全真色彩显示,扫描频率不低于400Hz;
串行级联接口,能通过一根信号线完成数据的接收与解码;
任意两点传输距离在不超过5米时,无需增加额外电路;
当刷新速率30帧/秒时,级联数不小于1024点;
数据发送速度可达800Kbps;
光的颜色高度一致,性价比高。
注意: 800Kbps,相当于1.25us传输一比特数据。
引脚图
引脚功能描述:
NO. | Symbol | 功能描述 |
---|---|---|
1 | VDD | LED的供电电源,Vdd 范围 +3.5~+5.3 V |
2 | DOUT | 控制信号数据输出引脚 |
3 | VSS | 地 |
4 | DIN | 控制信号数据输入引脚 |
典型电路
串联方法
原理图
除了灯珠以外只需要额外增加一个0.1uF的电容即可。
硬件连接
HC32F460 | WS2812模块 |
---|---|
PA15(可以选择任意一个GPIO,即使是PA15作为JTAG口也可以复用为IO) | DIN |
VCC | +5V |
GND | GND |
驱动原理
数据协议采用单线归零码的通讯方式,像素点在上电复位以后,DIN端接受从控制器传输过来的数据,首先送过来的24bit数据被第一个像素点提取后,送到像素点内部的数据锁存器,剩余的数据经过内部整形处理电路整形放大后通过DOUT端口开始转发输出给下一个级联的像素点,每经过一个像素点的传输,信号减少24bit。
像素点采用自动整形转发技术,使得像素点的级联个数不受信号传送的限制,仅仅受限信号传输速度要求。
因为数据被内部锁存,所以只要不改变颜色值(模块持续供电),颜色是不会发生改变的,设置颜色的脉冲也不需要持续提供(单片机发生复位也无影响),只需要在修改颜色值的时候,发送一遍即可。
0和1的区分
Treset:复位时间
由上图可知,我们要发送 '0' ,需要将GPIO引脚置高并持续0.4 us(400 ns),然后GPIO置低并持续0.85 us(850 ns),此过程即完成0 code的发送。如何产生这个ns级别的延时呢,常用的方法是使用nop空指令:
#define WS_TIMES 2 //和你的芯片主频有关,HC32F460主频168M的时候,使用的是2
void delay_250ns(void)
{u8 del_t=WS_TIMES;while(del_t--)__NOP();
}
然后用示波器观察与模块DIN引脚相连的GPIO输出的脉冲信号,查看其高电平是否与咱们预定义的一致,如果不一致,增加或减少空指令进行调整。
经过示波器大约是这么长的时间。
//发送0和1的函数void send_0(void)
{TH;delay_250ns();TL;delay_250ns();delay_250ns();delay_250ns();
}
void send_1(void)
{TH;delay_250ns();delay_250ns();delay_250ns();TL;delay_250ns();delay_250ns();delay_250ns();
}
实际调试的时候需要根据实际情况调整。
24 bit数据的组成
注意: 数据传输顺序按GRB顺序传输,并且高位在前。
void ws2812_rgb(u8 ws_num,u8 ws_r,u8 ws_g,u8 ws_b)
{ws_data[(ws_num-1)*3]=ws_g;ws_data[(ws_num-1)*3+1]=ws_r;ws_data[(ws_num-1)*3+2]=ws_b;
}
ws_data[] 数组用于记录待传输的RGB数据,每一个灯珠的颜色占用三个字节,因为数据传输顺序按GRB的顺序传输,所以赋值的时候注意先后顺序,上面函数是设置某一个灯珠的颜色值。
ws_data[] 数组中颜色值设置完毕之后,就要把这个数组的数据发送到模块中,具体的实现函数如下:
void ws2812_refresh(u8 ws_count)
{u8 ws_ri=0;for(;ws_ri<ws_count*3;ws_ri++){if((ws_data[ws_ri]&0x80)==0) send_0(); else send_1();if((ws_data[ws_ri]&0x40)==0) send_0(); else send_1();if((ws_data[ws_ri]&0x20)==0) send_0(); else send_1();if((ws_data[ws_ri]&0x10)==0) send_0(); else send_1();if((ws_data[ws_ri]&0x08)==0) send_0(); else send_1();if((ws_data[ws_ri]&0x04)==0) send_0(); else send_1();if((ws_data[ws_ri]&0x02)==0) send_0(); else send_1();if((ws_data[ws_ri]&0x01)==0) send_0(); else send_1();}//延时一段时间ws2812_reset();
}
ws_data[] 数组中的每一个字节按位发送,因为高位在前,所以先发送每个字节的高位,获取最高位的值的方法为:ws_data[ws_ri]&0x80 。
数据传输方法
N位的模块,一次就要发送 N * 3 字节的数据。
注意: 上图中D1的数据是通过单片机发送,D2,D3,D4通过像素内重塑放大传输。
主函数就是点灯逻辑了。上传参考的代码:
#ifndef ws2812_h__
#define ws2812_h__
#include "sys.h"//用户修改处
#define WS_TIMES 6 //和你的芯片主频有关,stm32f407用6,自己多试下,或者有条件的用示波器看下
#define TH PEout(4)=1;
#define TL PEout(4)=0;//RGB--定义了几个标准的rgb值
#define WS_DARK 0,0,0
#define WS_WHITE 255,255,255
#define WS_RED 255,0,0
#define WS_GREEN 0,255,0
#define WS_BLUE 0,0,255
#define WS_YELLO 255,255,0
#define WS_PURPLE 255,0,255
#define WS_CYAN 0,255,255//extern u8 ws_data[];如果你需要在其他地方用到这个数组,就不注释 void ws2812_init(void);
void ws2812_rgb(u8 ws_i,u8 ws_r,u8 ws_g,u8 ws_b);
void ws2812_rgb_all(u8 ws_i,u8 ws_r,u8 ws_g,u8 ws_b);
void ws2812_refresh(u8 ws_i);
void ws2812_reset(u8 ws_set);void delay_250ns(void);
void send_0(void);
void send_1(void);
void send_res(void);#endif //ws2812_h__
#include "ws2812.h"
//用法示例,先保存到数组,用 ws2812_rgb函数,然后用ws2812_refresh函数发送
// ws2812_rgb(1, WS_RED);
// ws2812_rgb(2, WS_GREEN);
// ws2812_rgb(3, WS_BLUE);
// ws2812_rgb(4, WS_WHITE);
// ws2812_rgb(5, WS_PURPLE);
// ws2812_rgb(6, WS_YELLO);
// ws2812_rgb(7, WS_DARK);
// ws2812_rgb(8, WS_BLUE);
// ws2812_refresh(8);void ws2812_init(void)//PE4
{GPIO_InitTypeDef GPIO_InitStructure;RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;GPIO_Init(GPIOE, &GPIO_InitStructure);GPIO_ResetBits(GPIOE,GPIO_Pin_4);
}u8 ws_data[200]={0};
void ws2812_rgb(u8 ws_i,u8 ws_r,u8 ws_g,u8 ws_b)
{ws_data[(ws_i-1)*3]=ws_g;ws_data[(ws_i-1)*3+1]=ws_r;ws_data[(ws_i-1)*3+2]=ws_b;
}
void ws2812_rgb_all(u8 ws_i,u8 ws_r,u8 ws_g,u8 ws_b)
{static u8 rgb_wsi;for(rgb_wsi=1;rgb_wsi<=ws_i;rgb_wsi++){ws_data[(rgb_wsi-1)*3]=ws_g;ws_data[(rgb_wsi-1)*3+1]=ws_r;ws_data[(rgb_wsi-1)*3+2]=ws_b;}
}void ws2812_refresh(u8 ws_i)
{u8 ws_ri=0;for(;ws_ri<ws_i*3;ws_ri++){if((ws_data[ws_ri]&0x80)==0) send_0(); else send_1();if((ws_data[ws_ri]&0x40)==0) send_0(); else send_1();if((ws_data[ws_ri]&0x20)==0) send_0(); else send_1();if((ws_data[ws_ri]&0x10)==0) send_0(); else send_1();if((ws_data[ws_ri]&0x08)==0) send_0(); else send_1();if((ws_data[ws_ri]&0x04)==0) send_0(); else send_1();if((ws_data[ws_ri]&0x02)==0) send_0(); else send_1();if((ws_data[ws_ri]&0x01)==0) send_0(); else send_1();}send_res();
}void ws2812_reset(u8 ws_set)
{for(int i=0;i<200;i++){ws_data[i]=ws_set;}
}void delay_250ns(void)
{u8 del_t=WS_TIMES;while(del_t--)__NOP();
}void send_0(void)
{TH;delay_250ns();TL;delay_250ns();delay_250ns();delay_250ns();delay_250ns();
}
void send_1(void)
{TH;delay_250ns();delay_250ns();delay_250ns();delay_250ns();TL;delay_250ns();
}
void send_res(void)
{TL;delay_us(300);
}
最后感谢B站的视频教程,感谢网友们的分享。
收益最大的是这个:一个IO控制很多个LED,这个技能你get到了吗
ws2812C驱动示例主控芯片为HC32F460系列相关推荐
- 华大单片机HC32F460 系列MCU
1 摘要 本篇应用笔记主要介绍如何使用华大单片机 HC32F460 系列MCU的 DMA 模块传输数据. 2 DMA 简介 什么是 DMA? DMA(直接内存访问控制器)功能块可以不通过 CPU 高速 ...
- 1.8寸TFT LCD128X160 ST7735S SPI串口屏驱动示例
1.8寸TFT LCD128X160 ST7735S SPI串口屏驱动示例 1.8寸TFT LCD128X160 ST7735S SPI串口屏 驱动资料 由中景园提供的,里面包含了: 链接:https ...
- Linux MISC驱动示例
misc 的意思是混合.杂项的,因此 MISC 驱动也叫做杂项驱动,也就是当我们板子上的某些外设无法进行分类的时候就可以使用 MISC 驱动.MISC 驱动其实就是最简单的字符设备驱动,通常嵌套在 p ...
- Linux SPI 驱动示例
一 Linux 下 SPI 驱动框架 SPI 驱动框架分为主机控制器驱动和设备驱动,主机控制器也就是 SOC 的 SPI 控制器接口. 1.1 SPI 主机驱动 SPI 主机驱动就是 SOC 的 SP ...
- DPDK — 网卡初始化流程(Intel 82599 ixgbe 网卡驱动示例)
目录 文章目录 目录 总览 rte_eth_dev/rte_eth_dev_data 数据结构 rte_eth_dev_count 函数 rte_eth_dev_configure 函数 ixgbe_ ...
- 8188gu驱动和su realtek_Realtek全系列官方网卡驱动
1.有线网卡系列: 81xx系列:理论可以完美驱动下面所有网卡(Lion和SL均可驱动) RTL8100E/RTL8101E/RTL8102E-GR/RTL8103E(L) RTL8102E(L)/R ...
- mysqlyog mysql8.012_瑞昱网卡驱动-Realtek瑞昱RTL-81xx系列网卡驱动(Win8)8.012.0304.2013版-东坡下载...
如果说Realtek靠着产品物美价廉以及提供公版驱动支持这两大法宝在集成音频芯片领域一枝独秀,大有一统江湖之势,那么在集成网卡芯片领域,可以说对手如云了. 像Marvell.Broadcom.Inte ...
- mysqlyog mysql8.012_瑞昱网卡驱动-Realtek瑞昱RTL-81xx系列网卡驱动(Win8)8.012.0304.2013版下载_东坡手机下载...
如果说Realtek靠着产品物美价廉以及提供公版驱动支持这两大法宝在集成音频芯片领域一枝独秀,大有一统江湖之势,那么在集成网卡芯片领域,可以说对手如云了. 像Marvell.Broadcom.Inte ...
- NVIDIA Jetson Xavier配置大恒相机驱动(gige接口火星系列)
一.下载驱动 下载链接:https://www.daheng-imaging.com/Software/index.aspx?nodeid=304 这里要注意:Xavier采用ARMv8架构,因此下载 ...
最新文章
- 【译文转帖】用C#写COM组件 Building COM Objects in C#
- 12306新版上线 还是不能选上下铺
- GHOST系统封装详细图文教程
- 【Matlab】求解黎卡提 Riccati 方程 李雅普诺夫 Lyapunov 方程
- 2021年程序员可以做哪些副业?
- python秒表代码_斌哥教你自制千分秒表(键盘控制)
- 支付中心设计与方案,收藏了
- 【历史上的今天】1 月 17 日:VirtualBox 诞生;杨致远辞职;风暴蠕虫问世
- 动态规划——详细入门讲解
- 微信扫描下载apk解决方案
- 1062: [NOI2008]糖果雨 - BZOJ
- python统计一组数据中的概率_Python实现概率分布
- 网络工程师每日练习(5)
- 移动web——学习笔记整理
- no matching host key type found. Their offer: ssh-rsa 问题解决
- win7无线局域网_存储卡具备WiFi有多方便?东芝 FlashAir 无线存储卡上手体验
- 小白终是踏上了这条不归路----小文的mysql学习笔记(8)----分页查询
- SSL/TLS会话的流量分析
- vCalendar文件格式解析
- vue传值的几种方法