WS2812的数据手册还是很好找的,可以直接去立创商城输入型号就可以找到。
VDD:供电输入;DI:数据输入;DO:数据输出(用于级联);GND:供电地
如图供电5V足够了
每个颜色数据为8bit
波形图还是很明了易懂的,类似于NEC编码方式。根据数据传输定义,可以知道咱们需要给它的控制信号是1MHz的。
一定要看,厂商一般都会做大量的测试,他们的建议是最好的参考标准。这个器件的手册还是很详细的,如图的1、2条说明仔细看。
根据器件的数据手册,可以很轻松的绘制电路图
例程内容较为复杂,初学者一时半会很难明白其中的逻辑。在此,我做一个简单的实现例程,
目前只用到了RMT的发送,所以只说明发送的API函数
typedef struct {
gpio_num_t gpio_num; /*所要映射的GPIO口,不使用时设置为-1*/
rmt_clock_source_t clk_src; /*RMT通道所使用的时钟源 */
uint32_t resolution_hz; /*此通道的时钟分辨率 */
size_t mem_block_symbols; /*内存块大小,如果启用了DMA,则该字段可以控制内部DMA缓冲区大小,建议设置1024;如果未启用DMA,则至少设置为64。不是所有通道都支持DMA,具体要查看芯片的TRM文档*/
size_t trans_queue_depth; /*设置后台等待处理的事务数量*/
int intr_priority; /*设置中断优先级 */
struct {
uint32_t invert_out: 1; /*设置是否反转输出信号*/
uint32_t with_dma: 1; /*是否开启DMA */
uint32_t io_loop_back: 1; /*是否返回给输入,作为换回测试 */
uint32_t io_od_mode: 1; /*设置GPIO是否作为开漏模式 */
} flags; /*!< TX channel config flags */
} rmt_tx_channel_config_t;
esp_err_t rmt_new_tx_channel(const rmt_tx_channel_config_t *config, rmt_channel_handle_t *ret_chan)
/*第一个参数是 rmt_tx_channel_config_t定义并填充的结构体变量,第二个参数是此函数返回的RMT通道句柄,需要使用rmt_channel_handle_t先声明一个变量*/
//使能
esp_err_t rmt_enable(rmt_channel_handle_t channel) //参数为rmt_new_tx_channel返回的RMT通道句柄
//禁用
esp_err_t rmt_disable(rmt_channel_handle_t channel)//参数为rmt_new_tx_channel返回的RMT通道句柄
typedef struct {
rmt_symbol_word_t bit0; /*RMT符号的bit0字节格式 */
rmt_symbol_word_t bit1; /*RMT符号的bit1字节格式*/
struct {
uint32_t msb_first: 1; /*最先编最高有效位*/
} flags; /*编码配置状态 */
} rmt_bytes_encoder_config_t;
typedef union {
struct {
uint16_t duration0 : 15; /* level0 持续时间*/
uint16_t level0 : 1; /*Level0的电平值*/
uint16_t duration1 : 15; /*level1 持续时间*/
uint16_t level1 : 1; /*Level1的电平值 */
};
uint32_t val; /* 与RMT 符号等价的无符号值 */
} rmt_symbol_word_t;
esp_err_t rmt_new_bytes_encoder(
const rmt_bytes_encoder_config_t *config, //创建好的 rmt_bytes_encoder_config_t的结构体变量
rmt_encoder_handle_t *ret_encoder//返回的编码器句柄,需要在调用前创建 rmt_encoder_handle_t变量
)
typedef struct {
int loop_count; /*循环次数 ,设置为-1则无限循环*/
struct {
uint32_t eot_level : 1; /*发送结束后输出的电平 */
uint32_t queue_nonblocking : 1; /*设置当传输队列满的时候该函数是否需要等待 */
} flags; /*!< Transmit specific config flags */
} rmt_transmit_config_t;
esp_err_t rmt_transmit(
rmt_channel_handle_t tx_channel,//发送通道句柄
rmt_encoder_handle_t encoder, //编码器句柄
const void *payload, //指向需要发送的值
size_t payload_bytes, //发送的值的大小
const rmt_transmit_config_t *config//发送的配置结构体
)
/**
* Copyright (C) 2024-2034 HalfMoon2.
* All rights reserved.
*
* @file Filename without the absolute path
* @brief Brief description
* @author HalfMoon2
* @date 2025-06-05
* @version v0.1
*
* @revision history:
* 2025-06-05 - Initial version.
*/
#include <stdio.h>
#include "driver/rmt_common.h"
#include "driver/rmt_tx.h"
#include "driver/rmt_encoder.h"
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
void app_main(void)
{
uint8_t value[3]={0x0f,0xb0,0x01};
rmt_channel_handle_t tx_chan = NULL;
rmt_tx_channel_config_t tx_chan_config = {
.clk_src = RMT_CLK_SRC_DEFAULT, // 选择时钟源
.gpio_num = 48, // GPIO 编号
.mem_block_symbols = 64, // 内存块大小,即 64 * 4 = 256 字节
.resolution_hz = 10 * 1000 * 1000, // 10 MHz 滴答分辨率,即 1 滴答 = 100ns
.trans_queue_depth = 4, // 设置后台等待处理的事务数量
.flags.invert_out = false, // 不反转输出信号
.flags.with_dma = false, // 不需要 DMA 后端
};
ESP_ERROR_CHECK(rmt_new_tx_channel(&tx_chan_config, &tx_chan));
rmt_encoder_handle_t rmt_encoder=NULL;
rmt_bytes_encoder_config_t rmt_bytes_encoder={
.bit0={
.level0=1,
.duration0=0.3*10000000/1000000, //T0H
.level1=0,
.duration1=0.6*10000000/1000000, //T0L
},
.bit1={
.level0=1,
.duration0=0.6*10000000/1000000, //T1H
.level1=0,
.duration1=0.3*10000000/1000000, //T1L
},
.flags={
.msb_first=1,
}
};
rmt_new_bytes_encoder(&rmt_bytes_encoder,&rmt_encoder);
rmt_transmit_config_t rmt_transmit_config={
.loop_count=0,
};
ESP_ERROR_CHECK(rmt_enable(tx_chan));
ESP_ERROR_CHECK(rmt_transmit(tx_chan,rmt_encoder,value,sizeof(value),&rmt_transmit_config));
}
从波形到颜色,说明这个简单的操作是可以很轻松实现WS2812B的控制的。
整篇文章结构可以看出,如果要控制一个外设要做到以下步骤:
这样一个简单的控制程序就完成了。当然最后的结果就跟我粘贴的代码一样,都放在了main函数里了,业界称为屎山。这个时候就需要通过面向对象的编程思想以及设计模式等知识,将代码规范化、增强其可移植性等。
要记住的是,只有理解了其基本的原理,才能万变不离其中。
作者: 二月半, 来源:面包板社区
链接: https://mbb.eet-china.com/blog/uid-me-1862109.html
版权声明:本文为博主原创,未经本人允许,禁止转载!
二月半 2025-6-10 09:16
eeNick 2025-6-10 08:59