esp32c2气氛灯
小陈学不停 2025-06-13

1 氛围灯
氛围灯的应用场景有汽车装饰、智能家居、娱乐场所、办公和学习环境等,也可以结合DMX512协议做一些舞台灯光效果,在此总结一下esp32c2驱动ws2812的方法

2 测试环境

3 实现方法
idf只有RMT方式驱动灯条的例子,而esp32c2刚好不支持rmt,
这里总结一下gpio和spi方式来驱动ws2812,希望能帮到一些人

采用单线归零方式驱动

根据IO的电平持续时间来区分逻辑0和逻辑1

绿色数据先发,高位在前

3.1 gpio方式
3.1.1 实现纳秒延时

#define delay_test(n) {cnt = n; do{__asm__ __volatile__("NOP");}while(cnt--);}static volatile gpio_dev_t *get_dev = GPIO_HAL_GET_HW(GPIO_PORT_0); int8_t gpio_test_delay(led_strip_t *handle, uint8_t set_delay){  volatile uint8_t cnt = 0; portDISABLE_INTERRUPTS();  get_dev->out_w1ts.val = (1<<4UL);  delay_test(set_delay); get_dev->out_w1tc.val = (1<<4UL);  portENABLE_INTERRUPTS();  return 0;}

用逻辑分析仪测试高电平的时间
当cnt为1时

当cnt为2时

当cnt为6时

3.1.2 发送数据

这里取cnt等于2时作为330ns的延时,取cnt为6时作为660ns的延时

static void io_write_data(uint8_t data, uint8_t gpio_pin){ volatile uint8_t cnt = 2;  for(uint8_t i=0;i<8;i++) { if(data & 0x80)//高位先发 {  get_dev->out_w1ts.val = (1< delay_660ns(); get_dev->out_w1tc.val = (1< delay_660ns();  } else {  get_dev->out_w1ts.val = (1< delay_330ns(); get_dev->out_w1tc.val = (1< delay_660ns(); } data<<=1; }}

3.1.3 设置颜色

static int8_t gpio_set_color(led_strip_t *handle, const uint32_t color){  uint8_t green = (uint8_t)(color>>8);//g uint8_t red = (uint8_t)(color>>16);//r uint8_t blue = (uint8_t)(color);//b uint8_t get_pin = handle->config.gpio_pin;   io_write_data(0,get_pin); io_write_data(0,get_pin);  io_write_data(0,get_pin); usleep(300);  portDISABLE_INTERRUPTS();  for (uint8_t i=0; iled_cnt; i++) { io_write_data(green,get_pin); io_write_data(red,get_pin);  io_write_data(blue,get_pin); }  portENABLE_INTERRUPTS();  usleep(300);   return 0;}

RGB颜色为FF00FF的实测波形

3.2 spi方式
3.2.1 写数据
设置spi的时钟为6MHz,那么一个时钟周期的时间为(1/6M)167ns,
当想表示逻辑1的时候,
需要高电平持续580ns~1us,然后是580ns~1us的低电平
需要4个时钟的高电平和4个时钟的低电平,都是167*4=668ns刚好满足条件,数据为0xF0
当想表示逻辑0的时候,
需要高电平持续220ns~380ns,然后是580ns~1us的低电平
需要2个时钟的高电平=2*167=334ns,6个时钟的低电平=6*167=1002ns=1us,数据为0xC0

static int8_t spi_send_data(spi_device_handle_t handle, const uint8_t *data, int len){ esp_err_t ret; spi_transaction_t t; if (len==0) return -1; //no need to send anything memset(&t, 0, sizeof(t)); //Zero out the transaction t.length=len*8; //Len is in bytes, transaction length is in bits. t.tx_buffer=data; //Data t.user=(void*)1; //D/C needs to be set to 1 ret=spi_device_polling_transmit(handle, &t); //Transmit!  if (ret) { return -1; }  return 0;}  static int8_t spi_set_color(led_strip_t *handle, const uint32_t color){ uint8_t color_rgb_buf[3];  color_rgb_buf[0] = (uint8_t)(color>>8);//g color_rgb_buf[1] = (uint8_t)(color>>16);//r color_rgb_buf[2] = (uint8_t)(color);//b  uint8_t data[24];  uint8_t get_high = handle->config.spi_config.spi_high_level_data; uint8_t get_low = handle->config.spi_config.spi_low_level_data;  for(uint8_t j = 0 ; j<3; j++) { uint8_t cr = color_rgb_buf[j];  uint8_t mask = 0x80; for(uint8_t k = 0; k<8; k++){ data[j*8+k] = (mask & cr) ? get_high : get_low; mask>>=1; } }  for (uint8_t i=0; iled_cnt; i++) { if (spi_send_data(handle->config.spi_config.handle,data,24)) {  return -1; }  }   return 0;}

3.2.2 实测波形
逻辑0:350ns高电平,1.05us低电平,
逻辑1:高电平和低电平都为700ns 设置RGB颜色为FF00FF的实测波形

4 测试程序
 #include #include #include  #include #include  #include "nvs_flash.h"#include "esp_event.h"#include "esp_netif.h"#include "esp_wifi.h"#include "esp_now.h"#include "esp_mac.h"#include "freertos/FreeRTOS.h"#include "freertos/semphr.h"#include "freertos/timers.h"#include "freertos/event_groups.h"#include "led_strip.h"led_strip_t led_strip;  void app_main(void){  #if 1 spi_config_t spi_config =  { .mosi_pin=4, .spi_high_level_data=0xf0, .spi_low_level_data=0xc0, .clock_speed_hz = 6*1000*1000, .host_id=SPI2_HOST, }; memcpy(&led_strip.config.spi_config,&spi_config,sizeof(spi_config_t));  uint8_t io_type=LED_STRIP_CTL_SPI; #else led_strip.config.gpio_pin = 4; #endif  led_strip_init(&led_strip,io_type,8);  led_strip_config_flash_ivt_ms(&led_strip,1000); led_strip_update_rgb(&led_strip,0xffffff); led_strip_set_state(&led_strip,LED_STRIP_STATE_BREATH);  for (;;) { led_strip_handle(&led_strip);  vTaskDelay(pdMS_TO_TICKS(10)); } } 

5 实验效果

6 总结
esp32的api占用时间过长,使用gpio方式驱动ws2812的话,无法像stm32那样可以轻松实现纳秒级别延时,需要结合逻辑分析仪来做实际测试,所以选择spi方式会更好一些。


声明: 本文转载自其它媒体或授权刊载,目的在于信息传递,并不代表本站赞同其观点和对其真实性负责,如有新闻稿件和图片作品的内容、版权以及其它问题的,请联系我们及时删除。(联系我们,邮箱:evan.li@aspencore.com )
0
评论
  • 相关技术文库
  • 电源
  • DC
  • AC
  • 稳压
下载排行榜
更多
评测报告
更多
广告