ESP32学习日记:(2)驱动WS2812b

本文讲述了作者在使用ESP32驱动WS2812b时遇到的延时问题,通过探索并利用RMT功能,最终成功实现驱动。作者还提到ESP-IDF文档的挑战和学习新外设的重要性。
摘要由CSDN通过智能技术生成

使用ESP32驱动WS2812b

踩过的坑放在前面

ws2812b手册
通过阅读ws2812b的手册可以知道它使用的通信协议,高低电平的变化在ns这个级别,但是esp-idf库中提供的延时函数只有s和ms级别的。

#include <unistd.h>
sleep(1);// 延时1s 
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
vTaskDelay(100 / portTICK_PERIOD_MS); // 延时100ms

之前在stm32的学习过程中,可以通过while循环获取一个ns级别的延时,方法如下:

/*
	假设主频是72000000Hz,也就是单片机1s进行72M次运算,可以换算出
	单片机100ns进行7.2此运算。
*/
void delay_ns(uint32_t ns)
{
	ns*=7;
	while(ns--);
}

之前我用这个办法在stm32上实现过驱动ws2812b,可是同样的方法搬到ESP32就不好使了。

使用Remote Control Transceiver (RMT)轻松驱动ws2812b

经过上面的一番折腾,没能成功驱动,在查找资料的过程中偶然看到了官方教程😶(挺让人无语的,我不知道有这个外设)
乐鑫科技官方驱动ws2812b教程
看完教程后先去官方文档中了解了一下这个外设
官方文档对RMT的介绍
然后参考着例程源码,把关键代码copy过来成功驱动!

#include <stdio.h>
#include <unistd.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include "driver/rmt_tx.h"

#define LED_PIN 2
#define LED_NUM 20

typedef struct ledcolor
{
    uint8_t G;
    uint8_t R;
    uint8_t B;
} ledcolor;

void app_main(void)
{
    // 初始化RMT的一个通道
    printf("New RMT_CH...\n");
    rmt_channel_handle_t LED_CH = NULL; // LED的通道
    rmt_tx_channel_config_t LED_CH_CONFIG =
        {
            .clk_src = RMT_CLK_SRC_DEFAULT, // 选择时钟资源:默认资源
            .gpio_num = LED_PIN,            // 配置rmt输出引脚
            .mem_block_symbols = 64,        // 增大块的大小可以使 LED 减少闪烁?
            .resolution_hz = 10000000,      // 频率为10MHz,1个tick是0.1us
            .trans_queue_depth = 4,         // 设置后台待处理的事务数量?
        };
    rmt_new_tx_channel(&LED_CH_CONFIG, &LED_CH);

    // 初始化一个RMT编码器
    rmt_encoder_handle_t LED_ENCODE = NULL; // LED的编码器
    rmt_bytes_encoder_config_t LED_ENCODE_CONFIG = {
        .bit0 = {
            .level0 = 1,
            .duration0 = 3, // T0H=0.3us
            .level1 = 0,
            .duration1 = 9, // T0L=0.9us
        },
        .bit1 = {
            .level0 = 1,
            .duration0 = 9, // T1H=0.9us
            .level1 = 0,
            .duration1 = 3, // T1L=0.3us
        },
        .flags.msb_first = 1 // 大端先发
    };
    rmt_new_bytes_encoder(&LED_ENCODE_CONFIG, &LED_ENCODE);

    // 使能RMT
    rmt_enable(LED_CH);

    // 配置发送
    rmt_transmit_config_t RMT_TRANSMIT_CONFIG = {.loop_count = 0}; // 不循环发送

    // 主循环
    while (1)
    {
        // 发送数据
        ledcolor led_buffer[LED_NUM] = {0};
        ledcolor *sel = led_buffer;
        for (int i = 0; i < LED_NUM; i++)
        {
            sel->R = 0xFF;
            sel->G = 0;
            sel->B = 0;
            rmt_transmit(LED_CH, LED_ENCODE, &led_buffer, sizeof(led_buffer), &RMT_TRANSMIT_CONFIG);
            rmt_tx_wait_all_done(LED_CH, 0xFF);
            vTaskDelay(100 / portTICK_PERIOD_MS); // 延时100ms
            sel->R = 0;
            sel->G = 0;
            sel->B = 0;
            if (sel == &led_buffer[19])
            {
                sel = led_buffer;
                continue;
            }
            sel++;
        }
    }
}


写在最后的碎碎念

esp-idf的文档很大一部分都是英文的,例程里的注释也是,阅读起来比较缓慢,但是也能理解。
今天浪费了大量时间去实现ns级别的延时函数,看来得去熟悉一下ESP32上已经有的所有外设,以防再次踩坑。

  • 9
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值