/*! * \file ws2815.c * * \brief Target xc aotimer driver implementation * * \copyright Revised BSD License, see section \ref LICENSE. * * \code * * _ __ _ ________ _ * | |/ /(_)___ / ____/ /_ (_)___ * | // / __ \/ / / __ \/ / __ \ * / |/ / / / / /___/ / / / / /_/ / * /_/|_/_/_/ /_/\____/_/ /_/_/ .___/ * /_/ * (C) 2022-2025 XinChip * * \endcode * * \author ( XinChip ) Alex-J * * \author ( XinChip ) */ /*----------------------------------------------------------------------------------- INCLUDE HEADE FILES ------------------------------------------------------------------------------------*/ #if(WS2815_CONTROL_MODE == SPI_DMA_MODE) #include "xc_drv_spi_dma.h" #include "xc_drv_spi.h" #elif(WS2815_CONTROL_MODE == GPIO_DELAY_MODE) #include "xc_drv_gpio.h" #endif /*------------------------------------------------------------------------------------ Local Variables -------------------------------------------------------------------------------------*/ LEDX_Task_TypeDef LED_TaskDef; uint8_t Temp_Flag = 0; uint8_t auto_Flag = 0; bool shutdown_Flag = 0; uint32_t color_buf[1] = {0}; uint32_t code_buf[1] = {0}; uint32_t conversion_color = 0; uint8_t step_temp = 0; uint8_t Muisc_mode = 0; uint8_t Muisc_Flag = 0; uint8_t color_ch = 0; uint8_t T1H = (0xF0); // 1码高电平(937.5ns) uint8_t T0H = (0xC0); // 0码高电平(312.5ns) // 预定义彩虹颜色表 const uint32_t rainbow_colors[11] = { 0xFF0000, // 红色 0xFF007F, // 粉红 0xFF00FF, // 紫色 0x7F00FF, // 靛蓝 0x0000FF, // 蓝色 0x00FFFF, // 青色 0x00FF7F, // 蓝绿色 0x00FF00, // 绿色 0x7FFF00, // 黄绿色 0xFFFF00, // 黄色 0xFF7F00, // 橙色 }; const uint32_t rainbow[7] = { 0xff0000, // 红 0x00ff00, // 绿 0x0000ff, // 蓝 0xffff00, // 黄 0x00ffff, // 青 0x9400D3, // 紫 0xffffff // 白 }; const uint32_t _rgb[3] = { 0xff0000, // 红 0x00ff00, // 绿 0x0000ff // 蓝 }; const uint32_t _ycp[3] = { 0xffff00, // 黄 0x00ffff, // 青 0x9400D3 // 紫 }; const uint32_t _ycpb[4] = { 0xffff00, // 黄 0x00ffff, // 青 0x9400D3, // 紫 0x0000ff // 蓝 }; const uint32_t _ycgb[4] = { 0xffff00, // 黄 0x00ffff, // 青 0x00ff00, // 绿 0x0000ff // 蓝 }; const uint32_t _ry[2] = { 0xff0000, // 红 0xffff00 // 黄 }; const uint32_t _rp[2] = { 0xff0000, // 红 0x9400D3 // 紫 }; const uint32_t _gc[2] = { 0x00ff00, // 绿 0x00ffff // 青 }; const uint32_t _gy[2] = { 0x00ff00, // 绿 0xffff00 // 黄 }; const uint32_t _bp[2] = { 0x0000ff, // 蓝 0x9400D3 // 紫 }; const uint32_t _rg[2] = { 0xff0000, // 红 0x00ff00 // 绿 }; const uint32_t _gb[2] = { 0x00ff00, // 绿 0x0000ff // 蓝 }; const uint32_t _yb[2] = { 0xffff00, // 黄 0x0000ff // 蓝 }; const uint32_t _yc[2] = { 0xffff00, // 黄 0x00ffff // 青 }; const uint32_t _cp[2] = { 0x00ffff, // 青 0x9400D3 // 紫 }; const uint32_t _bw[2] = { 0x000000, // 黑 0xffffff // 白 }; // mode73-74 六色明暗过渡红色 const uint32_t rainbow1[9] = { 0x00FF7F, // 绿 0x1E90FF, // 蓝 0xDC143C, // 红 0xFFD700, // 黄 0x00ffff, // 青 0xDC143C, // 红 0x9400D3, // 紫 0xFFFAF0, // 白 0xDC143C // 红 }; // mode75-76 六色明暗过渡绿色 const uint32_t rainbow2[9] = { 0xDC143C, // 红 0x1E90FF, // 蓝 0x00FF7F, // 绿 0xFFD700, // 黄 0x00ffff, // 青 0x00FF7F, // 绿 0x9400D3, // 紫 0xFFFAF0, // 白 0x00FF7F // 绿 }; // mode77-78 六色明暗过渡蓝色 const uint32_t rainbow3[9] = { 0xDC143C, // 红 0x00FF7F, // 绿 0x1E90FF, // 蓝 0xFFD700, // 黄 0x00ffff, // 青 0x1E90FF, // 蓝 0x9400D3, // 紫 0xFFFAF0, // 白 0x1E90FF // 蓝 }; // mode79-80 六色明暗过渡青色 const uint32_t rainbow4[9] = { 0xDC143C, // 红 0x00FF7F, // 绿 0x00ffff, // 青 0x1E90FF, // 蓝 0xFFD700, // 黄 0x00ffff, // 青 0x9400D3, // 紫 0xFFFAF0, // 白 0x00ffff // 青 }; // mode81-82 六色明暗过渡黄色 const uint32_t rainbow5[9] = { 0xDC143C, // 红 0x00FF7F, // 绿 0xFFD700, // 黄 0x1E90FF, // 蓝 0x00ffff, // 青 0xFFD700, // 黄 0x9400D3, // 紫 0xFFFAF0, // 白 0xFFD700 // 黄 }; // mode83-84 六色明暗过渡紫色 const uint32_t rainbow6[9] = { 0xDC143C, // 红 0x00FF7F, // 绿 0x9400D3, // 紫 0x1E90FF, // 蓝 0x00ffff, // 青 0x9400D3, // 紫 0xFFD700, // 黄 0xFFFAF0, // 白 0x9400D3 // 紫 }; // mode85-86 六色明暗过渡白色 const uint32_t rainbow7[9] = { 0xDC143C, // 红 0x00FF7F, // 绿 0xF5FFFA, // 白 0x1E90FF, // 蓝 0x00ffff, // 青 0xF5FFFA, // 白 0xFFD700, // 黄 0x9400D3, // 紫 0xF5FFFA // 白 }; // mode3-亮度衰减表 const uint16_t brightness_table[5] = { 102, // 位置0: 40%亮度 179, // 位置1: 70%亮度 255, // 位置2: 100%亮度 179, // 位置3: 70%亮度 102 // 位置4: 40%亮度 }; // mode10亮度衰减表 const uint16_t brightness_table2[21] = { 255, // 位置0: 100%亮度 242, // 位置1: 95%亮度 230, // 位置2: 90%亮度 217, // 位置3: 85%亮度 204, // 位置4: 80%亮度 191, // 位置5: 75%亮度 179, // 位置6: 70%亮度 166, // 位置7: 65%亮度 153, // 位置8: 60%亮度 140, // 位置9: 55%亮度 128, // 位置10: 50%亮度 115, // 位置11: 45%亮度 102, // 位置12: 40%亮度 90, // 位置13: 35%亮度 77, // 位置14: 30%亮度 64, // 位置15: 25%亮度 51, // 位置16: 20%亮度 38, // 位置17: 15%亮度 26, // 位置18: 10%亮度 13, // 位置19: 5%亮度 0 // 位置20: 0%亮度 }; // mode11-16亮度衰减表 const uint16_t brightness_table3[11] = { 255, // 位置0: 100%亮度 230, // 位置1: 90%亮度 204, // 位置2: 80%亮度 179, // 位置3: 70%亮度 153, // 位置4: 60%亮度 128, // 位置5: 50%亮度 102, // 位置6: 40%亮度 77, // 位置7: 30%亮度 51, // 位置8: 20%亮度 26, // 位置9: 10%亮度 0 // 位置10: 0%亮度 }; // mode67-72亮度衰减表 const uint16_t brightness_table4[7] = { 64, // 位置0: 25%亮度 128, // 位置1: 50%亮度 191, // 位置2: 75%亮度 255, // 位置3: 100%亮度 191, // 位置4: 75%亮度 128, // 位置5: 50%亮度 64 // 位置6: 25%亮度 }; // mode73-86亮度衰减表 const uint16_t brightness_table5[7] = { 255, // 位置0: 100%亮度 204, // 位置2: 80%亮度 153, // 位置4: 60%亮度 102, // 位置6: 40%亮度 77, // 位置8: 30%亮度 51, // 位置9: 20%亮度 26 // 位置6: 10%亮度 }; // mode129亮度衰减表 const uint16_t brightness_table6[24] = { 0, // 位置0: 亮度 0, 0, 0, 13, // 位置1: 亮度 13, // 位置2: 亮度 13, 26, 26, // 位置3: 亮度 38, // 位置4: 亮度 38, 51, // 位置5: 亮度 64, // 位置6: 亮度 77, // 位置7: 亮度 90, // 位置8: 亮度 102, // 位置9: 亮度 128, // 位置11: 亮度 140, // 位置12: 亮度 166, // 位置14: 亮度 179, // 位置15: 亮度 204, // 位置17: 亮度 217, // 位置18: 亮度 242, // 位置20: 度 255 }; // mode130亮度衰减表 const uint16_t brightness_table7[24] = { 255, // 位置0: 亮度 242, 217, 204, 217, // 位置1: 亮度 204, // 位置2: 亮度 179, 166, 140, // 位置3: 亮度 128, // 位置4: 亮度 102, 90, // 位置5: 亮度 77, // 位置6: 亮度 64, // 位置7: 亮度 51, // 位置8: 亮度 38, // 位置9: 亮度 38, // 位置11: 亮度 26, // 位置12: 亮度 26, // 位置14: 亮度 13, // 位置15: 亮度 13, // 位置17: 亮度 0, // 位置18: 亮度 0, // 位置20: 度 0 }; //uint32_t sysclk_sel_tbl[] = {2000, 16000, 24000, 48000, 60000, 80000, 1200000, 160000}; #if(WS2815_CONTROL_MODE == SPI_DMA_MODE) // 双缓冲区定义 static uint8_t buffer0[DMA_MAX_BLOCK_SIZE]; static uint8_t buffer1[DMA_MAX_BLOCK_SIZE]; static uint8_t* active_buffer = buffer0; static uint8_t* fill_buffer = buffer1; // 传输状态 static RGB_Color led_colors[LEDS_NUM]; volatile uint8_t dma_busy = 0; static volatile TransferState transfer_state = TRANSFER_IDLE; static uint16_t current_led_index = 0; static uint16_t current_active_len = 0; static uint32_t reset_bytes_remaining = 0; #elif(WS2815_CONTROL_MODE == GPIO_DELAY_MODE) //static RGB_Color led_colors[LEDS_NUM]; #endif /*------------------------------------------------------------------------------------ Func Prototype -------------------------------------------------------------------------------------*/ #if(WS2815_CONTROL_MODE == SPI_DMA_MODE) // 函数声明 static void start_next_segment(void); static uint16_t generate_led_data(uint8_t* buff, uint16_t start_index); static uint16_t fill_next_buffer(void); __RAM_CODE void ws2815_start_transfer(uint16_t len); extern void xc_spi_dma_init(uint8_t spi_idx, uint8_t dfs, uint8_t tdl, uint8_t rdl); extern uint32_t xc_spi_prf_data_addr(uint8_t spi_idx, uint8_t *eCode); #elif(WS2815_CONTROL_MODE == GPIO_DELAY_MODE) extern void xc_clock_set_osc32m_bbpll_64m(CLOCK_InitCfg_t *cb); extern void xc_clock_set_osc32m(CLOCK_InitCfg_t *cb); #endif /*------------------------------------------------------------------------------------ Functions -------------------------------------------------------------------------------------*/ #if(WS2815_CONTROL_MODE == SPI_DMA_MODE) __RAM_CODE DMA_Callback dma_listener_cb(uint8_t eCode) { DEBUG("\nERROR: DMA error! eCode:%d\n", eCode); return 0; } __RAM_CODE static uint16_t generate_led_data(uint8_t* buff, uint16_t start_index) { uint16_t buff_index = 0; uint16_t led_index = start_index; while (led_index < LED_TaskDef.RGB_XLED_NUM && buff_index < DMA_MAX_BLOCK_SIZE) {//修改 RGB_Color color = led_colors[led_index]; uint32_t grb = ((uint32_t)color.g << 16) | ((uint32_t)color.r << 8) | color.b; // 处理24位数据 (MSB优先) for (int8_t bit_pos = 23; bit_pos >= 0; bit_pos--) { buff[buff_index++] = (grb & (1 << bit_pos)) ? T1H : T0H; } led_index++; } // 更新当前LED索引 current_led_index = led_index; return buff_index; } __RAM_CODE static uint16_t fill_reset_data(uint8_t* buff) { uint16_t bytes_to_fill = (reset_bytes_remaining > DMA_MAX_BLOCK_SIZE) ? DMA_MAX_BLOCK_SIZE : reset_bytes_remaining; // 填充0x00作为复位信号 for (uint16_t i = 0; i < bytes_to_fill; i++) buff[i] = 0; // 更新剩余复位字节数 reset_bytes_remaining -= bytes_to_fill; return bytes_to_fill; } __RAM_CODE static uint16_t fill_next_buffer(void) { if (transfer_state == TRANSFER_LEDS) { // 填充LED数据 return generate_led_data(fill_buffer, current_led_index); } else if (transfer_state == TRANSFER_RESET) { // 填充复位数据 return fill_reset_data(fill_buffer); } return 0; } __RAM_CODE static void start_next_segment(void) { // 检查传输是否完成 if (transfer_state == TRANSFER_LEDS && current_led_index >= LED_TaskDef.RGB_XLED_NUM) {//修改 // 所有LED数据传输完成,切换到复位状态 transfer_state = TRANSFER_RESET; reset_bytes_remaining = RESET_BYTES; } if (transfer_state == TRANSFER_RESET && reset_bytes_remaining == 0) { transfer_state = TRANSFER_IDLE; } if (current_active_len == 0) { // 整个传输完成 dma_busy = 0; return; } // 启动DMA传输 ws2815_start_transfer(current_active_len); dma_busy = 1; // 填充下一个缓冲区 current_active_len = fill_next_buffer(); } __RAM_CODE void ws2815_trans_finish(uint8_t eCode) { // 交换缓冲区角色 uint8_t* temp = active_buffer; active_buffer = fill_buffer; fill_buffer = temp; // 继续传输 start_next_segment(); } /* spi初始化 */ void spi_init(uint8_t spix, uint16_t spi_tx_pin) { uint8_t spi_baud_div; SPI_InitCfg_t spi_cfg = { .Mode = SPI_MODE_MASTER, .DataSize = SSI_CTRL0_DFS_LEN_8BIT, .Direction = SSI_CTRL0_TMOD_W, .CLKPolarity = SSI_CTRL0_SCPOL_LOW, .CLKPhase = SSI_CTRL0_SCPHA_LEAD, .FirstBit = SPI_FirstBit_MSB, }; GPIO_InitCfg_t gpio_cfg = { .Mux = GPIO_Mux0, .Dir = GPIO_DIR_OUTPUT, .Int = NOT_INT, .Pull = GPIO_PULLDOWN, .Pin = GPIO_DUMMY, }; gpio_cfg.FunSel = SSI1_CLK; xc_gpio_init(&gpio_cfg); gpio_cfg.FunSel = SSI1_SSN; xc_gpio_init(&gpio_cfg); gpio_cfg.Dir = GPIO_DIR_INPUT; gpio_cfg.FunSel = SSI1_RX; xc_gpio_init(&gpio_cfg); gpio_cfg.FunSel = SSI1_TX; gpio_cfg.Pin = spi_tx_pin; if ((gpio_cfg.Pin == GPIO_11) || (gpio_cfg.Pin == GPIO_12) ||(gpio_cfg.Pin == GPIO_13)) gpio_cfg.Mux = GPIO_Mux1; xc_gpio_init(&gpio_cfg); spi_baud_div = (uint32_t)xc_clock_hfclk_in_get() / SPI_FREQUENCY; //printf("%s\tspi_baud_div:%d\n",__func__,spi_baud_div); spi_cfg.BaudRatePrescaler = spi_baud_div; xc_spi_init(spix, &spi_cfg); xc_spi_dma_init(spix, 0x07, 7, 7); } int dma_init(uint8_t spix, eDMA_Ch_Num dma_channel) { uint8_t errorCode = DMA_OK; uint32_t spi_prf_addr = xc_spi_prf_data_addr(spix, &errorCode); if (errorCode != DMA_OK) { return errorCode; } DMA_Chx_Cfg_t ch_cfg = { .sar = (uint32_t)buffer0, // 初始使用buffer0 .dar = spi_prf_addr, .ctl_src_msize = DMA_MSIZE_1, .ctl_dst_msize = DMA_MSIZE_1, .ctl_sinc = DMA_ADDR_INCREMENT, .ctl_dinc = DMA_ADDR_NOCHANGE, .ctl_src_tr_width = DMA_TRANS_WIDTH_8, .ctl_dst_tr_width = DMA_TRANS_WIDTH_8, .ctl_tt_fc = DMA_MEM2PRF_DMA, .cfg_hs_sel_src = DMA_HS_HARDWARE, .cfg_hs_sel_dst = DMA_HS_HARDWARE, .cfg_fifo_mode = DMA_FIFO_MODE_SINGLE, //.cfg_ch_prior = DMA_PRIORITY_0,//配置DMA中断优先级为0,即最高优先级 }; switch (spix) { case SPI1_IDX: { ch_cfg.cfg_dst_per = SSI1_DMA_TX_HS_IF3; } break; case SPI2_IDX: { ch_cfg.cfg_dst_per = SSI2_DMA_TX_HS_IF4; } break; default: { errorCode = DMA_EINVAL; return errorCode; } } errorCode = xc_dma_set_channel_config(dma_channel, &ch_cfg); if (errorCode != 0) { DEBUG("\nERROR: Failed to initialise configuration\n"); } xc_dma_init(); xc_dma_set_listener(dma_channel, (DMA_Callback)dma_listener_cb); xc_dma_enable(); NVIC_SetPriority(DMA_IRQn, 2); NVIC_EnableIRQ(DMA_IRQn); return errorCode; } __RAM_CODE void ws2815_start_transfer(uint16_t len) { uint8_t ch_index = xc_dma_get_channel_index(WS2815_DMA_CHANNEL); dma_ctl_h__block_ts__setf(ch_index, len); // 更新DMA源地址为当前活动缓冲区 dma_sar_set(ch_index, (uint32_t)active_buffer); xc_dma_start_transfer(WS2815_DMA_CHANNEL, (DMA_Callback)ws2815_trans_finish); } int WS2815_Init(void) { uint8_t errorCode = DMA_OK; spi_init(WS2815_SPI_IDX, WS2815_TX_PIN);//对spi进行初始化以及数据的输出引脚进行初始化 errorCode = dma_init(WS2815_SPI_IDX, WS2815_DMA_CHANNEL); WS2815_Clear(); return errorCode; } __RAM_CODE void WS2815_Update(void) { // 等待前一次传输完成 while (dma_busy); // 重置传输状态 current_led_index = 0; reset_bytes_remaining = 0; transfer_state = TRANSFER_LEDS; dma_busy = 1; // 填充第一个缓冲区 uint16_t active_len = generate_led_data(active_buffer, current_led_index); // 仅当还有剩余数据时才填充第二个缓冲区 if (current_led_index < LED_TaskDef.RGB_XLED_NUM) {//修改 current_active_len = fill_next_buffer(); }else{ current_active_len = RESET_BYTES; } // 启动第一个DMA传输 ws2815_start_transfer(active_len); } /* __RAM_CODE void WS2815_Update(void) {*/ /* * 关键优化点: * 1. 去除不必要的原子操作 * 2. 优化变量访问顺序 * 3. 简化控制流程 * 4. 确保DMA传输的可靠性 */ /* // 1. 等待DMA完成(紧凑循环) while(dma_busy) { rwip_schedule(); __NOP(); } // 使用NOP防止编译器优化掉空循环 // 2. 批量初始化状态变量(减少内存写入次数) current_led_index = 0; reset_bytes_remaining = 0; transfer_state = TRANSFER_LEDS; dma_busy = 1; // 在最后设置busy标志 // 3. 合并缓冲区填充逻辑 uint16_t active_len = generate_led_data(active_buffer, current_led_index); current_active_len = (current_led_index < LEDS_NUM) ? fill_next_buffer() : RESET_BYTES; // 4. 确保内存写入完成后再启动DMA __DSB(); // 数据同步屏障 // 5. 启动DMA传输 ws2815_start_transfer(active_len); } */ #elif(WS2815_CONTROL_MODE == GPIO_DELAY_MODE) static void gpio_nrz_init(void) { GPIO_InitCfg_t GPIO_InitCfg = { 0 }; GPIO_InitCfg.Mux = GPIO_Mux0; GPIO_InitCfg.FunSel = GPIO_Dx; GPIO_InitCfg.Pull = GPIO_NOPULL; GPIO_InitCfg.Dir = GPIO_DIR_OUTPUT; GPIO_InitCfg.Int = NOT_INT; GPIO_InitCfg.Pin = WS2815_TX_PIN; if ((GPIO_InitCfg.Pin == GPIO_11) || (GPIO_InitCfg.Pin == GPIO_12) ||(GPIO_InitCfg.Pin == GPIO_13)) GPIO_InitCfg.Mux = GPIO_Mux1; xc_gpio_init(&GPIO_InitCfg); xc_gpio_write_pin(GPIO_InitCfg.Pin, GPIO_PIN_RESET); } __INLINE void gpio_nrz_0(void) { WS2815_GPIO_PIN_HIGH; for (uint8_t i = 0; i < 1; i++) { __NOP(); } WS2815_GPIO_PIN_LOW; for (uint8_t i = 0; i < 6; i++) { __NOP(); } } __INLINE void gpio_nrz_1(void) { WS2815_GPIO_PIN_HIGH; for (uint8_t i = 0; i < 7; i++) { __NOP(); } WS2815_GPIO_PIN_LOW; } __RAM_CODE static void send_led_data(void) { // 临时切换到64MHz时钟以确保时序精确 CLOCK_InitCfg_t *pclock_cb = &clock_cb; uint32_t orig_clock = xc_clock_hfclk_in_get(); if (orig_clock < 64000000) { xc_clock_set_osc32m_bbpll_64m(pclock_cb); } __disable_irq(); // 发送所有LED数据 for (uint16_t i = 0; i < LEDS_NUM; i++) { RGB_Color color = led_colors[i]; uint32_t grb = ((uint32_t)color.g << 16) | ((uint32_t)color.r << 8) | color.b; // 发送24位数据 (MSB优先) for (int8_t bit_pos = 23; bit_pos >= 0; bit_pos--) { if (grb & (1 << bit_pos)) { gpio_nrz_1(); } else { gpio_nrz_0(); } } } __enable_irq(); // 恢复原始时钟 if (orig_clock < 64000000) { #if (CONFIG_HFCLK_IS_OSC32M_PLL_32M) xc_clock_set_osc32m_bbpll_32m(pclock_cb); #else xc_clock_set_osc32m(pclock_cb); #endif } } int WS2815_Init(void) { gpio_nrz_init(); WS2815_Clear(); return 0; } __RAM_CODE void WS2815_Update(void) { send_led_data(); } #endif //WS2815_CONTROL_MODE == GPIO_DELAY_MODE void WS2815_SetColor(uint16_t led_num, RGB_Color color) { if (led_num < LED_TaskDef.RGB_XLED_NUM) {//修改 led_colors[led_num] = color; } } void WS2815_SetAll(RGB_Color color) { for (uint16_t i = 0; i < LED_TaskDef.RGB_XLED_NUM; i++) {//修改 led_colors[i] = color; } } void WS2815_Clear(void) { RGB_Color black = {0, 0, 0}; WS2815_SetAll(black); } #define CHASE_SPEED_MS 30 // 跑马灯移动速度(毫秒) //SDK的WS2815灯效的DEMO /* void WS2815_demo(void) { // 初始化LED驱动 if(WS2815_Init() != DMA_OK) { DEBUG("WS2815 Init Failed!\n"); return; } // 定义颜色 RGB_Color red = {255, 0, 0}; RGB_Color green = {0, 255, 0}; RGB_Color blue = {0, 0, 255}; RGB_Color yellow = {255, 150, 0}; RGB_Color purple = {180, 0, 255}; // 彩色光点数组(彩虹色序列) RGB_Color chase_colors[] = { green, red, blue, yellow, purple }; const uint8_t num_colors = sizeof(chase_colors) / sizeof(chase_colors[0]); // 尾巴长度(光点后面的拖尾效果) const uint8_t tail_length = 8; while(1) { //xc_wdt_reload(); // 循环所有彩色光点 for(uint8_t color_idx = 0; color_idx < num_colors; color_idx++) { // 光点从0到末尾移动 for(uint16_t pos = 0; pos < LEDS_NUM + tail_length; pos++) { // 清除所有LED WS2815_Clear(); // 绘制光点拖尾 uint8_t intensity = 255; for(int i = 0; i < tail_length; i++) { if(pos - i < LEDS_NUM && pos - i >= 0) { // 拖尾颜色渐变(越远越暗) RGB_Color tail_color = chase_colors[color_idx]; tail_color.r = (uint8_t)(tail_color.r * intensity / 255); tail_color.g = (uint8_t)(tail_color.g * intensity / 255); tail_color.b = (uint8_t)(tail_color.b * intensity / 255); WS2815_SetColor(pos - i, tail_color); intensity = (uint8_t)(intensity * 0.7); // 每节拖尾亮度递减 } } // 绘制主光点(最亮) if(pos < LEDS_NUM) { WS2815_SetColor(pos, chase_colors[color_idx]); } // 更新显示 WS2815_Update(); // 控制速度 delay_ms(CHASE_SPEED_MS); DEBUG("1\n"); DEBUG("color_idx:%d\n",color_idx); } } //xc_wdt_reload(); DEBUG("RETURN_2\n"); // 反向移动 for(uint8_t color_idx = 0; color_idx < num_colors; color_idx++) { // 光点从末尾到0移动 for(int pos = LEDS_NUM - 1; pos >= - tail_length; pos--) { WS2815_Clear(); uint8_t intensity = 255;//亮度 for(int i = 0; i < tail_length; i++) { if(pos + i < LEDS_NUM && pos + i >= 0) { RGB_Color tail_color = chase_colors[color_idx]; tail_color.r = (uint8_t)(tail_color.r * intensity / 255); tail_color.g = (uint8_t)(tail_color.g * intensity / 255); tail_color.b = (uint8_t)(tail_color.b * intensity / 255); WS2815_SetColor(pos + i, tail_color); intensity = (uint8_t)(intensity * 0.7); } } if(pos >= 0) { WS2815_SetColor(pos, chase_colors[color_idx]); } WS2815_Update(); delay_ms(CHASE_SPEED_MS); DEBUG("return_finish\n"); DEBUG("color_idx:%d\n",color_idx); } } } } */ /* * * 以下为数据处理相关函数 * */ RGB_Color Data_24_To_RGB_Color(uint32_t Old_Data,uint8_t intensity){ RGB_Color Temp; Temp.b = (uint8_t)(((Old_Data&0xff0000)>>16)*intensity/100); Temp.g = (uint8_t)(((Old_Data&0xff00)>>8)*intensity/100); Temp.r = (uint8_t)((Old_Data&0xff)*intensity/100); //DEBUG("Data Conversion\n"); return Temp; } void ws2815_xledc(uint8_t display_format,uint32_t xLED_color,uint16_t xLED, uint8_t Brightness) { RGB_Color Rev; RGB_Color temp = Data_24_To_RGB_Color(ws2815_rgb_color_format_conversion(xLED_color,display_format),Brightness); Rev.r = temp.r; Rev.g = temp.g; Rev.b = temp.b; WS2815_SetColor(xLED,Rev); } void ledc_dma_kick(uint32_t addr, uint16_t len) { WS2815_Update(); } /** * @brief 将数据转换成4字节 * @retval None */ void ws2815_rgb_color_out_32to24bit_code_fill(uint32_t buf_code_grb[], uint32_t buf_grb[]) { } /** * @brief 转换像素点数据格式 * @retval None */ static uint32_t ws2815_rgb_color_format_conversion(uint32_t display_color,unsigned char display_format) { uint32_t color_temp = 0; switch (display_format) { case LEDC_BRG://实际测试ws2815输出为GRB格式,数据为小端格式,bit0-bit7对应B,bit8-bit15对应R,bit16-bit23对应G color_temp = display_color; display_color &= 0x000000; //brg display_color |= ((color_temp & 0xff0000) >> 8);//0g display_color |= ((color_temp & 0x00ff00) << 8);//0r display_color |= (color_temp & 0x0000ff);//FF b break; case LEDC_BGR://实际测试ws2815输出为RGB格式,数据为小端格式,bit0-bit7对应B,bit8-bit15对应R,bit16-bit23对应G //格式一致,无需转换 bgr break; case LEDC_GRB://实际测试ws2815输出为BRG格式,数据为小端格式,bit0-bit7对应B,bit8-bit15对应R,bit16-bit23对应G color_temp = display_color;//rbg display_color &= 0x000000; display_color |= ((color_temp & 0xff0000) >> 8);//g display_color |= ((color_temp & 0x00ff00) >> 8);//b display_color |= ((color_temp & 0x0000ff) << 16);//r break; case LEDC_GBR://实际测试ws2815输出为RBG格式,数据为小端格式,bit0-bit7对应B,bit8-bit15对应R,bit16-bit23对应G color_temp = display_color; display_color &= 0x000000;//gbr display_color |= (color_temp & 0xff0000);//r display_color |= ((color_temp & 0x00ff00) >> 8);//b display_color |= ((color_temp & 0x0000ff) << 8);//g break; case LEDC_RBG://实际测试ws2815输出为BGR格式,数据为小端格式,bit0-bit7对应B,bit8-bit15对应R,bit16-bit23对应G color_temp = display_color; display_color &= 0x000000;//grb display_color |= ((color_temp & 0xff0000) >> 16);//b display_color |= ((color_temp & 0x00ff00) << 8);//r display_color |= ((color_temp & 0x0000ff) << 8);//g break; case LEDC_RGB://实际测试ws2815输出为RGB格式,数据为小端格式,bit0-bit7对应B,bit8-bit15对应R,bit16-bit23对应G color_temp = display_color; display_color &= 0x000000;//rgb display_color |= ((color_temp & 0xff0000) >> 16);//b display_color |= (color_temp & 0x00ff00);//g display_color |= ((color_temp & 0x0000ff) << 16);//r break; } return display_color; } /* ** ** 以下为项目的灯效函数 ** */ /** * @brief 初始化LEDdeftask数据 * @retval None */ void ledc_Taskdef_init(void) { LED_TaskDef.CURRENT_TASK = 2; //mode LED_TaskDef.ledc_fill_state = 0; LED_TaskDef.ledc_kick_state = 0; //空闲 LED_TaskDef.LEDC_TICK_Speed = 150; //10ms*tick LED_TaskDef.LED_Brightne = 50; //亮度 LED_TaskDef.LED_SWITCH = 1; //开启 LED_TaskDef.RGB_CODE_LEN = 0; LED_TaskDef.RGB_XLED_NUM = 100; //像素点 LED_TaskDef.Timer_count = 0; LED_TaskDef.Temp_Step = 0; LED_TaskDef.xianxu = LEDC_BRG; //线序 } /** * @brief mode0 全灯亮.单色全亮 * @param LED_Maincolor: 颜色. * @retval None */ void ws2815_ledc_show(uint8_t display_format,uint32_t LED_Maincolor) { //printf("LED_SWITCH = %x\n", LED_TaskDef.LED_SWITCH); if (!LED_TaskDef.LED_SWITCH) { return; } uint16_t i = 0; //空闲状态 if (LED_TaskDef.ledc_kick_state == 0) { //printf("CURRENT_TASK = %x\n", LED_TaskDef.CURRENT_TASK); //printf("LEDC_TICK_Speed = %d\n", LED_TaskDef.LEDC_TICK_Speed); //printf("RGB_XLED_NUM = %x\n", LED_TaskDef.RGB_XLED_NUM); //printf("LED_Brightne = %.2f\n", LED_TaskDef.LED_Brightne); //全灯赋值 for(i=0;i LED_TaskDef.RGB_XLED_NUM){ LED_TaskDef.ledc_fill_state = 0; } else { ws2815_xledc(display_format,LED_Maincolor,LED_TaskDef.ledc_fill_state,LED_TaskDef.LED_Brightne); LED_TaskDef.ledc_fill_state++; } //其他灯赋值 for(i=0;i 255) final_brightness = 255; else if (final_brightness < 5) final_brightness = 5; final_brightness = final_brightness*100/255; // 调用LED设置函数 ws2815_xledc(display_format, rainbow[color_index], i, final_brightness); } // 更新流动状态(确保无限循环) LED_TaskDef.ledc_fill_state = (LED_TaskDef.ledc_fill_state + 1) % mod_factor; // 生成DMA数据 //ws2815_rgb_color_out_32to24bit_code_fill(&code_buf[0], &color_buf[0]); // DMA传输(考虑不同灯珠数量的情况) if(LED_TaskDef.RGB_XLED_NUM % 4 == 1) { ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN + 1); } else { ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN); } // 设置为忙碌状态 LED_TaskDef.ledc_kick_state = 1; } } /** * @brief mode4 七彩跳变/能量. * @param . * @retval None */ void ws2815_ledc_multjumpshow(uint8_t display_format) { if (!LED_TaskDef.LED_SWITCH) { return; } uint16_t i = 0; //空闲状态 if (LED_TaskDef.ledc_kick_state == 0) { //printf("CURRENT_TASK = %x\n", LED_TaskDef.CURRENT_TASK); //printf("DMA_CODE_LEN = %x\n", LED_TaskDef.RGB_CODE_LEN); //printf("RGB_XLED_NUM = %x\n", LED_TaskDef.RGB_XLED_NUM); //printf("LED_Brightne = %.2f\n", LED_TaskDef.LED_Brightne); if(LED_TaskDef.ledc_fill_state > 6){ LED_TaskDef.ledc_fill_state = 0; } //全灯赋值 for(i=0;i 13){ LED_TaskDef.ledc_fill_state = 0; } if(LED_TaskDef.ledc_fill_state % 2 == 0){ //全灯赋值 七彩 for(i=0;i 5){ LED_TaskDef.ledc_fill_state = 0; } if(LED_TaskDef.ledc_fill_state % 2 == 0){//0 2 4 //全灯赋值 三色 for(i=0;i 20) { current_brightness = 20; // 达到0%亮度 current_color = (current_color + 1) % 7; // 切换颜色 brightness_direction = -1; // 重置为亮度增加方向 } } //判断使能DMA发送 if(LED_TaskDef.RGB_XLED_NUM%4 == 1){ ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN+1); } else{ ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN); } //忙碌状态 LED_TaskDef.ledc_kick_state = 1; } } /** * @brief mode11-16 双色交替渐变. * @param 速度50ms最佳. * @retval None */ void ws2815_ledc_secondalternategradient(uint8_t display_format,uint32_t colors[]) { if (!LED_TaskDef.LED_SWITCH) { return; } //空闲状态 if (LED_TaskDef.ledc_kick_state == 0) { //LED_TaskDef.LEDC_TICK_Speed = 100; //ms // 定义彩虹颜色数组 static uint8_t current_color = 0; // 当前颜色索引(0-1) static int8_t brightness_direction = -1; // 亮度变化方向(-1:增加, 1:减少) static int8_t current_brightness = 10; // 当前亮度级别索引(0%) // 计算实际亮度值 float brightness = (brightness_table3[current_brightness] / 255.0f) * LED_TaskDef.LED_Brightne; // 设置当前颜色的当前亮度 for (uint16_t i = 0; i < LED_TaskDef.RGB_XLED_NUM; i++) { ws2815_xledc(display_format, colors[current_color], i, brightness); } // 更新亮度级别 current_brightness += brightness_direction; // 切换方向或更换颜色 if (brightness_direction < 0) { // 亮度增加过程 if (current_brightness < 0) { current_brightness = 0; // 达到100%亮度 brightness_direction = 1; // 开始降低亮度 } } else { // 亮度减少过程 if (current_brightness > 10) { current_brightness = 10; // 达到0%亮度 current_color = (current_color + 1) % 2; // 切换颜色 brightness_direction = -1; // 重置为亮度增加方向 } } //判断使能DMA发送 if(LED_TaskDef.RGB_XLED_NUM%4 == 1){ ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN+1); } else{ ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN); } //忙碌状态 LED_TaskDef.ledc_kick_state = 1; } } /** * @brief mode17-22 单色跑马. * @param . * @retval None */ void ws2815_ledc_singleridehorse(uint8_t display_format,uint32_t colors) { if (!LED_TaskDef.LED_SWITCH) { return; } //空闲状态 if (LED_TaskDef.ledc_kick_state == 0) { // 设置所有LED的颜色 for (uint16_t i = 0; i < LED_TaskDef.RGB_XLED_NUM; i++) { // 奇数位置灯亮,偶数位置灯灭 // 偶数位置灯亮,奇数位置灯灭 if ((i % 2) == LED_TaskDef.ledc_fill_state) { // 亮灯状态 ws2815_xledc(display_format, colors, i, LED_TaskDef.LED_Brightne); } else { // 灭灯状态 ws2815_xledc(display_format, Color_BLACK, i, LED_TaskDef.LED_Brightne); } } // 更新状态 LED_TaskDef.ledc_fill_state = LED_TaskDef.ledc_fill_state ? 0 : 1; //判断使能DMA发送 if(LED_TaskDef.RGB_XLED_NUM%4 == 1){ ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN+1); } else{ ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN); } //忙碌状态 LED_TaskDef.ledc_kick_state = 1; } } /** * @brief mode23-24 七彩追光. * @param direction: 方向. * @retval 0 = 反向 , 1 = 正向 * @note speed50ms最佳 */ void ws2815_ledc_multspotlight(uint8_t display_format,uint8_t direction) { if (!LED_TaskDef.LED_SWITCH) { return; } //空闲状态 if (LED_TaskDef.ledc_kick_state == 0) { static uint8_t led_index = 0; // 当前灯颜色索引 static uint8_t last_led_index = 6; // 上一次灯颜色索引 // 正向追光 if (direction == 1) { for (uint16_t i = 0; i < LED_TaskDef.RGB_XLED_NUM; i++) { if (i < LED_TaskDef.ledc_fill_state) { ws2815_xledc(display_format, rainbow[led_index], i, LED_TaskDef.LED_Brightne); } else { ws2815_xledc(display_format, rainbow[last_led_index], i, LED_TaskDef.LED_Brightne); } } } // 反向追光 else if (direction == 0) { uint16_t reverse_active = LED_TaskDef.RGB_XLED_NUM - LED_TaskDef.ledc_fill_state; for (uint16_t i = 0; i < LED_TaskDef.RGB_XLED_NUM; i++) { if (i >= reverse_active) { ws2815_xledc(display_format, rainbow[led_index], i, LED_TaskDef.LED_Brightne); } else { ws2815_xledc(display_format, rainbow[last_led_index], i, LED_TaskDef.LED_Brightne); } } } LED_TaskDef.ledc_fill_state++; // 超出灯数,重置状态并切换到下一个颜色 if (LED_TaskDef.ledc_fill_state > LED_TaskDef.RGB_XLED_NUM) { LED_TaskDef.ledc_fill_state = 0; last_led_index = led_index; led_index = (led_index + 1) % 7; // 循环使用彩虹色 } //判断使能DMA发送 if(LED_TaskDef.RGB_XLED_NUM%4 == 1){ ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN+1); } else{ ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN); } //忙碌状态 LED_TaskDef.ledc_kick_state = 1; } } /** * @brief mode25-28 三色追光. * @param direction: 方向. * @retval 0 = 反向 , 1 = 正向 * @note speed50ms最佳 */ void ws2815_ledc_threespotlight(uint8_t display_format,uint8_t direction,uint32_t colors[]) { if (!LED_TaskDef.LED_SWITCH) { return; } //空闲状态 if (LED_TaskDef.ledc_kick_state == 0) { //printf("CURRENT_TASK = %x\n", LED_TaskDef.CURRENT_TASK); //printf("DMA_CODE_LEN = %x\n", LED_TaskDef.RGB_CODE_LEN); //printf("RGB_XLED_NUM = %x\n", LED_TaskDef.RGB_XLED_NUM); //printf("LED_Brightne = %.2f\n", LED_TaskDef.LED_Brightne); static uint8_t led_index = 0; // 当前灯颜色索引 static uint8_t last_led_index = 2; // 上一次灯颜色索引 // 正向追光 if (direction == 1) { for (uint16_t i = 0; i < LED_TaskDef.RGB_XLED_NUM; i++) { if (i < LED_TaskDef.ledc_fill_state) { ws2815_xledc(display_format, colors[led_index], i, LED_TaskDef.LED_Brightne); } else { ws2815_xledc(display_format, colors[last_led_index], i, LED_TaskDef.LED_Brightne); } } } // 反向追光 else if (direction == 0) { uint16_t reverse_active = LED_TaskDef.RGB_XLED_NUM - LED_TaskDef.ledc_fill_state; for (uint16_t i = 0; i < LED_TaskDef.RGB_XLED_NUM; i++) { if (i >= reverse_active) { ws2815_xledc(display_format, colors[led_index], i, LED_TaskDef.LED_Brightne); } else { ws2815_xledc(display_format, colors[last_led_index], i, LED_TaskDef.LED_Brightne); } } } LED_TaskDef.ledc_fill_state++; // 超出灯数,重置状态并切换到下一个颜色 if (LED_TaskDef.ledc_fill_state > LED_TaskDef.RGB_XLED_NUM) { LED_TaskDef.ledc_fill_state = 0; last_led_index = led_index; led_index = (led_index + 1) % 3; } //ws2815_rgb_color_out_32to24bit_code_fill(&code_buf[0],&color_buf[0]); //判断使能DMA发送 if(LED_TaskDef.RGB_XLED_NUM%4 == 1){ ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN+1); } else{ ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN); } //忙碌状态 LED_TaskDef.ledc_kick_state = 1; } } /** * @brief mode29-30 七色飘动. * @param direction: 方向. * @retval 0 = 反向 , 1 = 正向 * @note speed200ms最佳 */ void ws2815_multfloatlight(uint8_t display_format,uint8_t direction) { if (!LED_TaskDef.LED_SWITCH) { return; } //空闲状态 if (LED_TaskDef.ledc_kick_state == 0) { //printf("CURRENT_TASK = %x\n", LED_TaskDef.CURRENT_TASK); //printf("DMA_CODE_LEN = %x\n", LED_TaskDef.RGB_CODE_LEN); //printf("RGB_XLED_NUM = %x\n", LED_TaskDef.RGB_XLED_NUM); //printf("LED_Brightne = %.2f\n", LED_TaskDef.LED_Brightne); if(direction==0){//反向流动 for(uint16_t i = 0; i < LED_TaskDef.RGB_XLED_NUM; i++) { uint8_t color_index = (i + LED_TaskDef.ledc_fill_state) % 7; ws2815_xledc(display_format, rainbow[color_index], i,LED_TaskDef.LED_Brightne); } } else if(direction==1){//正向流动 for(uint16_t i = 0; i < LED_TaskDef.RGB_XLED_NUM; i++) { int16_t position = LED_TaskDef.RGB_XLED_NUM - LED_TaskDef.ledc_fill_state + i; uint8_t color_index = position % 7; ws2815_xledc(display_format, rainbow[color_index], i,LED_TaskDef.LED_Brightne); } } LED_TaskDef.ledc_fill_state = (LED_TaskDef.ledc_fill_state + 1) % LED_TaskDef.RGB_XLED_NUM; //ws2815_rgb_color_out_32to24bit_code_fill(&code_buf[0],&color_buf[0]); //判断使能DMA发送 if(LED_TaskDef.RGB_XLED_NUM%4 == 1){ ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN+1); } else{ ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN); } //忙碌状态 LED_TaskDef.ledc_kick_state = 1; } } /** * @brief mode31-34 三色飘动. * @param direction: 方向. * @retval 0 = 反向 , 1 = 正向 * @note speed200ms最佳 */ void ws2815_threefloatlight(uint8_t display_format,uint8_t direction,uint32_t colors[]) { if (!LED_TaskDef.LED_SWITCH) { return; } //空闲状态 if (LED_TaskDef.ledc_kick_state == 0) { //printf("CURRENT_TASK = %x\n", LED_TaskDef.CURRENT_TASK); //printf("DMA_CODE_LEN = %x\n", LED_TaskDef.RGB_CODE_LEN); //printf("RGB_XLED_NUM = %x\n", LED_TaskDef.RGB_XLED_NUM); //printf("LED_Brightne = %.2f\n", LED_TaskDef.LED_Brightne); if(direction==0){//反向流动 for(uint16_t i = 0; i < LED_TaskDef.RGB_XLED_NUM; i++) { uint8_t color_index = (i + LED_TaskDef.ledc_fill_state) % 3; ws2815_xledc(display_format, colors[color_index], i,LED_TaskDef.LED_Brightne); } } else if(direction==1){//正向流动 for(uint16_t i = 0; i < LED_TaskDef.RGB_XLED_NUM; i++) { int16_t position = LED_TaskDef.RGB_XLED_NUM - LED_TaskDef.ledc_fill_state + i; uint8_t color_index = position % 3; ws2815_xledc(display_format, colors[color_index], i,LED_TaskDef.LED_Brightne); } } LED_TaskDef.ledc_fill_state = (LED_TaskDef.ledc_fill_state + 1) % LED_TaskDef.RGB_XLED_NUM; //ws2815_rgb_color_out_32to24bit_code_fill(&code_buf[0],&color_buf[0]); //判断使能DMA发送 if(LED_TaskDef.RGB_XLED_NUM%4 == 1){ ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN+1); } else{ ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN); } //忙碌状态 LED_TaskDef.ledc_kick_state = 1; } } /** * @brief mode35-36 七彩刷色. * @param direction: 方向. * @retval 0 = 反向 , 1 = 正向 * @note speed100ms最佳 */ void ws2815_multbrushcolor(uint8_t display_format,uint8_t direction) { if (!LED_TaskDef.LED_SWITCH) { return; } // 空闲状态 if (LED_TaskDef.ledc_kick_state == 0) { // 调试信息 //printf("CURRENT_TASK = %x\n", LED_TaskDef.CURRENT_TASK); //printf("DMA_CODE_LEN = %x\n", LED_TaskDef.RGB_CODE_LEN); //printf("RGB_XLED_NUM = %x\n", LED_TaskDef.RGB_XLED_NUM); //printf("LED_Brightne = %.2f\n", LED_TaskDef.LED_Brightne); uint16_t num_leds = LED_TaskDef.RGB_XLED_NUM; static uint8_t color_index = 0; // 当前颜色索引 static uint8_t frame_count = 0; // 帧计数器 static uint8_t cover_step = 0; // 覆盖步数 static uint8_t flash_state = 0; // 闪烁状态(0或1) static uint8_t before_color = 6; // 正向上一个颜色 // 更新闪烁状态(每帧切换) flash_state = !flash_state; // 正向刷色效果 if (direction == 1) { // 设置所有灯的颜色 for (uint16_t i = 0; i < num_leds; i++) { // 根据灯的位置和帧计数确定颜色 if ((i % 2) == ((cover_step % 2) ^ flash_state)) { ws2815_xledc(display_format, rainbow[before_color], i, LED_TaskDef.LED_Brightne); // 上一个颜色 } else { ws2815_xledc(display_format, rainbow[color_index], i, LED_TaskDef.LED_Brightne); // 当前颜色 } } // 对于已经被覆盖的灯,设置为当前颜色 for (uint16_t i = 0; i < cover_step; i++) { // 覆盖灯(每组两个灯) uint16_t pos1 = i * 2; uint16_t pos2 = i * 2 + 1; if (pos1 < num_leds) { ws2815_xledc(display_format, rainbow[color_index], pos1, LED_TaskDef.LED_Brightne); } if (pos2 < num_leds) { ws2815_xledc(display_format, rainbow[color_index], pos2, LED_TaskDef.LED_Brightne); } } // 更新帧计数器 frame_count++; // 每两帧推进一次覆盖进度 if (frame_count % 2 == 0) { cover_step++; // 检查是否完成当前颜色的覆盖 if (cover_step > num_leds / 2) { cover_step = 0; before_color = color_index; color_index = (color_index + 1) % 7; // 切换到下一个颜色 } } } // 反向刷色效果 else if (direction == 0) { // 首先将所有灯设置为当前颜色 for (uint16_t i = 0; i < num_leds; i++) { ws2815_xledc(display_format, rainbow[color_index], i, LED_TaskDef.LED_Brightne); } // 计算前一个颜色索引(彩虹数组中的前一个颜色) uint8_t prev_color_index = (color_index + 6) % 7; // 彩虹数组中的前一个颜色 // 计算开始位置(从尾部向前) uint16_t start_pos = num_leds - 2 * cover_step; // 设置尾部交替闪烁 for (uint16_t i = start_pos; i < num_leds; i++) { // 从尾部开始位置计算偏移量 uint16_t offset = num_leds - 1 - i; // 根据闪烁状态决定颜色 if ((offset % 2) == flash_state) { ws2815_xledc(display_format, rainbow[color_index], i, LED_TaskDef.LED_Brightne); // 当前颜色 } else { ws2815_xledc(display_format, rainbow[prev_color_index], i, LED_TaskDef.LED_Brightne); // 前一个颜色 } } // 更新帧计数器 frame_count++; // 每两帧推进一次覆盖进度 if (frame_count % 2 == 0) { cover_step++; // 检查是否完成当前颜色的覆盖 if (cover_step > num_leds / 2) { cover_step = 0; color_index = (color_index + 1) % 7; // 切换到下一个颜色 } } } // 准备DMA数据 //ws2815_rgb_color_out_32to24bit_code_fill(&code_buf[0], &color_buf[0]); // 判断使能DMA发送 if (num_leds % 4 == 1) { ledc_dma_kick((uint32_t)&code_buf[0], LED_TaskDef.RGB_CODE_LEN + 1); } else { ledc_dma_kick((uint32_t)&code_buf[0], LED_TaskDef.RGB_CODE_LEN); } // 标记忙碌状态 LED_TaskDef.ledc_kick_state = 1; } } /** * @brief mode37-40 三色刷色. * @param direction: 方向. * @retval 0 = 反向 , 1 = 正向 * @note speed100ms最佳 */ void ws2815_threebrushcolor(uint8_t display_format,uint8_t direction,uint32_t colors[]) { if (!LED_TaskDef.LED_SWITCH) { return; } // 空闲状态 if (LED_TaskDef.ledc_kick_state == 0) { // 调试信息 //printf("CURRENT_TASK = %x\n", LED_TaskDef.CURRENT_TASK); //printf("DMA_CODE_LEN = %x\n", LED_TaskDef.RGB_CODE_LEN); //printf("RGB_XLED_NUM = %x\n", LED_TaskDef.RGB_XLED_NUM); //printf("LED_Brightne = %.2f\n", LED_TaskDef.LED_Brightne); uint16_t num_leds = LED_TaskDef.RGB_XLED_NUM; static uint8_t color_index = 0; // 当前颜色索引 static uint8_t frame_count = 0; // 帧计数器 static uint8_t cover_step = 0; // 覆盖步数 static uint8_t flash_state = 0; // 闪烁状态(0或1) static uint8_t before_color = 2; // 正向上一个颜色 // 更新闪烁状态(每帧切换) flash_state = !flash_state; // 正向刷色效果 if (direction == 1) { // 设置所有灯的颜色 for (uint16_t i = 0; i < num_leds; i++) { // 根据灯的位置和帧计数确定颜色 if ((i % 2) == ((cover_step % 2) ^ flash_state)) { ws2815_xledc(display_format, colors[before_color], i, LED_TaskDef.LED_Brightne); // 上一个颜色 } else { ws2815_xledc(display_format, colors[color_index], i, LED_TaskDef.LED_Brightne); // 当前颜色 } } // 对于已经被覆盖的灯,设置为当前颜色 for (uint16_t i = 0; i < cover_step; i++) { // 覆盖灯(每组两个灯) uint16_t pos1 = i * 2; uint16_t pos2 = i * 2 + 1; if (pos1 < num_leds) { ws2815_xledc(display_format, colors[color_index], pos1, LED_TaskDef.LED_Brightne); } if (pos2 < num_leds) { ws2815_xledc(display_format, colors[color_index], pos2, LED_TaskDef.LED_Brightne); } } // 更新帧计数器 frame_count++; // 每两帧推进一次覆盖进度 if (frame_count % 2 == 0) { cover_step++; // 检查是否完成当前颜色的覆盖 if (cover_step > num_leds / 2) { cover_step = 0; before_color = color_index; color_index = (color_index + 1) % 3; // 切换到下一个颜色 } } } // 反向刷色效果 else if (direction == 0) { // 首先将所有灯设置为当前颜色 for (uint16_t i = 0; i < num_leds; i++) { ws2815_xledc(display_format, colors[color_index], i, LED_TaskDef.LED_Brightne); } // 计算前一个颜色索引(彩虹数组中的前一个颜色) uint8_t prev_color_index = (color_index + 2) % 3; // 彩虹数组中的前一个颜色 // 计算开始位置(从尾部向前) uint16_t start_pos = num_leds - 2 * cover_step; // 设置尾部交替闪烁 for (uint16_t i = start_pos; i < num_leds; i++) { // 从尾部开始位置计算偏移量 uint16_t offset = num_leds - 1 - i; // 根据闪烁状态决定颜色 if ((offset % 2) == flash_state) { ws2815_xledc(display_format, colors[color_index], i, LED_TaskDef.LED_Brightne); // 当前颜色 } else { ws2815_xledc(display_format, colors[prev_color_index], i, LED_TaskDef.LED_Brightne); // 前一个颜色 } } // 更新帧计数器 frame_count++; // 每两帧推进一次覆盖进度 if (frame_count % 2 == 0) { cover_step++; // 检查是否完成当前颜色的覆盖 if (cover_step > num_leds / 2) { cover_step = 0; color_index = (color_index + 1) % 3; // 切换到下一个颜色 } } } // 准备DMA数据 //ws2815_rgb_color_out_32to24bit_code_fill(&code_buf[0], &color_buf[0]); // 判断使能DMA发送 if (num_leds % 4 == 1) { ledc_dma_kick((uint32_t)&code_buf[0], LED_TaskDef.RGB_CODE_LEN + 1); } else { ledc_dma_kick((uint32_t)&code_buf[0], LED_TaskDef.RGB_CODE_LEN); } // 标记忙碌状态 LED_TaskDef.ledc_kick_state = 1; } } /** * @brief mode41 七彩刷色闭幕. * @param * @retval * @note speed100ms最佳 */ void ws2815_multbrushclosing(uint8_t display_format) { if (!LED_TaskDef.LED_SWITCH) { return; } // 空闲状态 if (LED_TaskDef.ledc_kick_state == 0) { //printf("CURRENT_TASK = %x\n", LED_TaskDef.CURRENT_TASK); //printf("DMA_CODE_LEN = %x\n", LED_TaskDef.RGB_CODE_LEN); //printf("RGB_XLED_NUM = %x\n", LED_TaskDef.RGB_XLED_NUM); //printf("LED_Brightne = %.2f\n", LED_TaskDef.LED_Brightne); uint16_t num_leds = LED_TaskDef.RGB_XLED_NUM; static uint8_t base_color_index = 0; // 基色索引(当前主要颜色) static uint8_t flash_color_index1 = 1; // 第一个闪烁颜色索引 static uint16_t step = 0; // 覆盖步数 static uint8_t flash_state = 0; // 闪烁状态(0或1) static uint8_t frame_count = 0; // 帧计数器 // 更新闪烁状态(每次调用翻转) flash_state = !flash_state; // 获取当前基色和闪烁颜色 uint32_t base_color = rainbow[base_color_index]; uint32_t flash_color1 = rainbow[flash_color_index1]; // 计算最大步数(从两边向中间推进) uint16_t max_steps = (num_leds + 1) / 2; // 中间点位置 // 1. 设置整个灯带为基色 for (uint16_t i = 0; i < num_leds; i++) { if ((i % 2) == ((step % 2))) { ws2815_xledc(display_format, base_color, i, LED_TaskDef.LED_Brightne); // 上一个颜色 } else { ws2815_xledc(display_format, flash_color1, i, LED_TaskDef.LED_Brightne); // 当前颜色 } } // 2. 在覆盖区域设置闪烁颜色(从头尾向中间推进) for (uint16_t s = 0; s <= step; s++) { // 计算左右覆盖位置(从头尾向中间推进) int16_t left_pos = s; // 从头开始 int16_t right_pos = num_leds - 1 - s; // 从尾开始 // 设置左侧LED if (left_pos < right_pos && left_pos < num_leds) { ws2815_xledc(display_format, flash_color1, left_pos, LED_TaskDef.LED_Brightne); } // 设置右侧LED if (right_pos > left_pos && right_pos < num_leds) { ws2815_xledc(display_format, flash_color1, right_pos, LED_TaskDef.LED_Brightne); } // 如果是奇数LED数量且到达中间点,设置中间LED if (num_leds % 2 == 1 && s == step && step == max_steps - 1) { uint16_t center_pos = num_leds / 2; ws2815_xledc(display_format, flash_color1, center_pos, LED_TaskDef.LED_Brightne); } } // 每1帧推进一次覆盖进度(根据需求调整) if (frame_count++ % 1 == 0) { if (step >= max_steps) { // 覆盖完成,切换到下一组颜色 base_color_index = flash_color_index1; // 基色变为第一个闪烁颜色 flash_color_index1 = (flash_color_index1 + 1) % 7; // 更新闪烁颜色索引 step = 0; // 重置覆盖进度 } else { step++; // 推进覆盖进度 } } // 准备DMA数据 //ws2815_rgb_color_out_32to24bit_code_fill(&code_buf[0], &color_buf[0]); // 判断使能DMA发送 if (num_leds % 4 == 1) { ledc_dma_kick((uint32_t)&code_buf[0], LED_TaskDef.RGB_CODE_LEN + 1); } else { ledc_dma_kick((uint32_t)&code_buf[0], LED_TaskDef.RGB_CODE_LEN); } // 标记忙碌状态 LED_TaskDef.ledc_kick_state = 1; } } /** * @brief mode42 七彩刷色拉幕 * @param * @retval * @note speed100ms最佳 */ void ws2815_multbrushsaladcurtain(uint8_t display_format) { if (!LED_TaskDef.LED_SWITCH) { return; } // 空闲状态 if (LED_TaskDef.ledc_kick_state == 0) { //printf("CURRENT_TASK = %x\n", LED_TaskDef.CURRENT_TASK); //printf("DMA_CODE_LEN = %x\n", LED_TaskDef.RGB_CODE_LEN); //printf("RGB_XLED_NUM = %x\n", LED_TaskDef.RGB_XLED_NUM); //printf("LED_Brightne = %.2f\n", LED_TaskDef.LED_Brightne); uint16_t num_leds = LED_TaskDef.RGB_XLED_NUM; static uint8_t color_index = 0; // 当前颜色索引 static uint8_t next_color_index = 1; // 下一个颜色索引 static uint16_t step = 0; // 覆盖步数 static uint8_t flash_state = 0; // 闪烁状态(0或1) static uint8_t frame_count = 0; // 帧计数器 // 更新闪烁状态(每次调用翻转) flash_state = !flash_state; // 计算中心位置 uint16_t center = num_leds / 2; uint16_t max_steps = (center > (num_leds - center)) ? center : (num_leds - center); // 获取当前颜色值 uint32_t current_color = rainbow[color_index]; uint32_t next_color = rainbow[next_color_index]; // 设置所有LED for (uint16_t i = 0; i < num_leds; i++) { // 计算该LED是否在覆盖区域内 uint8_t is_covered = 0; for (uint16_t s = 0; s <= step; s++) { uint16_t left_pos = center - s; uint16_t right_pos = center + s - (num_leds % 2 ? 0 : 1); // 当LED数量为偶数时,需要额外处理中心点 if (num_leds % 2 == 0) { left_pos = center - s - 1; right_pos = center + s; // 对于偶数LED,中心点有两个 if (s == 0) { if (i == center - 1 || i == center) { is_covered = 1; break; } } } // 检查是否在覆盖位置 if (i == left_pos || i == right_pos) { is_covered = 1; break; } } // 设置LED颜色 if (is_covered) { // 覆盖区域:根据闪烁状态显示颜色 if ((i % 2) == ((step % 2))) { ws2815_xledc(display_format, current_color, i, LED_TaskDef.LED_Brightne); // 上一个颜色 } else { ws2815_xledc(display_format, next_color, i, LED_TaskDef.LED_Brightne); // 当前颜色 } } else { // 未覆盖区域:固定显示下一个颜色 ws2815_xledc(display_format, next_color, i, LED_TaskDef.LED_Brightne); } } // 每1帧推进一次覆盖进度 if (frame_count++ % 1 == 0) { if (step > max_steps) { // 覆盖完成,切换到下一组颜色 color_index = next_color_index; next_color_index = (next_color_index + 1) % 7; step = 0; // 重置覆盖进度 } else { step++; // 推进覆盖进度 } } // 准备DMA数据 //ws2815_rgb_color_out_32to24bit_code_fill(&code_buf[0], &color_buf[0]); // 判断使能DMA发送 if (num_leds % 4 == 1) { ledc_dma_kick((uint32_t)&code_buf[0], LED_TaskDef.RGB_CODE_LEN + 1); } else { ledc_dma_kick((uint32_t)&code_buf[0], LED_TaskDef.RGB_CODE_LEN); } // 标记忙碌状态 LED_TaskDef.ledc_kick_state = 1; } } /** * @brief mode43,45 三色刷色闭幕. * @param * @retval * @note speed100ms最佳 */ void ws2815_threebrushclosing(uint8_t display_format,uint32_t colors[]) { if (!LED_TaskDef.LED_SWITCH) { return; } // 空闲状态 if (LED_TaskDef.ledc_kick_state == 0) { //printf("CURRENT_TASK = %x\n", LED_TaskDef.CURRENT_TASK); //printf("DMA_CODE_LEN = %x\n", LED_TaskDef.RGB_CODE_LEN); //printf("RGB_XLED_NUM = %x\n", LED_TaskDef.RGB_XLED_NUM); //printf("LED_Brightne = %.2f\n", LED_TaskDef.LED_Brightne); uint16_t num_leds = LED_TaskDef.RGB_XLED_NUM; static uint8_t base_color_index = 0; // 基色索引(当前主要颜色) static uint8_t flash_color_index1 = 1; // 第一个闪烁颜色索引 static uint16_t step = 0; // 覆盖步数 static uint8_t flash_state = 0; // 闪烁状态(0或1) static uint8_t frame_count = 0; // 帧计数器 // 更新闪烁状态(每次调用翻转) flash_state = !flash_state; // 获取当前基色和闪烁颜色 uint32_t base_color = rainbow[base_color_index]; uint32_t flash_color1 = rainbow[flash_color_index1]; // 计算最大步数(从两边向中间推进) uint16_t max_steps = (num_leds + 1) / 2; // 中间点位置 // 1. 设置整个灯带为基色 for (uint16_t i = 0; i < num_leds; i++) { if ((i % 2) == ((step % 2))) { ws2815_xledc(display_format, base_color, i, LED_TaskDef.LED_Brightne); // 上一个颜色 } else { ws2815_xledc(display_format, flash_color1, i, LED_TaskDef.LED_Brightne); // 当前颜色 } } // 2. 在覆盖区域设置闪烁颜色(从头尾向中间推进) for (uint16_t s = 0; s <= step; s++) { // 计算左右覆盖位置(从头尾向中间推进) int16_t left_pos = s; // 从头开始 int16_t right_pos = num_leds - 1 - s; // 从尾开始 // 设置左侧LED if (left_pos < right_pos && left_pos < num_leds) { ws2815_xledc(display_format, flash_color1, left_pos, LED_TaskDef.LED_Brightne); } // 设置右侧LED if (right_pos > left_pos && right_pos < num_leds) { ws2815_xledc(display_format, flash_color1, right_pos, LED_TaskDef.LED_Brightne); } // 如果是奇数LED数量且到达中间点,设置中间LED if (num_leds % 2 == 1 && s == step && step == max_steps - 1) { uint16_t center_pos = num_leds / 2; ws2815_xledc(display_format, flash_color1, center_pos, LED_TaskDef.LED_Brightne); } } // 每1帧推进一次覆盖进度(根据需求调整) if (frame_count++ % 1 == 0) { if (step >= max_steps) { // 覆盖完成,切换到下一组颜色 base_color_index = flash_color_index1; // 基色变为第一个闪烁颜色 flash_color_index1 = (flash_color_index1 + 1) % 3; // 更新闪烁颜色索引 step = 0; // 重置覆盖进度 } else { step++; // 推进覆盖进度 } } // 准备DMA数据 //ws2815_rgb_color_out_32to24bit_code_fill(&code_buf[0], &color_buf[0]); // 判断使能DMA发送 if (num_leds % 4 == 1) { ledc_dma_kick((uint32_t)&code_buf[0], LED_TaskDef.RGB_CODE_LEN + 1); } else { ledc_dma_kick((uint32_t)&code_buf[0], LED_TaskDef.RGB_CODE_LEN); } // 标记忙碌状态 LED_TaskDef.ledc_kick_state = 1; } } /** * @brief mode44,46 三色刷色拉幕 * @param * @retval * @note speed100ms最佳 */ void ws2815_threebrushsaladcurtain(uint8_t display_format,uint32_t colors[]) { if (!LED_TaskDef.LED_SWITCH) { return; } // 空闲状态 if (LED_TaskDef.ledc_kick_state == 0) { //printf("CURRENT_TASK = %x\n", LED_TaskDef.CURRENT_TASK); //printf("DMA_CODE_LEN = %x\n", LED_TaskDef.RGB_CODE_LEN); //printf("RGB_XLED_NUM = %x\n", LED_TaskDef.RGB_XLED_NUM); //printf("LED_Brightne = %.2f\n", LED_TaskDef.LED_Brightne); uint16_t num_leds = LED_TaskDef.RGB_XLED_NUM; static uint8_t color_index = 0; // 当前颜色索引 static uint8_t next_color_index = 1; // 下一个颜色索引 static uint16_t step = 0; // 覆盖步数 static uint8_t flash_state = 0; // 闪烁状态(0或1) static uint8_t frame_count = 0; // 帧计数器 // 更新闪烁状态(每次调用翻转) flash_state = !flash_state; // 计算中心位置 uint16_t center = num_leds / 2; uint16_t max_steps = (center > (num_leds - center)) ? center : (num_leds - center); // 获取当前颜色值 uint32_t current_color = colors[color_index]; uint32_t next_color = colors[next_color_index]; // 设置所有LED for (uint16_t i = 0; i < num_leds; i++) { // 计算该LED是否在覆盖区域内 uint8_t is_covered = 0; for (uint16_t s = 0; s <= step; s++) { uint16_t left_pos = center - s; uint16_t right_pos = center + s - (num_leds % 2 ? 0 : 1); // 当LED数量为偶数时,需要额外处理中心点 if (num_leds % 2 == 0) { left_pos = center - s - 1; right_pos = center + s; // 对于偶数LED,中心点有两个 if (s == 0) { if (i == center - 1 || i == center) { is_covered = 1; break; } } } // 检查是否在覆盖位置 if (i == left_pos || i == right_pos) { is_covered = 1; break; } } // 设置LED颜色 if (is_covered) { // 覆盖区域:根据闪烁状态显示颜色 if ((i % 2) == ((step % 2))) { ws2815_xledc(display_format, current_color, i, LED_TaskDef.LED_Brightne); // 上一个颜色 } else { ws2815_xledc(display_format, next_color, i, LED_TaskDef.LED_Brightne); // 当前颜色 } } else { // 未覆盖区域:固定显示下一个颜色 ws2815_xledc(display_format, next_color, i, LED_TaskDef.LED_Brightne); } } // 每1帧推进一次覆盖进度 if (frame_count++ % 1 == 0) { if (step > max_steps) { // 覆盖完成,切换到下一组颜色 color_index = next_color_index; next_color_index = (next_color_index + 1) % 3; step = 0; // 重置覆盖进度 } else { step++; // 推进覆盖进度 } } // 准备DMA数据 //ws2815_rgb_color_out_32to24bit_code_fill(&code_buf[0], &color_buf[0]); // 判断使能DMA发送 if (num_leds % 4 == 1) { ledc_dma_kick((uint32_t)&code_buf[0], LED_TaskDef.RGB_CODE_LEN + 1); } else { ledc_dma_kick((uint32_t)&code_buf[0], LED_TaskDef.RGB_CODE_LEN); } // 标记忙碌状态 LED_TaskDef.ledc_kick_state = 1; } } /** * @brief mode47 七彩闭幕 * @param * @retval * @note speed100ms最佳 */ void ws2815_multclosing(uint8_t display_format) { if (!LED_TaskDef.LED_SWITCH) { return; } // 空闲状态 if (LED_TaskDef.ledc_kick_state == 0) { //printf("CURRENT_TASK = %x\n", LED_TaskDef.CURRENT_TASK); //printf("DMA_CODE_LEN = %x\n", LED_TaskDef.RGB_CODE_LEN); //printf("RGB_XLED_NUM = %x\n", LED_TaskDef.RGB_XLED_NUM); //printf("LED_Brightne = %.2f\n", LED_TaskDef.LED_Brightne); uint16_t num_leds = LED_TaskDef.RGB_XLED_NUM; static uint8_t base_color_index = 0; // 当前颜色索引 static uint8_t closing_color_index = 1; // 拉幕颜色索引 static uint16_t step = 0; // 覆盖步数 static uint8_t frame_count = 0; // 帧计数器 // 计算中心位置 uint16_t center = num_leds / 2; // 设置整个灯带为基色 for (uint16_t i = 0; i < num_leds; i++) { ws2815_xledc(display_format, rainbow[base_color_index], i, LED_TaskDef.LED_Brightne); } // 左侧区域 for(uint16_t i = 0; i < step; i++){ ws2815_xledc(display_format, rainbow[closing_color_index], i, LED_TaskDef.LED_Brightne); } // 右侧闭幕区域 for (uint16_t i = num_leds - 1; i > num_leds - 1 - step; i--) { ws2815_xledc(display_format, rainbow[closing_color_index], i, LED_TaskDef.LED_Brightne); } // 每1帧推进一次覆盖进度 if (frame_count++ % 1 == 0) { if (step >= center) { // 覆盖完成,切换到下一组颜色 base_color_index = closing_color_index; // 基色变为拉幕颜色 closing_color_index = (closing_color_index + 1) % 7; // 更新拉幕颜色索引 step = 0; // 重置覆盖进度 } else { step++; // 推进覆盖进度 } } // 准备DMA数据 // ws2815_rgb_color_out_32to24bit_code_fill(&code_buf[0], &color_buf[0]); // 判断使能DMA发送 if (num_leds % 4 == 1) { ledc_dma_kick((uint32_t)&code_buf[0], LED_TaskDef.RGB_CODE_LEN + 1); } else { ledc_dma_kick((uint32_t)&code_buf[0], LED_TaskDef.RGB_CODE_LEN); } // 标记忙碌状态 LED_TaskDef.ledc_kick_state = 1; } } /** * @brief mode48 七彩拉幕 * @param * @retval * @note speed100ms最佳 */ void ws2815_multsaladcurtain(uint8_t display_format) { if (!LED_TaskDef.LED_SWITCH) { return; } // 空闲状态 if (LED_TaskDef.ledc_kick_state == 0) { //printf("CURRENT_TASK = %x\n", LED_TaskDef.CURRENT_TASK); //printf("DMA_CODE_LEN = %x\n", LED_TaskDef.RGB_CODE_LEN); //printf("RGB_XLED_NUM = %x\n", LED_TaskDef.RGB_XLED_NUM); //printf("LED_Brightne = %.2f\n", LED_TaskDef.LED_Brightne); uint16_t num_leds = LED_TaskDef.RGB_XLED_NUM; static uint8_t base_color_index = 0; // 基色索引(当前主要颜色) static uint8_t closing_color_index = 1; // 拉幕颜色索引 static uint16_t step = 0; // 覆盖步数 static uint8_t frame_count = 0; // 帧计数器 // 计算中心位置 uint16_t center = num_leds / 2; uint16_t max_steps = (center > (num_leds - center)) ? center : (num_leds - center); // 获取当前颜色 uint32_t base_color = rainbow[base_color_index]; uint32_t closing_color = rainbow[closing_color_index]; // 设置整个灯带为基色 for (uint16_t i = 0; i < num_leds; i++) { ws2815_xledc(display_format, base_color, i, LED_TaskDef.LED_Brightne); } // 在覆盖区域设置拉幕颜色 for (uint16_t s = 0; s <= step; s++) { int16_t left_pos = center - s; int16_t right_pos = center + s; // 处理偶数LED数量的中心偏移 if (num_leds % 2 == 0) { left_pos = center - s - 1; right_pos = center + s; } // 设置左侧LED if (left_pos >= 0 && left_pos < num_leds) { ws2815_xledc(display_format, closing_color, left_pos, LED_TaskDef.LED_Brightne); } // 设置右侧LED(避免中间点重复设置) if (right_pos != left_pos && right_pos >= 0 && right_pos < num_leds) { ws2815_xledc(display_format, closing_color, right_pos, LED_TaskDef.LED_Brightne); } } // 每1帧推进一次覆盖进度 if (frame_count++ % 1 == 0) { if (step >= max_steps) { // 覆盖完成,切换到下一组颜色 base_color_index = closing_color_index; // 基色变为拉幕颜色 closing_color_index = (closing_color_index + 1) % 7; // 更新拉幕颜色索引 step = 0; // 重置覆盖进度 } else { step++; // 推进覆盖进度 } } // 准备DMA数据 //ws2815_rgb_color_out_32to24bit_code_fill(&code_buf[0], &color_buf[0]); // 判断使能DMA发送 if (num_leds % 4 == 1) { ledc_dma_kick((uint32_t)&code_buf[0], LED_TaskDef.RGB_CODE_LEN + 1); } else { ledc_dma_kick((uint32_t)&code_buf[0], LED_TaskDef.RGB_CODE_LEN); } // 标记忙碌状态 LED_TaskDef.ledc_kick_state = 1; } } /** * @brief mode49,51 三色闭幕 * @param * @retval * @note speed100ms最佳 */ void ws2815_threeclosing(uint8_t display_format,uint32_t colors[]) { if (!LED_TaskDef.LED_SWITCH) { return; } // 空闲状态 if (LED_TaskDef.ledc_kick_state == 0) { //printf("CURRENT_TASK = %x\n", LED_TaskDef.CURRENT_TASK); //printf("DMA_CODE_LEN = %x\n", LED_TaskDef.RGB_CODE_LEN); //printf("RGB_XLED_NUM = %x\n", LED_TaskDef.RGB_XLED_NUM); //printf("LED_Brightne = %.2f\n", LED_TaskDef.LED_Brightne); uint16_t num_leds = LED_TaskDef.RGB_XLED_NUM; static uint8_t base_color_index = 0; // 当前颜色索引 static uint8_t closing_color_index = 1; // 拉幕颜色索引 static uint16_t step = 0; // 覆盖步数 static uint8_t frame_count = 0; // 帧计数器 // 计算中心位置 uint16_t center = num_leds / 2; // 设置整个灯带为基色 for (uint16_t i = 0; i < num_leds; i++) { ws2815_xledc(display_format, colors[base_color_index], i, LED_TaskDef.LED_Brightne); } // 左侧区域 for(uint16_t i = 0; i < step; i++){ ws2815_xledc(display_format, colors[closing_color_index], i, LED_TaskDef.LED_Brightne); } // 右侧闭幕区域 for (uint16_t i = num_leds - 1; i > num_leds - 1 - step; i--) { ws2815_xledc(display_format, colors[closing_color_index], i, LED_TaskDef.LED_Brightne); } // 每1帧推进一次覆盖进度 if (frame_count++ % 1 == 0) { if (step >= center) { // 覆盖完成,切换到下一组颜色 base_color_index = closing_color_index; // 基色变为拉幕颜色 closing_color_index = (closing_color_index + 1) % 3; // 更新拉幕颜色索引 step = 0; // 重置覆盖进度 } else { step++; // 推进覆盖进度 } } // 准备DMA数据 //ws2815_rgb_color_out_32to24bit_code_fill(&code_buf[0], &color_buf[0]); // 判断使能DMA发送 if (num_leds % 4 == 1) { ledc_dma_kick((uint32_t)&code_buf[0], LED_TaskDef.RGB_CODE_LEN + 1); } else { ledc_dma_kick((uint32_t)&code_buf[0], LED_TaskDef.RGB_CODE_LEN); } // 标记忙碌状态 LED_TaskDef.ledc_kick_state = 1; } } /** * @brief mode50,52 三色拉幕 * @param * @retval * @note speed100ms最佳 */ void ws2815_threesaladcurtain(uint8_t display_format,uint32_t colors[]) { if (!LED_TaskDef.LED_SWITCH) { return; } // 空闲状态 if (LED_TaskDef.ledc_kick_state == 0) { //printf("CURRENT_TASK = %x\n", LED_TaskDef.CURRENT_TASK); //printf("DMA_CODE_LEN = %x\n", LED_TaskDef.RGB_CODE_LEN); //printf("RGB_XLED_NUM = %x\n", LED_TaskDef.RGB_XLED_NUM); //printf("LED_Brightne = %.2f\n", LED_TaskDef.LED_Brightne); uint16_t num_leds = LED_TaskDef.RGB_XLED_NUM; static uint8_t base_color_index = 0; // 基色索引(当前主要颜色) static uint8_t closing_color_index = 1; // 拉幕颜色索引 static uint16_t step = 0; // 覆盖步数 static uint8_t frame_count = 0; // 帧计数器 // 计算中心位置 uint16_t center = num_leds / 2; uint16_t max_steps = (center > (num_leds - center)) ? center : (num_leds - center); // 获取当前颜色 uint32_t base_color = colors[base_color_index]; uint32_t closing_color = colors[closing_color_index]; // 设置整个灯带为基色 for (uint16_t i = 0; i < num_leds; i++) { ws2815_xledc(display_format, base_color, i, LED_TaskDef.LED_Brightne); } // 在覆盖区域设置拉幕颜色 for (uint16_t s = 0; s <= step; s++) { int16_t left_pos = center - s; int16_t right_pos = center + s; // 处理偶数LED数量的中心偏移 if (num_leds % 2 == 0) { left_pos = center - s - 1; right_pos = center + s; } // 设置左侧LED if (left_pos >= 0 && left_pos < num_leds) { ws2815_xledc(display_format, closing_color, left_pos, LED_TaskDef.LED_Brightne); } // 设置右侧LED(避免中间点重复设置) if (right_pos != left_pos && right_pos >= 0 && right_pos < num_leds) { ws2815_xledc(display_format, closing_color, right_pos, LED_TaskDef.LED_Brightne); } } // 每1帧推进一次覆盖进度 if (frame_count++ % 1 == 0) { if (step >= max_steps) { // 覆盖完成,切换到下一组颜色 base_color_index = closing_color_index; // 基色变为拉幕颜色 closing_color_index = (closing_color_index + 1) % 3; // 更新拉幕颜色索引 step = 0; // 重置覆盖进度 } else { step++; // 推进覆盖进度 } } // 准备DMA数据 //ws2815_rgb_color_out_32to24bit_code_fill(&code_buf[0], &color_buf[0]); // 判断使能DMA发送 if (num_leds % 4 == 1) { ledc_dma_kick((uint32_t)&code_buf[0], LED_TaskDef.RGB_CODE_LEN + 1); } else { ledc_dma_kick((uint32_t)&code_buf[0], LED_TaskDef.RGB_CODE_LEN); } // 标记忙碌状态 LED_TaskDef.ledc_kick_state = 1; } } /** * @brief mode53,55,57,59,61,63,65 单色闭幕 * @param * @retval * @note speed200ms最佳 */ void ws2815_singleclosing(uint8_t display_format, uint32_t color) { if (!LED_TaskDef.LED_SWITCH) { return; } // 空闲状态 if (LED_TaskDef.ledc_kick_state == 0) { uint16_t num_leds = LED_TaskDef.RGB_XLED_NUM; static uint16_t step = 0; // 推进步数 //printf("CURRENT_TASK = %x\n", LED_TaskDef.CURRENT_TASK); //printf("DMA_CODE_LEN = %x\n", LED_TaskDef.RGB_CODE_LEN); //printf("RGB_XLED_NUM = %x\n", LED_TaskDef.RGB_XLED_NUM); //printf("LED_Brightne = %.2f\n", LED_TaskDef.LED_Brightne); // 整个灯带设置为黑色(背景) for (uint16_t i = 0; i < num_leds; i++) { ws2815_xledc(display_format, Color_BLACK, i, LED_TaskDef.LED_Brightne); } // 计算中心位置 uint16_t center = num_leds / 2; uint16_t max_steps = center; // 左边LED颜色 (从开头向中间流动) for (uint16_t pos = step; pos < center; pos += 3) { if (pos < num_leds) { ws2815_xledc(display_format, color, pos, LED_TaskDef.LED_Brightne); } } // 右边LED颜色 (从尾部向中间流动) for (uint16_t pos = num_leds - 1 - step; pos >= center && pos < num_leds; pos -= 3) { if (pos < num_leds) { ws2815_xledc(display_format, color, pos, LED_TaskDef.LED_Brightne); } } // 处理奇数LED数量的中间点 if (num_leds % 2 == 1 && step == max_steps - 1) { // 在最后一次推进时点亮中间LED ws2815_xledc(display_format, color, center, LED_TaskDef.LED_Brightne); } // 更新帧计数器(0->1->2->0循环) step = (step + 1) % 3; // 准备DMA数据 //ws2815_rgb_color_out_32to24bit_code_fill(&code_buf[0], &color_buf[0]); // 判断使能DMA发送 if (num_leds % 4 == 1) { ledc_dma_kick((uint32_t)&code_buf[0], LED_TaskDef.RGB_CODE_LEN + 1); } else { ledc_dma_kick((uint32_t)&code_buf[0], LED_TaskDef.RGB_CODE_LEN); } // 标记忙碌状态 LED_TaskDef.ledc_kick_state = 1; } } /** * @brief mode54,56,58,60,62,64,66 单色拉幕 * @param * @retval * @note speed200ms最佳 */ void ws2815_singlesaladcurtain(uint8_t display_format, uint32_t color) { if (!LED_TaskDef.LED_SWITCH) { return; } // 空闲状态 if (LED_TaskDef.ledc_kick_state == 0) { uint16_t num_leds = LED_TaskDef.RGB_XLED_NUM; static uint8_t frame = 0; // 帧计数器(0,1,2循环) //printf("CURRENT_TASK = %x\n", LED_TaskDef.CURRENT_TASK); //printf("DMA_CODE_LEN = %x\n", LED_TaskDef.RGB_CODE_LEN); //printf("RGB_XLED_NUM = %x\n", LED_TaskDef.RGB_XLED_NUM); //printf("LED_Brightne = %.2f\n", LED_TaskDef.LED_Brightne); // 整个灯带设置为黑色(背景) for (uint16_t i = 0; i < num_leds; i++) { ws2815_xledc(display_format, Color_BLACK, i, LED_TaskDef.LED_Brightne); } // 计算中心位置 uint16_t center = num_leds / 2; // 根据当前帧设置亮灯位置 for (uint16_t i = 0; i < num_leds; i++) { // 计算当前LED相对于中心的位置 int16_t dist_to_center = i - center; // 从中间向头尾流动的特殊模式 switch(frame) { case 0: if ((abs(dist_to_center) % 3) == 0) { ws2815_xledc(display_format, color, i, LED_TaskDef.LED_Brightne); } break; case 1: if ((abs(dist_to_center) % 3) == 1) { ws2815_xledc(display_format, color, i, LED_TaskDef.LED_Brightne); } break; case 2: if ((abs(dist_to_center) % 3) == 2) { ws2815_xledc(display_format, color, i, LED_TaskDef.LED_Brightne); } break; } } // 更新帧计数器(0->1->2->0循环) frame = (frame + 1) % 3; // 准备DMA数据 //ws2815_rgb_color_out_32to24bit_code_fill(&code_buf[0], &color_buf[0]); // 判断使能DMA发送 if (num_leds % 4 == 1) { ledc_dma_kick((uint32_t)&code_buf[0], LED_TaskDef.RGB_CODE_LEN + 1); } else { ledc_dma_kick((uint32_t)&code_buf[0], LED_TaskDef.RGB_CODE_LEN); } // 标记忙碌状态 LED_TaskDef.ledc_kick_state = 1; } } /** * @brief mode67,68 七色明暗过渡 * @param direction: 方向. * @retval 0 = 反向 , 1 = 正向 * @note speed250ms最佳 */ void ws2815_multlightdarktran(uint8_t display_format, uint8_t direction) { if (!LED_TaskDef.LED_SWITCH) { return; } // 空闲状态 if (LED_TaskDef.ledc_kick_state == 0) { //printf("CURRENT_TASK = %x\n", LED_TaskDef.CURRENT_TASK); //printf("DMA_CODE_LEN = %x\n", LED_TaskDef.RGB_CODE_LEN); //printf("RGB_XLED_NUM = %x\n", LED_TaskDef.RGB_XLED_NUM); //printf("LED_Brightne = %.2f\n", LED_TaskDef.LED_Brightne); uint8_t block_size = 7; uint8_t colors_size = 7; // 计算状态循环模数 uint32_t mod_factor = block_size * LED_TaskDef.RGB_XLED_NUM; // 遍历所有LED灯珠 for (uint16_t i = 0; i < LED_TaskDef.RGB_XLED_NUM; i++) { // 全局位置 uint16_t global_pos = (direction == 1) ? (mod_factor - LED_TaskDef.ledc_fill_state + i) : // 反向流动 (i + LED_TaskDef.ledc_fill_state); // 正向流动 // 计算颜色索引(0-6) uint8_t color_index = (global_pos / block_size) % colors_size; // 计算在颜色块内的位置(0-4) uint8_t pos_in_block = global_pos % block_size; // 获取亮度系数并计算最终亮度值 uint16_t block_brightness = brightness_table4[pos_in_block]; uint16_t final_brightness = (uint16_t)(LED_TaskDef.LED_Brightne * block_brightness/255); // 确保亮度在安全范围内(5-255) if (final_brightness > 255) final_brightness = 255; else if (final_brightness < 5) final_brightness = 5; final_brightness = final_brightness*100/255; // 调用LED设置函数 ws2815_xledc(display_format, rainbow[color_index], i, final_brightness); } // 更新流动状态(确保无限循环) LED_TaskDef.ledc_fill_state = (LED_TaskDef.ledc_fill_state + 1) % mod_factor; // 生成DMA数据 //ws2815_rgb_color_out_32to24bit_code_fill(&code_buf[0], &color_buf[0]); // DMA传输 if(LED_TaskDef.RGB_XLED_NUM % 4 == 1) { ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN + 1); } else { ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN); } // 设置为忙碌状态 LED_TaskDef.ledc_kick_state = 1; } } /** * @brief mode69,70,71,72 三色明暗过渡 * @param direction: 方向. * @retval 0 = 反向 , 1 = 正向 * @note speed250ms最佳 */ void ws2815_threelightdarktran(uint8_t display_format,uint8_t direction, uint32_t colors[]) { if (!LED_TaskDef.LED_SWITCH) { return; } // 空闲状态 if (LED_TaskDef.ledc_kick_state == 0) { //printf("CURRENT_TASK = %x\n", LED_TaskDef.CURRENT_TASK); //printf("DMA_CODE_LEN = %x\n", LED_TaskDef.RGB_CODE_LEN); //printf("RGB_XLED_NUM = %x\n", LED_TaskDef.RGB_XLED_NUM); //printf("LED_Brightne = %.2f\n", LED_TaskDef.LED_Brightne); uint8_t block_size = 7; uint8_t colors_size = 3; // 计算状态循环模数 uint32_t mod_factor = block_size * LED_TaskDef.RGB_XLED_NUM; // 遍历所有LED灯珠 for (uint16_t i = 0; i < LED_TaskDef.RGB_XLED_NUM; i++) { // 全局位置 uint16_t global_pos = (direction == 1) ? (mod_factor - LED_TaskDef.ledc_fill_state + i) : // 反向流动 (i + LED_TaskDef.ledc_fill_state); // 正向流动 // 计算颜色索引(0-2) uint8_t color_index = (global_pos / block_size) % colors_size; // 计算在颜色块内的位置(0-6) uint8_t pos_in_block = global_pos % block_size; // 获取亮度系数并计算最终亮度值 uint16_t block_brightness = brightness_table4[pos_in_block]; uint16_t final_brightness = (uint16_t)(LED_TaskDef.LED_Brightne * block_brightness/255); // 确保亮度在安全范围内 if (final_brightness > 255) final_brightness = 255; else if (final_brightness < 5) final_brightness = 5; final_brightness = final_brightness*100/255; // 调用LED设置函数 ws2815_xledc(display_format, colors[color_index], i, final_brightness); } // 更新流动状态(确保无限循环) LED_TaskDef.ledc_fill_state = (LED_TaskDef.ledc_fill_state + 1) % mod_factor; // 生成DMA数据 //ws2815_rgb_color_out_32to24bit_code_fill(&code_buf[0], &color_buf[0]); // DMA传输 if(LED_TaskDef.RGB_XLED_NUM % 4 == 1) { ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN + 1); } else { ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN); } // 设置为忙碌状态 LED_TaskDef.ledc_kick_state = 1; } } /** * @brief mode73-86 六色明暗过渡X色 * @param direction: 方向. * @retval 0 = 反向 , 1 = 正向 * @note speed250ms最佳 */ /* void ws2815_sixlightdarktran(uint8_t display_format, uint8_t direction, uint32_t colors[], uint32_t color) { if (!LED_TaskDef.LED_SWITCH) { return; } // 空闲状态 if (LED_TaskDef.ledc_kick_state == 0) { uint8_t red_block_size = 2; // 红色块大小 uint8_t other_block_size = 7; // 其他颜色块大小 uint8_t colors_size = 12; // 计算状态循环模数(固定总块大小为7) uint32_t mod_factor = other_block_size * LED_TaskDef.RGB_XLED_NUM; // 遍历所有LED灯珠 for (uint16_t i = 0; i < LED_TaskDef.RGB_XLED_NUM; i++) { // 计算全局位置 uint16_t global_pos = (direction == 1) ? (mod_factor - LED_TaskDef.ledc_fill_state + i) : // 反向流动 (i + LED_TaskDef.ledc_fill_state); // 正向流动 // 计算颜色索引(0-11) uint8_t color_index = (global_pos / other_block_size) % colors_size; uint8_t pos_in_block = global_pos % other_block_size; // 检查是否在红色区域内 if (colors[color_index] == color && pos_in_block >= red_block_size) { // 不在红色区域,跳过 continue; } uint16_t final_brightness; // 处理红色 if (colors[color_index] == color) { // 亮度固定 系统亮度 final_brightness = (uint16_t)(LED_TaskDef.LED_Brightne * 63); } // 处理其他颜色 else { // 获取亮度系数并计算最终亮度值 uint16_t block_brightness = brightness_table4[pos_in_block]; uint16_t temp_brightness = (uint16_t)(LED_TaskDef.LED_Brightne * block_brightness); // 确保亮度在安全范围内 if (temp_brightness > 255) final_brightness = 255; else if (temp_brightness < 5) final_brightness = 5; else final_brightness = temp_brightness; } // 调用LED设置函数 ws2815_xledc(display_format, colors[color_index], i, (float)final_brightness / 255.0f); } // 更新流动状态(确保无限循环) LED_TaskDef.ledc_fill_state = (LED_TaskDef.ledc_fill_state + 1) % mod_factor; // 生成DMA数据 //ws2815_rgb_color_out_32to24bit_code_fill(&code_buf[0], &color_buf[0]); // DMA传输 if (LED_TaskDef.RGB_XLED_NUM % 4 == 1) { ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN + 1); } else { ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN); } // 设置为忙碌状态 LED_TaskDef.ledc_kick_state = 1; } } */ void ws2815_sixlightdarktran(uint8_t display_format, uint8_t direction, uint32_t colors[]) { if (!LED_TaskDef.LED_SWITCH) { return; } // 空闲状态 if (LED_TaskDef.ledc_kick_state == 0) { //printf("CURRENT_TASK = %x\n", LED_TaskDef.CURRENT_TASK); //printf("DMA_CODE_LEN = %x\n", LED_TaskDef.RGB_CODE_LEN); //printf("RGB_XLED_NUM = %x\n", LED_TaskDef.RGB_XLED_NUM); //printf("LED_Brightne = %.2f\n", LED_TaskDef.LED_Brightne); uint8_t block_size = 7; uint8_t colors_size = 9; // 计算状态循环模数 uint32_t mod_factor = block_size * LED_TaskDef.RGB_XLED_NUM; // 遍历所有LED灯珠 for (uint16_t i = 0; i < LED_TaskDef.RGB_XLED_NUM; i++) { // 全局位置 uint16_t global_pos = (direction == 1) ? (mod_factor - LED_TaskDef.ledc_fill_state + i) : // 反向流动 (i + LED_TaskDef.ledc_fill_state); // 正向流动 // 计算颜色索引(0-8) uint8_t color_index = (global_pos / block_size) % colors_size; // 计算在颜色块内的位置(0-6) uint8_t pos_in_block = global_pos % block_size; // 获取亮度系数并计算最终亮度值 uint16_t block_brightness = brightness_table5[pos_in_block]; uint16_t final_brightness = (uint16_t)(LED_TaskDef.LED_Brightne * block_brightness/255); // 确保亮度在安全范围内(5-255) if (final_brightness > 255) final_brightness = 255; else if (final_brightness < 5) final_brightness = 5; final_brightness = final_brightness*100/255; // 调用LED设置函数 ws2815_xledc(display_format, colors[color_index], i,final_brightness); } // 更新流动状态(确保无限循环) LED_TaskDef.ledc_fill_state = (LED_TaskDef.ledc_fill_state + 1) % mod_factor; // 生成DMA数据 //ws2815_rgb_color_out_32to24bit_code_fill(&code_buf[0], &color_buf[0]); // DMA传输 if(LED_TaskDef.RGB_XLED_NUM % 4 == 1) { ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN + 1); } else { ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN); } // 设置为忙碌状态 LED_TaskDef.ledc_kick_state = 1; } } /** * @brief mode87-88 七色流水 * @param direction: 方向. * @retval 0 = 反向 , 1 = 正向 * @note speed250ms最佳 */ void ws2815_multRunningwater(uint8_t display_format, uint8_t direction) { if (!LED_TaskDef.LED_SWITCH) { return; } //空闲状态 if (LED_TaskDef.ledc_kick_state == 0) { //printf("CURRENT_TASK = %x\n", LED_TaskDef.CURRENT_TASK); //printf("DMA_CODE_LEN = %x\n", LED_TaskDef.RGB_CODE_LEN); //printf("RGB_XLED_NUM = %x\n", LED_TaskDef.RGB_XLED_NUM); //printf("LED_Brightne = %.2f\n", LED_TaskDef.LED_Brightne); if(direction==0){//反向流动 // 填充当前帧 for(uint16_t i = 0; i < LED_TaskDef.RGB_XLED_NUM; i++) { // 计算颜色索引(使用取模保证连续性) uint8_t color_index = ((i + LED_TaskDef.ledc_fill_state) / 7) % 7; ws2815_xledc(display_format, rainbow[color_index], i,LED_TaskDef.LED_Brightne); } } else if(direction==1){//正向流动 // 填充当前帧 for(uint16_t i = 0; i < LED_TaskDef.RGB_XLED_NUM; i++) { // 反向流动:通过整体偏移使流动方向相反 int32_t position = LED_TaskDef.RGB_XLED_NUM * 7 - LED_TaskDef.ledc_fill_state + i; uint8_t color_index = (position / 7) % 7; ws2815_xledc(display_format, rainbow[color_index], i,LED_TaskDef.LED_Brightne); } } LED_TaskDef.ledc_fill_state = (LED_TaskDef.ledc_fill_state + 1) % (LED_TaskDef.RGB_XLED_NUM * 7); //ws2815_rgb_color_out_32to24bit_code_fill(&code_buf[0],&color_buf[0]); //判断使能DMA发送 if(LED_TaskDef.RGB_XLED_NUM%4 == 1){ ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN+1); } else{ ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN); } //忙碌状态 LED_TaskDef.ledc_kick_state = 1; } } /** * @brief mode89-92 三色流水 * @param direction: 方向. * @retval 0 = 反向 , 1 = 正向 * @note speed250ms最佳 */ void ws2815_threeRunningwater(uint8_t display_format, uint8_t direction,uint32_t colors[]) { if (!LED_TaskDef.LED_SWITCH) { return; } //空闲状态 if (LED_TaskDef.ledc_kick_state == 0) { //printf("CURRENT_TASK = %x\n", LED_TaskDef.CURRENT_TASK); //printf("DMA_CODE_LEN = %x\n", LED_TaskDef.RGB_CODE_LEN); //printf("RGB_XLED_NUM = %x\n", LED_TaskDef.RGB_XLED_NUM); //printf("LED_Brightne = %.2f\n", LED_TaskDef.LED_Brightne); if(direction==0){//反向流动 // 填充当前帧 for(uint16_t i = 0; i < LED_TaskDef.RGB_XLED_NUM; i++) { // 计算颜色索引(使用取模保证连续性) uint8_t color_index = ((i + LED_TaskDef.ledc_fill_state) / 7) % 3; ws2815_xledc(display_format, colors[color_index], i,LED_TaskDef.LED_Brightne); } } else if(direction==1){//正向流动 // 填充当前帧 for(uint16_t i = 0; i < LED_TaskDef.RGB_XLED_NUM; i++) { // 反向流动:通过整体偏移使流动方向相反 int32_t position = LED_TaskDef.RGB_XLED_NUM * 7 - LED_TaskDef.ledc_fill_state + i; uint8_t color_index = (position / 7) % 3; ws2815_xledc(display_format, colors[color_index], i,LED_TaskDef.LED_Brightne); } } LED_TaskDef.ledc_fill_state = (LED_TaskDef.ledc_fill_state + 1) % (LED_TaskDef.RGB_XLED_NUM * 7); //ws2815_rgb_color_out_32to24bit_code_fill(&code_buf[0],&color_buf[0]); //判断使能DMA发送 if(LED_TaskDef.RGB_XLED_NUM%4 == 1){ ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN+1); } else{ ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN); } //忙碌状态 LED_TaskDef.ledc_kick_state = 1; } } /** * @brief mode93-104 双色流水 * @param direction: 方向. * @retval 0 = 反向 , 1 = 正向 * @note speed250ms最佳 */ void ws2815_secondRunningwater(uint8_t display_format, uint8_t direction,uint32_t colors[]) { if (!LED_TaskDef.LED_SWITCH) { return; } //空闲状态 if (LED_TaskDef.ledc_kick_state == 0) { //printf("CURRENT_TASK = %x\n", LED_TaskDef.CURRENT_TASK); //printf("DMA_CODE_LEN = %x\n", LED_TaskDef.RGB_CODE_LEN); //printf("RGB_XLED_NUM = %x\n", LED_TaskDef.RGB_XLED_NUM); //printf("LED_Brightne = %.2f\n", LED_TaskDef.LED_Brightne); if(direction==0){//反向流动 // 填充当前帧 for(uint16_t i = 0; i < LED_TaskDef.RGB_XLED_NUM; i++) { // 计算颜色索引(使用取模保证连续性) uint8_t color_index = ((i + LED_TaskDef.ledc_fill_state) / 7) % 2; ws2815_xledc(display_format, colors[color_index], i,LED_TaskDef.LED_Brightne); } } else if(direction==1){//正向流动 // 填充当前帧 for(uint16_t i = 0; i < LED_TaskDef.RGB_XLED_NUM; i++) { // 反向流动:通过整体偏移使流动方向相反 int32_t position = LED_TaskDef.RGB_XLED_NUM * 7 - LED_TaskDef.ledc_fill_state + i; uint8_t color_index = (position / 7) % 2; ws2815_xledc(display_format, colors[color_index], i,LED_TaskDef.LED_Brightne); } } LED_TaskDef.ledc_fill_state = (LED_TaskDef.ledc_fill_state + 1) % (LED_TaskDef.RGB_XLED_NUM * 7); //ws2815_rgb_color_out_32to24bit_code_fill(&code_buf[0],&color_buf[0]); //判断使能DMA发送 if(LED_TaskDef.RGB_XLED_NUM%4 == 1){ ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN+1); } else{ ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN); } //忙碌状态 LED_TaskDef.ledc_kick_state = 1; } } /** * @brief mode105-128 XYX流动 * @param direction: 方向. * @retval 0 = 反向 , 1 = 正向 * @note speed200ms最佳 */ void ws2815_flowingstripe(uint8_t display_format, uint8_t direction, uint32_t stripe_color, uint32_t gap_color) { if (!LED_TaskDef.LED_SWITCH) { return; } //空闲状态 if (LED_TaskDef.ledc_kick_state == 0) { //printf("CURRENT_TASK = %x\n", LED_TaskDef.CURRENT_TASK); //printf("DMA_CODE_LEN = %x\n", LED_TaskDef.RGB_CODE_LEN); //printf("RGB_XLED_NUM = %x\n", LED_TaskDef.RGB_XLED_NUM); //printf("LED_Brightne = %.2f\n", LED_TaskDef.LED_Brightne); const uint16_t pattern_size = 20; // 2(stripe) + 6(gap) + 2(stripe) + 10(black) = 20 if(direction == 0){ // 反向 for(uint16_t i = 0; i < LED_TaskDef.RGB_XLED_NUM; i++) { // 计算在当前帧中的相对位置 uint16_t pos = (i + LED_TaskDef.ledc_fill_state) % pattern_size; if(pos < 2) // 条纹色 ws2815_xledc(display_format, stripe_color, i, LED_TaskDef.LED_Brightne); else if(pos < 8) // 间隙色 ws2815_xledc(display_format, gap_color, i, LED_TaskDef.LED_Brightne); else if(pos < 10) // 条纹色 ws2815_xledc(display_format, stripe_color, i, LED_TaskDef.LED_Brightne); else // 黑色 ws2815_xledc(display_format, Color_BLACK, i, LED_TaskDef.LED_Brightne); } } else if(direction == 1){ // 正向 for(uint16_t i = 0; i < LED_TaskDef.RGB_XLED_NUM; i++) { // 整体偏移 int32_t position = (pattern_size - LED_TaskDef.ledc_fill_state) + i; uint16_t pos = position % pattern_size; if(pos < 2) ws2815_xledc(display_format, stripe_color, i, LED_TaskDef.LED_Brightne); else if(pos < 8) ws2815_xledc(display_format, gap_color, i, LED_TaskDef.LED_Brightne); else if(pos < 10) ws2815_xledc(display_format, stripe_color, i, LED_TaskDef.LED_Brightne); else ws2815_xledc(display_format, Color_BLACK, i, LED_TaskDef.LED_Brightne); } } // 更新流动状态 LED_TaskDef.ledc_fill_state = (LED_TaskDef.ledc_fill_state + 1) % pattern_size; //ws2815_rgb_color_out_32to24bit_code_fill(&code_buf[0], &color_buf[0]); // 判断使能DMA发送 if(LED_TaskDef.RGB_XLED_NUM % 4 == 1){ ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN + 1); } else { ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN); } // 忙碌状态 LED_TaskDef.ledc_kick_state = 1; } } /** * @brief mode129-130 七彩拖尾 * @param direction: 方向. * @retval 0 = 反向 , 1 = 正向 * @note */ void ws2815_multtrailing(uint8_t display_format, uint8_t direction) { if (!LED_TaskDef.LED_SWITCH) { return; } // 空闲状态 if (LED_TaskDef.ledc_kick_state == 0) { //printf("CURRENT_TASK = %x\n", LED_TaskDef.CURRENT_TASK); //printf("DMA_CODE_LEN = %x\n", LED_TaskDef.RGB_CODE_LEN); //printf("RGB_XLED_NUM = %x\n", LED_TaskDef.RGB_XLED_NUM); //printf("LED_Brightne = %.2f\n", LED_TaskDef.LED_Brightne); uint8_t block_size = 24; uint8_t colors_size = 7; // 计算状态循环模数 uint32_t mod_factor = block_size * LED_TaskDef.RGB_XLED_NUM; uint8_t under_Brightne = LED_TaskDef.LED_Brightne*64/255; // 遍历所有LED灯珠 for (uint16_t i = 0; i < LED_TaskDef.RGB_XLED_NUM; i++) { // 全局位置 uint16_t global_pos = (direction == 1) ? (mod_factor - LED_TaskDef.ledc_fill_state + i) : // 反向流动 (i + LED_TaskDef.ledc_fill_state); // 正向流动 // 计算颜色索引(0-6) uint8_t color_index = (global_pos / block_size) % colors_size; // 计算在颜色块内的位置(0-23) uint8_t pos_in_block = global_pos % block_size; // 计算亮度值 uint16_t block_brightness = 0; if(direction == 1){ block_brightness = brightness_table6[pos_in_block]; } else if(direction == 0){ block_brightness = brightness_table7[pos_in_block]; } uint16_t final_brightness = (uint16_t)(LED_TaskDef.LED_Brightne*block_brightness/255); // 确保亮度在安全范围内(5-255) if (final_brightness > 255) final_brightness = 255; else if (final_brightness < 5) final_brightness = 5; final_brightness = final_brightness*128/255; ws2815_xledc(display_format, rainbow[color_index], i,final_brightness); } // 更新流动状态(确保无限循环) LED_TaskDef.ledc_fill_state = (LED_TaskDef.ledc_fill_state + 1) % mod_factor; // 生成DMA数据 //ws2815_rgb_color_out_32to24bit_code_fill(&code_buf[0], &color_buf[0]); // DMA传输 if(LED_TaskDef.RGB_XLED_NUM % 4 == 1) { ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN + 1); } else { ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN); } // 设置为忙碌状态 LED_TaskDef.ledc_kick_state = 1; } } /** * @brief mode131-144 单色拖尾 * @param direction: 方向. * @retval 0 = 反向 , 1 = 正向 * @note */ void ws2815_singletrailing(uint8_t display_format, uint8_t direction, uint32_t color) { if (!LED_TaskDef.LED_SWITCH) { return; } // 空闲状态 if (LED_TaskDef.ledc_kick_state == 0) { //printf("CURRENT_TASK = %x\n", LED_TaskDef.CURRENT_TASK); //printf("DMA_CODE_LEN = %x\n", LED_TaskDef.RGB_CODE_LEN); //printf("RGB_XLED_NUM = %x\n", LED_TaskDef.RGB_XLED_NUM); //printf("LED_Brightne = %.2f\n", LED_TaskDef.LED_Brightne); uint8_t block_size = 24; // 计算状态循环模数 uint32_t mod_factor = block_size * LED_TaskDef.RGB_XLED_NUM; // 遍历所有LED灯珠 for (uint16_t i = 0; i < LED_TaskDef.RGB_XLED_NUM; i++) { // 全局位置 uint16_t global_pos = (direction == 1) ? (mod_factor - LED_TaskDef.ledc_fill_state + i) : // 反向流动 (i + LED_TaskDef.ledc_fill_state); // 正向流动 // 计算在颜色块内的位置(0-23) uint8_t pos_in_block = global_pos % block_size; // 计算亮度值 uint16_t block_brightness = 0; if(direction == 1){ block_brightness = brightness_table6[pos_in_block]; } else if(direction == 0){ block_brightness = brightness_table7[pos_in_block]; } uint16_t final_brightness = (uint16_t)(LED_TaskDef.LED_Brightne * block_brightness/255); // 确保亮度在安全范围内(5-255) if (final_brightness > 255) final_brightness = 255; else if (final_brightness < 5) final_brightness = 5; final_brightness = final_brightness*128/255; ws2815_xledc(display_format, color, i, final_brightness); } // 更新流动状态(确保无限循环) LED_TaskDef.ledc_fill_state = (LED_TaskDef.ledc_fill_state + 1) % mod_factor; // 生成DMA数据 //ws2815_rgb_color_out_32to24bit_code_fill(&code_buf[0], &color_buf[0]); // DMA传输 if(LED_TaskDef.RGB_XLED_NUM % 4 == 1) { ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN + 1); } else { ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN); } // 设置为忙碌状态 LED_TaskDef.ledc_kick_state = 1; } } /** * @brief mode145-158 单色跑动 * @param direction: 方向. * @retval 0 = 反向 , 1 = 正向 * @note speed300ms最佳 */ void ws2815_singlerunning(uint8_t display_format, uint8_t direction, uint32_t color) { if (!LED_TaskDef.LED_SWITCH) { return; } //空闲状态 if (LED_TaskDef.ledc_kick_state == 0) { //printf("CURRENT_TASK = %x\n", LED_TaskDef.CURRENT_TASK); //printf("DMA_CODE_LEN = %x\n", LED_TaskDef.RGB_CODE_LEN); //printf("RGB_XLED_NUM = %x\n", LED_TaskDef.RGB_XLED_NUM); //printf("LED_Brightne = %.2f\n", LED_TaskDef.LED_Brightne); const uint8_t gap = 8; // 每隔8个灯珠亮一个 // 计算组内的亮灯位置(0-7) uint8_t light_pos = LED_TaskDef.ledc_fill_state % gap; for(uint16_t i = 0; i < LED_TaskDef.RGB_XLED_NUM; i++) { // 计算当前灯珠在组内的位置 uint8_t pos_in_group = i % gap; if (direction == 0) { // 反向流动 // 亮灯位置从右向左移动 uint8_t reversed_pos = gap - 1 - light_pos; if (pos_in_group == reversed_pos) { ws2815_xledc(display_format, color, i, LED_TaskDef.LED_Brightne); } else { ws2815_xledc(display_format, Color_BLACK, i, LED_TaskDef.LED_Brightne); } } else if (direction == 1) { // 正向流动 // 亮灯位置从左向右移动 if (pos_in_group == light_pos) { ws2815_xledc(display_format, color, i, LED_TaskDef.LED_Brightne); } else { ws2815_xledc(display_format, Color_BLACK, i, LED_TaskDef.LED_Brightne); } } } // 更新流动状态 LED_TaskDef.ledc_fill_state = (LED_TaskDef.ledc_fill_state + 1) % gap; //ws2815_rgb_color_out_32to24bit_code_fill(&code_buf[0], &color_buf[0]); // 判断使能DMA发送 if (LED_TaskDef.RGB_XLED_NUM % 4 == 1) { ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN + 1); } else { ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN); } // 忙碌状态 LED_TaskDef.ledc_kick_state = 1; } } /** * @brief mode159-160 七色跑动 * @param direction: 方向. * @retval 0 = 反向 , 1 = 正向 * @note speed200ms最佳 */ void ws2815_multrunning(uint8_t display_format, uint8_t direction) { if (!LED_TaskDef.LED_SWITCH) { return; } // 空闲状态 if (LED_TaskDef.ledc_kick_state == 0) { // 打印信息 //printf("CURRENT_TASK = %x\n", LED_TaskDef.CURRENT_TASK); //printf("DMA_CODE_LEN = %x\n", LED_TaskDef.RGB_CODE_LEN); //printf("RGB_XLED_NUM = %x\n", LED_TaskDef.RGB_XLED_NUM); //printf("LED_Brightne = %.2f\n", LED_TaskDef.LED_Brightne); if(direction == 1){ for(uint16_t i = 0; i < LED_TaskDef.RGB_XLED_NUM; i++) { // 正向流动 uint16_t reversed_i = LED_TaskDef.RGB_XLED_NUM - 1 - i; // 位置索引 uint32_t pos_index = (reversed_i + LED_TaskDef.ledc_fill_state) % 56; // 每8个位置中有7个是黑色 if (pos_index % 8 == 0) { // 每8个位置中的第一个显示彩虹色 uint8_t color_index = (pos_index / 8) % 7; ws2815_xledc(display_format, rainbow[color_index], i, LED_TaskDef.LED_Brightne); } else { // 其他位置显示黑色 ws2815_xledc(display_format, Color_BLACK, i, LED_TaskDef.LED_Brightne); } } } else if(direction == 0){ // 填充当前帧 for(uint16_t i = 0; i < LED_TaskDef.RGB_XLED_NUM; i++) { // 计算位置索引(考虑反向流动) uint32_t pos_index = (i + LED_TaskDef.ledc_fill_state) % 56; // 计算颜色索引:每8个位置中有7个是黑色 if (pos_index % 8 == 0) { // 每8个位置中的第一个显示彩虹色 uint8_t color_index = (pos_index / 8) % 7; ws2815_xledc(display_format, rainbow[color_index], i, LED_TaskDef.LED_Brightne); } else { // 其他位置显示黑色 ws2815_xledc(display_format, Color_BLACK, i, LED_TaskDef.LED_Brightne); } } } // 更新流动状态 LED_TaskDef.ledc_fill_state = (LED_TaskDef.ledc_fill_state + 1) % 56; // 生成DMA数据 //ws2815_rgb_color_out_32to24bit_code_fill(&code_buf[0], &color_buf[0]); // DMA传输 if(LED_TaskDef.RGB_XLED_NUM % 4 == 1) { ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN + 1); } else { ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN); } // 设置为忙碌状态 LED_TaskDef.ledc_kick_state = 1; } } /** * @brief mode161-164 三色跑动 * @param direction: 方向. * @retval 0 = 反向 , 1 = 正向 * @note speed200ms最佳 */ void ws2815_threerunning(uint8_t display_format, uint8_t direction, uint32_t colors[]) { if (!LED_TaskDef.LED_SWITCH) { return; } //空闲状态 if (LED_TaskDef.ledc_kick_state == 0) { //printf("CURRENT_TASK = %x\n", LED_TaskDef.CURRENT_TASK); //printf("DMA_CODE_LEN = %x\n", LED_TaskDef.RGB_CODE_LEN); //printf("RGB_XLED_NUM = %x\n", LED_TaskDef.RGB_XLED_NUM); //printf("LED_Brightne = %.2f\n", LED_TaskDef.LED_Brightne); if(direction==0){//反向流动 for(uint16_t i = 0; i < LED_TaskDef.RGB_XLED_NUM; i++) { // 反向流动 uint32_t pos_index = (i + LED_TaskDef.ledc_fill_state) % 24; // 每8个位置中有7个是黑色 if (pos_index % 8 == 0) { // 每8个位置中的第一个显示彩虹色 uint8_t color_index = (pos_index / 8) % 3; ws2815_xledc(display_format, colors[color_index], i, LED_TaskDef.LED_Brightne); } else { // 其他位置显示黑色 ws2815_xledc(display_format, Color_BLACK, i, LED_TaskDef.LED_Brightne); } } } else if(direction==1){//正向流动 for(uint16_t i = 0; i < LED_TaskDef.RGB_XLED_NUM; i++) { // 正向流动 uint16_t reversed_i = LED_TaskDef.RGB_XLED_NUM - 1 - i; // 位置索引 uint32_t pos_index = (reversed_i + LED_TaskDef.ledc_fill_state) % 24; // 每8个位置中有7个是黑色 if (pos_index % 8 == 0) { // 每8个位置中的第一个显示彩虹色 uint8_t color_index = (pos_index / 8) % 3; ws2815_xledc(display_format, colors[color_index], i, LED_TaskDef.LED_Brightne); } else { // 其他位置显示黑色 ws2815_xledc(display_format, Color_BLACK, i, LED_TaskDef.LED_Brightne); } } } LED_TaskDef.ledc_fill_state = (LED_TaskDef.ledc_fill_state + 1) % (LED_TaskDef.RGB_XLED_NUM * 3); //ws2815_rgb_color_out_32to24bit_code_fill(&code_buf[0],&color_buf[0]); //判断使能DMA发送 if(LED_TaskDef.RGB_XLED_NUM%4 == 1){ ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN+1); } else{ ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN); } //忙碌状态 LED_TaskDef.ledc_kick_state = 1; } } /** * @brief mode165-168 四色跑动 * @param direction: 方向. * @retval 0 = 反向 , 1 = 正向 * @note speed200ms最佳 */ void ws2815_fourrunning(uint8_t display_format, uint8_t direction, uint32_t colors[]) { if (!LED_TaskDef.LED_SWITCH) { return; } //空闲状态 if (LED_TaskDef.ledc_kick_state == 0) { //printf("CURRENT_TASK = %x\n", LED_TaskDef.CURRENT_TASK); //printf("DMA_CODE_LEN = %x\n", LED_TaskDef.RGB_CODE_LEN); //printf("RGB_XLED_NUM = %x\n", LED_TaskDef.RGB_XLED_NUM); //printf("LED_Brightne = %.2f\n", LED_TaskDef.LED_Brightne); if(direction==0){//反向流动 for(uint16_t i = 0; i < LED_TaskDef.RGB_XLED_NUM; i++) { // 反向流动 uint32_t pos_index = (i + LED_TaskDef.ledc_fill_state) % 32; // 每8个位置中有7个是黑色 if (pos_index % 8 == 0) { // 每8个位置中的第一个显示彩虹色 uint8_t color_index = (pos_index / 8) % 4; ws2815_xledc(display_format, colors[color_index], i, LED_TaskDef.LED_Brightne); } else { // 其他位置显示黑色 ws2815_xledc(display_format, Color_BLACK, i, LED_TaskDef.LED_Brightne); } } } else if(direction==1){//正向流动 for(uint16_t i = 0; i < LED_TaskDef.RGB_XLED_NUM; i++) { // 正向流动 uint16_t reversed_i = LED_TaskDef.RGB_XLED_NUM - 1 - i; // 位置索引 uint32_t pos_index = (reversed_i + LED_TaskDef.ledc_fill_state) % 32; // 每8个位置中有7个是黑色 if (pos_index % 8 == 0) { // 每8个位置中的第一个显示彩虹色 uint8_t color_index = (pos_index / 8) % 4; ws2815_xledc(display_format, colors[color_index], i, LED_TaskDef.LED_Brightne); } else { // 其他位置显示黑色 ws2815_xledc(display_format, Color_BLACK, i, LED_TaskDef.LED_Brightne); } } } LED_TaskDef.ledc_fill_state = (LED_TaskDef.ledc_fill_state + 1) % (LED_TaskDef.RGB_XLED_NUM * 4); //ws2815_rgb_color_out_32to24bit_code_fill(&code_buf[0],&color_buf[0]); //判断使能DMA发送 if(LED_TaskDef.RGB_XLED_NUM%4 == 1){ ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN+1); } else{ ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN); } //忙碌状态 LED_TaskDef.ledc_kick_state = 1; } } /** * @brief mode169-196 单底单色跑动 * @param direction: 方向. * @retval 0 = 反向 , 1 = 正向 * @note speed200ms最佳 */ void ws2815_undersinglerunning(uint8_t display_format, uint8_t direction, uint32_t undercolor, uint32_t color) { if (!LED_TaskDef.LED_SWITCH) { return; } //空闲状态 if (LED_TaskDef.ledc_kick_state == 0) { //printf("CURRENT_TASK = %x\n", LED_TaskDef.CURRENT_TASK); //printf("DMA_CODE_LEN = %x\n", LED_TaskDef.RGB_CODE_LEN); //printf("RGB_XLED_NUM = %x\n", LED_TaskDef.RGB_XLED_NUM); //printf("LED_Brightne = %.2f\n", LED_TaskDef.LED_Brightne); const uint8_t gap = 8; // 每隔8个灯珠亮一个 // 计算组内的亮灯位置(0-7) uint8_t light_pos = LED_TaskDef.ledc_fill_state % gap; uint8_t under_Brightne = LED_TaskDef.LED_Brightne*64/255; if(LED_TaskDef.CURRENT_TASK == 180 || LED_TaskDef.CURRENT_TASK == 179){ under_Brightne = LED_TaskDef.LED_Brightne*32/255; } for(uint16_t i = 0; i < LED_TaskDef.RGB_XLED_NUM; i++) { // 计算当前灯珠在组内的位置 uint8_t pos_in_group = i % gap; if (direction == 0) { // 反向流动 // 亮灯位置从右向左移动 uint8_t reversed_pos = gap - 1 - light_pos; if (pos_in_group == reversed_pos) { ws2815_xledc(display_format, color, i, LED_TaskDef.LED_Brightne); } else { ws2815_xledc(display_format, undercolor, i, under_Brightne); } } else if (direction == 1) { // 正向流动 // 亮灯位置从左向右移动 if (pos_in_group == light_pos) { ws2815_xledc(display_format, color, i, LED_TaskDef.LED_Brightne); } else { ws2815_xledc(display_format, undercolor, i, under_Brightne); } } } // 更新流动状态 LED_TaskDef.ledc_fill_state = (LED_TaskDef.ledc_fill_state + 1) % gap; //ws2815_rgb_color_out_32to24bit_code_fill(&code_buf[0], &color_buf[0]); // 判断使能DMA发送 if (LED_TaskDef.RGB_XLED_NUM % 4 == 1) { ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN + 1); } else { ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN); } // 忙碌状态 LED_TaskDef.ledc_kick_state = 1; } } /** * @brief mode197-210 单底七色跑动 * @param direction: 方向. * @retval 0 = 反向 , 1 = 正向 * @note speed200ms最佳 */ void ws2815_undermultrunning(uint8_t display_format, uint8_t direction, uint32_t undercolor) { uint8_t under_Brightne; if (!LED_TaskDef.LED_SWITCH) { return; } // 空闲状态 if (LED_TaskDef.ledc_kick_state == 0) { // 打印信息 //printf("CURRENT_TASK = %x\n", LED_TaskDef.CURRENT_TASK); //printf("DMA_CODE_LEN = %x\n", LED_TaskDef.RGB_CODE_LEN); //printf("RGB_XLED_NUM = %x\n", LED_TaskDef.RGB_XLED_NUM); //printf("LED_Brightne = %.2f\n", LED_TaskDef.LED_Brightne); if(LED_TaskDef.CURRENT_TASK == 205 || LED_TaskDef.CURRENT_TASK == 206 || LED_TaskDef.CURRENT_TASK == 209 || LED_TaskDef.CURRENT_TASK == 210) under_Brightne = LED_TaskDef.LED_Brightne*32/255; else under_Brightne = LED_TaskDef.LED_Brightne*64/255; if(direction == 1){ for(uint16_t i = 0; i < LED_TaskDef.RGB_XLED_NUM; i++) { // 正向流动 uint16_t reversed_i = LED_TaskDef.RGB_XLED_NUM - 1 - i; // 位置索引 uint32_t pos_index = (reversed_i + LED_TaskDef.ledc_fill_state) % 56; // 每8个位置中有7个是黑色 if (pos_index % 8 == 0) { // 每8个位置中的第一个显示彩虹色 uint8_t color_index = (pos_index / 8) % 7; ws2815_xledc(display_format, rainbow[color_index], i, LED_TaskDef.LED_Brightne); } else { // 其他位置显示黑色 ws2815_xledc(display_format, undercolor, i, under_Brightne); } } } else if(direction == 0){ // 填充当前帧 for(uint16_t i = 0; i < LED_TaskDef.RGB_XLED_NUM; i++) { // 计算位置索引(考虑反向流动) uint32_t pos_index = (i + LED_TaskDef.ledc_fill_state) % 56; // 计算颜色索引:每8个位置中有7个是黑色 if (pos_index % 8 == 0) { // 每8个位置中的第一个显示彩虹色 uint8_t color_index = (pos_index / 8) % 7; ws2815_xledc(display_format, rainbow[color_index], i, LED_TaskDef.LED_Brightne); } else { // 其他位置显示黑色 ws2815_xledc(display_format, undercolor, i, under_Brightne); } } } // 更新流动状态 LED_TaskDef.ledc_fill_state = (LED_TaskDef.ledc_fill_state + 1) % 56; // 生成DMA数据 //ws2815_rgb_color_out_32to24bit_code_fill(&code_buf[0], &color_buf[0]); // DMA传输 if(LED_TaskDef.RGB_XLED_NUM % 4 == 1) { ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN + 1); } else { ledc_dma_kick((u32)&code_buf[0], LED_TaskDef.RGB_CODE_LEN); } // 设置为忙碌状态 LED_TaskDef.ledc_kick_state = 1; } } /** * @brief 彩色色温调节从红到绿到蓝在到红 * @param * @retval * @note */ void ws2815_Color_temperature_adjustment(uint8_t display_format,uint8_t Temp){ const uint16_t R[] = { 255, 226, 198, 170, 141, 113, 85, 56, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 56, 85, 113, 141, 170, 198, 226, 255 }; const uint16_t G[] = { 0, 28, 56, 85, 113, 141, 170, 198, 226, 255, 255, 226, 198, 170, 141, 113, 85, 56, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; const uint16_t B[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 56, 85, 113, 141, 170, 198, 226, 255, 255, 226, 198, 170, 141, 113, 85, 56, 28, 0 }; uint32_t color = 0; color |= R[Temp]<<16; color |= G[Temp]<<8; color |= B[Temp]; //RGB_Color Temp_Color = Data_24_To_RGB_Color(color,LED_TaskDef.LED_Brightne); //WS2815_SetAll(Temp_Color); //WS2815_Update(); for(uint16_t i=0;i 1){ // if(LED_TaskDef.CURRENT_TASK == 0){ // LED_TaskDef.CURRENT_TASK++; // }else if(LED_TaskDef.CURRENT_TASK >= 211){ LED_TaskDef.CURRENT_TASK = 2; }else{ LED_TaskDef.CURRENT_TASK++; } }else{ LED_TaskDef.CURRENT_TASK = 2; } set_TaskComps_timer(7, 30000); } } void Music_Mode_Change(void){ if(mic_start){ //DEBUG("mic_start is True\tlevel is :%d\n",level); switch(Muisc_mode){ case 0: app_ws2812_set__music_fireworks_light_forward(rainbow_colors[step],4); break; case 1: app_ws2812_set__music_fireworks_light_reverse(rainbow_colors[step],4); break; case 2: ws2815_bidirectional_meteor(rainbow_colors[step],4); break; case 3: ws2815_center_to_edges(rainbow_colors[step],LED_TaskDef.RGB_XLED_NUM/2); break; case 4: ws2815_integrated_effects(LED_TaskDef.RGB_XLED_NUM); break; case 5: ws2815_center_to_edges_optimized(0,LED_TaskDef.RGB_XLED_NUM); break; default: break; } } } //目前LED_MODE函数的索引为0 uint8_t Task_tamp = 0; //接收到命令的处理过程有误,即:在关闭的状态下,不能修改其他属性。 void handle_remote_key(uint8_t key_value) { uint32_t Countdown = 0;// 0 ms if(!LED_TaskDef.LED_SWITCH){ if(key_value == ON){//关机状态按开机才有识别 LED_TaskDef.LED_SWITCH = 1;//开机 } }else{ Countdown = 0; switch (key_value) { case OFF: if (LED_TaskDef.LED_SWITCH == 1)//关机状态按开机才有识别 LED_TaskDef.LED_SWITCH = 0;//关机 break; case SPEED_IN: if (LED_TaskDef.LEDC_TICK_Speed > 50) { LED_TaskDef.LEDC_TICK_Speed -= 10; set_TaskComps_itvTime(3, LED_TaskDef.LEDC_TICK_Speed); } break; case SPEED_RE: if (LED_TaskDef.LEDC_TICK_Speed < 160) { LED_TaskDef.LEDC_TICK_Speed += 10; set_TaskComps_itvTime(3, LED_TaskDef.LEDC_TICK_Speed); //DEBUG("%d\n",LED_TaskDef.LEDC_TICK_Speed); } break; case BRIGHTNESS_IN: if (LED_TaskDef.LED_Brightne < 100) { LED_TaskDef.LED_Brightne += 10; if (LED_TaskDef.LED_Brightne > 100) LED_TaskDef.LED_Brightne = 100; } break; case BRIGHTNESS_RE: if (LED_TaskDef.LED_Brightne > 10) { LED_TaskDef.LED_Brightne -= 10; if(LED_TaskDef.LED_Brightne < 10){ LED_TaskDef.LED_Brightne = 10; } } break; case MODE_IN: if(LED_TaskDef.CURRENT_TASK>217){ LED_TaskDef.CURRENT_TASK = Task_tamp; } if (LED_TaskDef.CURRENT_TASK < 217 && LED_TaskDef.CURRENT_TASK >= 0) LED_TaskDef.CURRENT_TASK++; // else // LED_TaskDef.CURRENT_TASK = 0; Temp_Flag = 0;auto_Flag = 0;Color_Flag = 0;mic_start = 0; //set_TaskComps_timer(2, 30000); break; case MODE_RE: if (LED_TaskDef.CURRENT_TASK > 0) LED_TaskDef.CURRENT_TASK--; Temp_Flag = 0;auto_Flag = 0;Color_Flag = 0;mic_start = 0; //set_TaskComps_timer(2, 30000); break; case IR_AUTO: //printf ("LED_auto\n"); if(auto_Flag){ auto_Flag = 0; WS2815_Clear(); WS2815_Update(); delay_ms(200); light_mode(); delay_ms(200); WS2815_Clear(); WS2815_Update(); delay_ms(200); //DEBUG("auto_close\n"); set_TaskComps_timer(7, 30000); }else{ WS2815_Clear(); WS2815_Update(); delay_ms(200); auto_Flag = 1; Color_Flag = 0; Temp_Flag = 0; mic_start = 0; LED_TaskDef.CURRENT_TASK = 1; //DEBUG("auto_open\n"); set_TaskComps_timer(7, 11); } break; case IR_INMUSIC: //printf ("IR_INMUSIC\n"); Temp_Flag = 0; mic_start = 1;Color_Flag = 0; if(Muisc_mode < 5) Muisc_mode++; //DEBUG("mic_start:%d\n",mic_start); break; case IR_DEMUSIC: //printf ("IR_DEMUSIC\n"); Temp_Flag = 0; mic_start = 1;Color_Flag = 0; if(Muisc_mode > 0) Muisc_mode--; break; case IR_TIME1H: //printf ("IR_TIME1H\n"); if(shutdown_Flag){ shutdown_Flag = 0; WS2815_Clear(); WS2815_Update(); delay_ms(200); light_mode(); delay_ms(200); WS2815_Clear(); WS2815_Update(); delay_ms(200); }else{ shutdown_Flag = 1; WS2815_Clear(); WS2815_Update(); delay_ms(200); Countdown = 3600000;//3600 set_TaskComps_timer(6, Countdown); } break; case IR_TIME2H: if(shutdown_Flag){ shutdown_Flag = 0; WS2815_Clear(); WS2815_Update(); delay_ms(200); light_mode(); delay_ms(200); WS2815_Clear(); WS2815_Update(); delay_ms(200); }else{ shutdown_Flag = 1; WS2815_Clear(); WS2815_Update(); delay_ms(200); Countdown = 3600000 * 2; set_TaskComps_timer(6, Countdown); } //printf ("IR_TIME2H\n"); break; case IR_INTEMP : mic_start = 0; auto_Flag = 0;Color_Flag = 0; //printf ("IR_INTEMP\n"); if(!Temp_Flag){ LED_TaskDef.Temp_Step = 0; Temp_Flag = 1; }else{ if(LED_TaskDef.Temp_Step < 28){ LED_TaskDef.Temp_Step++; } } break; case IR_DETEMP : mic_start = 0; auto_Flag = 0;Color_Flag = 0; //printf ("IR_DETEMP\n"); if(!Temp_Flag){ LED_TaskDef.Temp_Step = 28; Temp_Flag = 1; }else{ if(LED_TaskDef.Temp_Step > 0){ LED_TaskDef.Temp_Step-- ; } } break; case IR_WHITE: //printf ("IR_WHITE\n"); Temp_Flag = 0;mic_start = 0;auto_Flag = 0;Color_Flag = 0; LED_TaskDef.CURRENT_TASK = 211; break; case IR_YELLOW: //printf ("IR_YELLOW\n"); Temp_Flag = 0;mic_start = 0;auto_Flag = 0;Color_Flag = 0; LED_TaskDef.CURRENT_TASK = 212; break; case IR_CHING: //printf ("IR_CHING\n"); Temp_Flag = 0;mic_start = 0;auto_Flag = 0;Color_Flag = 0; LED_TaskDef.CURRENT_TASK = 213; break; case IR_PINK: //printf ("IR_PINK\n"); Temp_Flag = 0;mic_start = 0;auto_Flag = 0;Color_Flag = 0; LED_TaskDef.CURRENT_TASK = 214; break; case IR_RED: //printf ("IR_RED\n"); Temp_Flag = 0;mic_start = 0;auto_Flag = 0;Color_Flag = 0; LED_TaskDef.CURRENT_TASK = 215; break; case IR_GREEN: //printf ("IR_GREEN\n"); Temp_Flag = 0;mic_start = 0;auto_Flag = 0;Color_Flag = 0; LED_TaskDef.CURRENT_TASK = 216; break; case IR_BLUE: //printf ("IR_BLUE\n"); Temp_Flag = 0;mic_start = 0;auto_Flag = 0;Color_Flag = 0; LED_TaskDef.CURRENT_TASK = 217; break; default: break; } } set_TaskComps_timer(5,500);//延时保存数据 5000 }