从渐变区间中插值取出对应值的颜色

//从渐变区间中插值取出对应的颜色   颜色数组  颜色对应值数组   想要插值颜色的数值
export function selectColor(gradientColors,gradientValues,valueToMatch){
  //插值计算
  function interpolateColor(color1, color2, percentage) {
      const r1 = parseInt(color1.slice(1, 3), 16);
      const g1 = parseInt(color1.slice(3, 5), 16);
      const b1 = parseInt(color1.slice(5, 7), 16);

      const r2 = parseInt(color2.slice(1, 3), 16);
      const g2 = parseInt(color2.slice(3, 5), 16);
      const b2 = parseInt(color2.slice(5, 7), 16);

      const r = Math.round(r1 + (r2 - r1) * percentage);
      const g = Math.round(g1 + (g2 - g1) * percentage);
      const b = Math.round(b1 + (b2 - b1) * percentage);

      return `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`;
  }
  let color = '';

  for (let i = 1; i < gradientValues.length; i++) {
      //寻找目标值在那一个渐变区间
      if (valueToMatch <= gradientValues[i]) {
          //计算比例  上区间和下区间的比例
          const percentage = (valueToMatch - gradientValues[i - 1]) / (gradientValues[i] - gradientValues[i - 1]);
          color = interpolateColor(gradientColors[i - 1], gradientColors[i], percentage);
          break;
      }
  }
  // console.log(color)
  return color
}
/******************************************************************************* @file HDL_WS2812B.c @author huiyang @version V1.0 @date 01/21/2022 ****************************************************************************/ #include “HDL_WS2812B.h” #include “stm32f10x.h” // Device header #include <math.h> #include “Delay.h” //延时函数加自己对应的头文件,在复位处使用 #include “OLED.h” uint32_t mode1[3] = {0xff0000,0x00ff00,0x0000ff};//绿红蓝 uint32_t mode2[3] = {0xffffff,0x00ff00,0x0000ff};//白红蓝 uint32_t mode3[3] = {0x0000ff,0x00ff00,0xffffff};//蓝红白 uint32_t mode_red[1] = {0x00ff00};//红 Bst arr[4] = { {0, 0, 0, mode1, 3}, // arr[0] {0, 0, 0, mode2, 3}, // arr[1] {0, 0, 0, mode3, 3}, // arr[2] {0, 0, 0, mode_red, 1} }; / 单个灯珠的编码对应的比较数组 / uint16_t Single_LED_Buffer[DATA_SIZELED_NUM]; uint16_t All_LED_DE[LED_NUM]; / *作用:通用定时器2 TIM2_CH2 PWM输出+DMA初始化 *参数:arr:自动重装 说明:定时器溢出时间计算方法:Tout=((arr+1)(psc+1))/Ft us. Ft=定时器工作频率,单位:Mhz */ void PWM_WS2812B_Init(uint16_t arr) { //结构体变量 GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; DMA_InitTypeDef DMA_InitStructure; //使能RCC时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能PORTA时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); //使能TIM2时钟 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE); //使能DMA1时钟 //初始化GPIO口 GPIO_InitStructure.GPIO_Pin = WS2812B_PIN; //GPIO口 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50MHz GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 GPIO_Init(WS2812B_PORT,&GPIO_InitStructure); //根据指定的参数初始化GPIO口 //初始化TIM2 TIM_TimeBaseStructure.TIM_Prescaler=0; //定时器分频:(0+1)=1,不分频 TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式 TIM_TimeBaseStructure.TIM_Period=arr; //自动重装载 TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; //时钟分割 TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure); //根据指定的参数初始化TIM2 //初始化TIM2 Channel2 PWM模式 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式1 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能 //TIM_OCInitStructure.TIM_Pulse = 0; //待装入捕获比较寄存器的脉冲(此程序不用加初) TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高 TIM_OC2Init(TIM2, &TIM_OCInitStructure); //根据指定的参数初始化外设TIM2 Channel2 /* 此处为知识点所描述处的对应代码,一定要有。移植时注意0C2代表定时器通道2*/ TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable); //使能TIM2在CCR2上的预装载寄存器 TIM_Cmd(TIM2, DISABLE); //失能TIM2,防止第一个脉冲异常 TIM_DMACmd(TIM2, TIM_DMA_CC2, ENABLE); //使能TIM2_CH2的DMA功能(CC2对应通道2) DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(TIM2->CCR2); //设置DMA目的地址 DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Single_LED_Buffer; //设置DMA源地址 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //方向:从内存SendBuff到内存ReceiveBuff DMA_InitStructure.DMA_BufferSize = DATA_SIZE; //一次传输大小DMA_BufferSize=SendBuffSize DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //ReceiveBuff地址不增 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //SendBuff地址自增 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //ReceiveBuff数据单位,16bit DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //SENDBUFF_SIZE数据单位,16bit DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //DMA模式:正常模式(传输一次) DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //优先级:中 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //内存到内存的传输 DMA_Init(DMA1_Channel7, &DMA_InitStructure); //配置DMA1的7通道(不同定时器的通道不一样) DMA_Cmd(DMA1_Channel7, DISABLE); //失能DMA1的7通道,因为一旦使能就开始传输 } //复位灯带 void WS2812B_Reset(void) { TIM_Cmd(TIM2, DISABLE); WS2812B_LOW; Delay_ms(1); //此处延时时间最小大于50us即可 } //写数据编码 void PWM_WS2812B_Write_24Bits(uint16_t num, uint32_t GRB_Data) { // 参数解释变更: // num: 如果为特定(如0xFFFF),则表示写入所有灯珠(保持向后兼容) // 否则,num代表要设置的单个灯珠的索引 // GRB_Data: 要写入的颜色 uint8_t i; // 判断是设置所有灯珠还是单个灯珠 if (num == 0xFFFF) { // 使用一个特殊表示设置全部灯珠 for (uint16_t j = 0; j < LED_NUM; j++) { for (i = 0; i < DATA_SIZE; i++) { Single_LED_Buffer[j * DATA_SIZE + i] = ((GRB_Data << i) & 0x800000) ? T1H : T0H; } } } else { // 设置单个灯珠 if (num >= LED_NUM) return; // 索引检查 for (i = 0; i < DATA_SIZE; i++) { Single_LED_Buffer[num * DATA_SIZE + i] = ((GRB_Data << i) & 0x800000) ? T1H : T0H; } } } //点亮灯珠 void PWM_WS2812B_Show(uint16_t num) typedef struct { uint16_t breath_step; uint8_t current_color_index; uint32_t current_color; uint8_t breath_direction; // 0:增加亮度, 1:减小亮度 } BreathingState_t; static BreathingState_t breath_state = {0, 0, 0, 0}; void PWM_WS2812B_SetBrightness(uint32_t* grb_color, uint8_t brightness) { if (brightness > MAX_BRIGHTNESS) brightness = MAX_BRIGHTNESS; // 分离GRB分量 uint8_t g = (*grb_color >> 16) & 0xFF; uint8_t r = (*grb_color >> 8) & 0xFF; uint8_t b = *grb_color & 0xFF; // 应用亮度缩放(保持颜色比例) g = (g * brightness) / MAX_BRIGHTNESS; r = (r * brightness) / MAX_BRIGHTNESS; b = (b * brightness) / MAX_BRIGHTNESS; // 重新组合GRB颜色 *grb_color = ((uint32_t)g << 16) | ((uint32_t)r << 8) | b; } void PWM_WS2812B_Breathing_MultiColor(uint16_t start_id, uint16_t end_id, Bst *current, uint8_t color_count, uint16_t speed) { if (start_id >= LED_NUM || end_id >= LED_NUM || start_id > end_id || color_count == 0) return; //static uint16_t breath_step = 0; //static uint8_t current_color_index = 0; uint16_t i; // 计算颜色过渡比例 uint8_t next_color_index = (current->current_color_index + 1) % color_count; OLED_ShowNum(3,1,next_color_index, 2); float transition_ratio = (float)current->breath_step / BREATH_STEP_MAX; // 获取当前和下一个颜色 uint32_t current_grb = current->color_palette[current->current_color_index]; uint32_t next_grb = current->color_palette[next_color_index]; // 分离当前颜色的GRB分量 uint8_t current_g = (current_grb >> 16) & 0xFF; uint8_t current_r = (current_grb >> 8) & 0xFF; uint8_t current_b = current_grb & 0xFF; // 分离下一个颜色的GRB分量 uint8_t next_g = (next_grb >> 16) & 0xFF; uint8_t next_r = (next_grb >> 8) & 0xFF; uint8_t next_b = next_grb & 0xFF; // 线性插值计算过渡颜色 uint8_t final_g = current_g + (uint8_t)((next_g - current_g) * transition_ratio); uint8_t final_r = current_r + (uint8_t)((next_r - current_r) * transition_ratio); uint8_t final_b = current_b + (uint8_t)((next_b - current_b) * transition_ratio); uint32_t final_color = ((uint32_t)final_g << 16) | ((uint32_t)final_r << 8) | final_b; // 应用正弦波亮度变化 float sin_value = sinf(2 * 3.14159f * current->breath_step / BREATH_STEP_MAX); uint8_t brightness = (uint8_t)((sin_value + 1.0f) * 50.0f); PWM_WS2812B_SetBrightness(&final_color, brightness); // 设置灯珠颜色 for (i = start_id; i <= end_id; i++) { PWM_WS2812B_Write_24Bits(i, final_color); } // 显示更新 // 更新状态 current->breath_step += speed; if (current->breath_step >= BREATH_STEP_MAX) { current->breath_step = 0; current->current_color_index = next_color_index; } } void PWM_WS2812B_BreathingCycle_Segment(uint16_t start_id, uint16_t end_id, uint16_t speed, Bst current) { PWM_WS2812B_Breathing_MultiColor(start_id, end_id, current, current->color_count, speed); } void PWM_WS2812B_Allreset(void) { uint16_t i; for(i = 0; i < LED_NUM; i++) { PWM_WS2812B_Write_24Bits(i, Dead_color);//先让所有熄灭 All_LED_DE[i] = 0;//同时让所有失能 } } /****************************************************************************** @file HDL_WS2812B.h @author huiyang @version V1.0 @date 01/21/2022 ******************************************************************************/ #ifndef _HDL_WS2812B_H #define _HDL_WS2812B_H #include “stm32f10x.h” #define MAX_BRIGHTNESS 100 // 最大亮度百分比 #define BREATH_STEP_MAX 512 // 呼吸步进最大 #define WS2812B_PIN GPIO_Pin_1 #define WS2812B_PORT GPIOA #define WS2812B_LOW GPIO_ResetBits(WS2812B_PORT,WS2812B_PIN) #define WS2812B_HIGH GPIO_SetBits(WS2812B_PORT,WS2812B_PIN) #define Dead_color 0x000000 #define GREEN 0xFF0000 #define RED 0x00FF00 #define BLUE 0x0000FF #define WHITE 0xFFFFFF /* 根据DataSheet定义0/1编码对应的高电平比较,因为高电平在前,定义高电平的即可 ** 高低电平的比例约为2:1 */ #define WS2812B_ARR 90 //TIM2的自动重装载 #define T0H 29 //0编码高电平时间占1/3 #define T1H 58 //1编码高电平时间占2/3 /* 灯珠亮的个数 / #define LED_NUM 100 //底层驱动未用,为应用方便,先加上 #define DATA_SIZE 24 //WS2812B一个编码的bit数,38\uint32_t mode1[3] = {0xff00,0x00ff00,0x0000ff};//绿-红-蓝 extern uint32_t mode1[3]; extern uint32_t mode2[3]; extern uint32_t mode3[3]; extern uint32_t mode_red[1]; typedef struct { uint16_t breath_step; uint8_t current_color_index; uint8_t breath_direction; uint32_t* color_palette; uint8_t color_count; } Bst; extern Bst arr[4]; void PWM_WS2812B_Init(uint16_t arr); void WS2812B_Reset(void); void PWM_WS2812B_Write_24Bits(uint16_t num,uint32_t GRB_Data); void PWM_WS2812B_Show(uint16_t num); void PWM_WS2812B_Red(uint16_t num); void PWM_WS2812B_Green(uint16_t num); void PWM_WS2812B_Blue(uint16_t num); void PWM_WS2812B_BreathingCycle_Segment(uint16_t start_id, uint16_t end_id, uint16_t speed, Bst current); void PWM_WS2812B_SetBrightness(uint32_t grb_color, uint8_t brightness); void PWM_WS2812B_Breathing_SingleColor(uint16_t start_id, uint16_t end_id, uint32_t base_color, uint16_t speed); void PWM_WS2812B_Breathing_MultiColor(uint16_t start_id, uint16_t end_id, Bst current, uint8_t color_count, uint16_t speed); void PWM_WS2812B_Allreset(void); #endif 基于以上代码,不要修改已经确定的量,实现控制N个级联的10*10WS2812B板显示波纹的RGB渐变效果,要求能自定义精确控制能以第几个板的某一点或某一中心区域(4个点)为中心的水波纹效果,可以实现多个同时出现的波纹效果
11-30
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值