RCC 2014 Warmup (Div. 2)

本文提供了一场 CodeForces 比赛(编号 417)的解题报告,包括 A 到 E 题的详细解析及代码实现。涉及主题有简单数学、模拟算法、构造算法、状态压缩 DP 和矩阵构造。

题目链接:http://codeforces.com/contest/417 

这可能是算很简单的一场CF了。

A题:大意是要让一些人进决赛, 有两种方式一种是C道题,晋级n个人, 还有一种是d道题, 晋级1个人, 现在给出要晋级的人数, 求最少需要多少道题目。 计算几种可能的情况, 比较一下即可。

#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
int c, d, m, n, k;

int main(){
    scanf("%d%d%d%d%d", &c, &d, &n, &m, &k);
    int x, y;
    int res = (m*n) - k;
    if(res < 0) res = 0;
    x = res*d;
    y = res/n * c;
    if(res % n != 0){
        int n1 = y + c;
        int n2 = y + (res%n) * d;
        y = n1 < n2 ? n1 : n2;
    }
    printf("%d\n", x < y? x : y);
    return 0;
}


B题:大意是描述了某个系统后台处理数据的模式, 对于每个用户K有相同ID来标记相同的code. 我们要确定的是, 对于某个用户K在出现标记为X的代码时, X-1标号的代码必须要出现过。 模拟即可

#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
const int N = 1e5 + 10;
int a[N];

int main(){
    int n;
    scanf("%d", &n);
    bool suc = 1;
    memset(a, -1, sizeof(a));
    while(n--){
        int x, k;
        scanf("%d%d", &x, &k);
        if(suc == 0) continue;
        if(x == 0 && a[k] == -1) a[k] = 0;
        else{
            if(x <= a[k]) continue;
            else if(x == a[k] + 1) a[k] = x;
            else suc = 0;
        }
    }
    if(suc) printf("YES\n");
    else printf("NO\n");
    return 0;
}


C题:一个简单的构造题。 题意是:有n个球队互相踢比赛, 每两个球队之间最多踢一场比赛, 现在已知每支球队都踢了K场比赛, 构造一种可能的情况。 首先N支球队最多踢n*(n-1)/2场比赛, 先预判断一下n*k是否超过这个数字。

如果没超过我们可以这样构造: 球队1与2,3...踢, 球队2与3,4...踢,...... 球队n与1,2..踢,依此构造。

#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;

int main(){
    int n, k;
    scanf("%d%d", &n, &k);
    int t = n*(n-1)/2;
    if(n*k > t) printf("-1\n");
    else{
        printf("%d\n", n*k);
        for(int i = 1; i <= n; ++i){
            for(int j = i + 1; j <= i + k; ++j){
                printf("%d %d\n", i, (j-1)%n + 1);
            }
        }
    }
    return 0;
}


D题:稍微困难, 状态压缩DP。 题意是某人有n个朋友, 要请他们完成m道题目(m < 20), 每个朋友帮忙都有要求, 一是要求有n个显示屏, 二是要给x卢布(RUS)的报酬, 每个显示屏b元, 给出每个朋友能做出的题目具体编号, 求要做出所有题目要花多少钱。 考虑到m较小, 我们可以用状态压缩DP来解决。 由于显示器可以分时复用,所以我们可以先将所有朋友按显示器个数从小到大排序,这样到后面选择的时候可以保证前面所选的人可以肯定有足够的显示器支持。 状态压缩DP显然向后DP比较方便。同时要注意数据的范围。

#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N = (1<<20) | 0x10;
const LL INF = ((LL)1 << 60);
LL f[N];
int n, m;
LL b;
struct node{
    int x, n;
    int slo;
}a[110];

bool cmp(node a, node b){
    return a.n < b.n;
}

int main(){
    scanf("%d%d%I64d", &n, &m, &b);
    for(int i = 0; i < n; ++i){
        int x, k, t;
        scanf("%d%d%d", &a[i].x, &a[i].n, &t);
        for(int j = 0; j < t; ++j){
            int num;
            scanf("%d", &num);
            a[i].slo |= 1 << (num - 1);
        }
    }

    sort(a, a + n, cmp);
   // memset(f, INF, sizeof(INF));
    for(int i = 1; i < (1<<m); ++i){
        f[i] = INF;
    }
    LL ans = INF;
    for(int i = 0; i < n; ++i){
        for(int j = 0; j < (1<<m); ++j){
            LL tmp = (LL)a[i].x + f[j];
            if(tmp < f[j|a[i].slo])
                f[j|a[i].slo] = tmp;
        }
        if(ans > f[(1 << m) - 1] + a[i].n * b)
            ans = f[(1 << m) - 1] + a[i].n * b;
    }
    if(ans == INF) ans = -1;
    printf("%lld\n", ans);
    return 0;
}



E题:看了别人的思路。 同样是一道构造题。用到了矩阵的知识。 给出m, n 要求构造出一个矩阵满足, 每一行每一列的数平方和都是一个完全平方数。 思路很巧。 考虑到m*1和1*n的两个矩阵, 假如这两个矩阵都满足平方和为完全平方数的话, 那么这两个矩阵的乘积就是一个满足条件的矩阵(自己试试看)。问题转化为给出一个n,如何构造n个数使他们的平方和为完全平方数。 考虑这个等式:(n-1)+ (n/2 - 1)^2 = (n/2)^2; 由此可知, 在n等于偶数的情况下,n-1个1 和 一个 (n/2-1)可以构造成功。 如果n是奇数如何解决?可以将其中的一个1变成2,那么通过调整之后可以知道(n+1)/2 , 2, n-2满足条件。

#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
const int N = 110;
int a[N], b[N];

void gao(int n, int *a){
    if(n == 1) a[0] = 1;
    else if(n == 2){
        a[0] = 3;
        a[1] = 4;
    }
    else{
        if(n & 1){
            for(int i = 0; i < n - 2; ++i) a[i] = 1;
            a[n-2] = 2;
            a[n-1] = (n >> 1) + 1;
        }
        else{
            for(int i = 0; i < n - 1; ++i) a[i] = 1;
            a[n-1] = (n >> 1) - 1;
        }
    }
}

int main(){
    int n, m;
    scanf("%d%d", &m, &n);
    gao(m, a);
    gao(n, b);
    for(int i = 0; i < m; ++i){
        for(int j = 0; j < n; ++j)
            printf("%d ", a[i]*b[j]);
        printf("\n");
    }
    return 0;
}



/** ****************************************************************************** * @file main.c * @author MCU Application Team * @brief Main program body ****************************************************************************** * @attention * * <h2><center>© Copyright (c) Puya Semiconductor Co. * All rights reserved.</center></h2> * * <h2><center>© Copyright (c) 2016 STMicroelectronics. * All rights reserved.</center></h2> * * This software component is licensed by ST under BSD 3-Clause license, * the "License"; You may not use this file except in compliance with the * License. You may obtain a copy of the License at: * opensource.org/licenses/BSD-3-Clause * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "main.h" #include "string.h" #include "py32f002b_it.h" #include "py32f002b_hal_tim.h" #include <stdio.h> #include <stdlib.h> // for abs() EXTI_HandleTypeDef exti_handle; UART_HandleTypeDef UartHandle; TIM_HandleTypeDef TimHandle; TIM_HandleTypeDef TimHandle14; TIM_OC_InitTypeDef sConfigOC = {0}; // 定义并初始化sConfigOC // 红外协议参数 #define NEC_HEADER_HIGH 9000 // 9ms引导码高电平 #define NEC_HEADER_LOW 4500 // 4.5ms引导码低电平 #define NEC_BIT_HIGH 3900 // 调整为实际测量的约3900us #define NEC_BIT_ONE_LOW 3900 // 调整为实际测量的约3900us #define NEC_BIT_ZERO_LOW 3900 // 调整为实际测量的约3900us /* 容差范围 */ #define NEC_HEADER_TOLERANCE 1000 // 引导码容差1ms #define NEC_BIT_TOLERANCE 500 // 数据位容差500us #define IR_MAX_PULSE_CNT 100 /* Private define ------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ volatile uint32_t timer1_overflow_count = 0; // TIM1溢出计数 /* Private user code ---------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/ /* Private function prototypes -----------------------------------------------*/ // 系统时钟频率(根据配置为24MHz) #define SYSTEM_CLOCK_FREQ 24000000 // 定义红外遥控按键对应的功能 #define KEY_POWER 0x01 #define KEY_ON 0xc0 #define KEY_OFF 0x40 #define KEY_RED 0x20 #define KEY_GREEN 0xA0 #define KEY_BLUE 0x60 #define KEY_WHITE 0xE0 #define KEY_FLASH 0xD0 #define KEY_SMOOTH 0xC8 #define KEY_YELLOW 0x06 #define KEY_CYAN 0x07 #define KEY_MAGENTA 0x08 #define KEY_BRIGHT_UP 0x00 #define KEY_BRIGHT_DN 0x80 #define KEY_MODE_NEXT 0x0B #define KEY_TIMER 0x28 #define KEY_SPEED_UP 0xA8 #define KEY_SPEED_DOWN 0x68 #define KEY_WARM 0x30 #define PWM_MAX 1000 // 满占空比 #define FADE_STEP 5 // 渐变步进 #define FADE_DELAY 10 // 每步延时(ms) #define BLUE_CHANNEL TIM_CHANNEL_1 #define GREEN_CHANNEL TIM_CHANNEL_2 #define RED_CHANNEL TIM_CHANNEL_3 #define WHITE_CHANNEL TIM_CHANNEL_4 // LED引脚定义 #define LED_RED_PIN GPIO_PIN_5 #define LED_GREEN_PIN GPIO_PIN_3 #define LED_BLUE_PIN GPIO_PIN_4 #define LED_WHITE_PIN GPIO_PIN_1 #define LED_ALL_PINS (LED_RED_PIN | LED_GREEN_PIN | LED_BLUE_PIN) // 白光呼吸灯参数 #define WARM_BRIGHTNESS_LEVELS 3 // 三种亮度等级 #define WARM_MODE 7 // 白光呼吸模式标识 uint8_t warm_brightness_level = 0; // 亮度等级(0-2对应3种亮度) uint16_t breath_speed = 20; // 呼吸速度(ms/步,值越小越快) // 三种亮度等级的最大亮度(0-100) const uint8_t warm_max_brightness[WARM_BRIGHTNESS_LEVELS] = {70, 40, 0}; // 全局变量 uint8_t ir_data[4] = {0}; // 红外数据缓冲区 uint8_t ir_data_len = 0; // 数据长度 uint8_t ir_repeat_flag = 0; // 重复码标志 uint8_t ir_last_cmd = 0; // 上一次命令 uint32_t last_int_time = 0; // 上一次中断时间戳 uint8_t decode_state = 0; // 解码状态机 uint8_t current_mode = 0; // 0-静态颜色, 1-呼吸模式, 2-颜色渐变 uint8_t current_brightness = 100; // 亮度0-100 (百分比) uint8_t color_r = 0; // 当前红色分量(0-100%) uint8_t color_g = 0; // 当前绿色分量(0-100%) uint8_t color_b = 0; // 当前蓝色分量(0-100%) uint8_t color_w = 0; //当前白色分量 uint8_t keep_color = 0; //保存当前灯的状态 // 定时器相关变量 // 定时器相关变量 typedef enum { TIMER_IDLE = 0, TIMER_SETTING, TIMER_GRADIENT, TIMER_RUNNING, TIMER_EXPIRED } TimerState_t; TimerState_t timer_state = TIMER_IDLE; uint32_t timer_end_time = 0; uint8_t timer_duration = 0; // 定时时长(小时) uint32_t gradient_start_time = 0; uint8_t gradient_steps = 0; // 保存定时前的状态 uint8_t pre_timer_mode = 0; uint8_t pre_timer_r = 0, pre_timer_g = 0, pre_timer_b = 0, pre_timer_w = 0; uint8_t saved_r = 0, saved_g = 0, saved_b = 0, saved_w = 0; // 全局呼吸参数 uint8_t breath_direction = 1; // 1=渐亮,0=渐暗 uint16_t breath_period = 4000; // 完整呼吸周期(ms) uint32_t last_breath_time = 0; // 上次呼吸更新时间 uint8_t breath_step_interval = 20;// 步进间隔(ms) // 函数声明 void led_extinct(void); void APP_GpioConfig(void); void APP_SystemClockConfig(void); void IR_ProcessCommand(void); void IR_ProcessRepeat(void); void set_led_color(uint8_t r, uint8_t g, uint8_t b, uint8_t w); void set_led_brightness(uint8_t brightness); void next_mode(void); void update_leds(void); void led_off(void); void IR_Decode(uint32_t duration, uint8_t level); void TIM14_Init(void); uint32_t IR_GetMicroseconds(void); // 4组七彩跳变组合(每组7种颜色,包含R/G/B/W分量) const uint16_t color_groups[4][7][4] = { // 第1组:基础彩虹色 { {1000, 0, 0, 0}, // 红 {1000, 647, 0, 0}, // 橙 {1000, 1000, 0, 0}, // 黄 {0, 1000, 0, 0}, // 绿 {0, 1000, 1000, 0}, // 青 {0, 0, 1000, 0}, // 蓝 {1000, 0, 1000, 0} // 紫 }, // 第2组:高饱和混合色 { {1000, 300, 300, 0}, // 粉 {300, 1000, 300, 0}, // 绿蓝 {300, 300, 1000, 0}, // 靛蓝 {1000, 1000, 300, 0}, // 金黄 {1000, 300, 1000, 0}, // 洋红 {300, 1000, 1000, 0}, // 青绿 {500, 500, 500, 0} // 灰 }, // 第3组:低饱和柔和色 { {500, 200, 200, 300}, // 淡红 {500, 400, 200, 300}, // 淡橙 {500, 500, 200, 300}, // 淡黄 {200, 500, 200, 300}, // 淡绿 {200, 500, 500, 300}, // 淡青 {200, 200, 500, 300}, // 淡蓝 {500, 200, 500, 300} // 淡紫 }, // 第4组:含白色混合色 { {1000, 0, 0, 300}, // 红+白 {1000, 600, 0, 300}, // 橙+白 {1000, 1000, 0, 300}, // 黄+白 {0, 1000, 0, 300}, // 绿+白 {0, 1000, 1000, 300}, // 青+白 {0, 0, 1000, 300}, // 蓝+白 {800, 800, 800, 500} // 全白 } }; // 4组七彩渐变颜色组合(每组7种颜色,用于渐变过渡) const uint8_t gradient_groups[4][7][4] = { // 第1组:标准彩虹渐变 { {100, 0, 0, 0}, // 红 {100, 50, 0, 0}, // 橙 {100, 100, 0, 0}, // 黄 {0, 100, 0, 0}, // 绿 {0, 100, 100, 0}, // 青 {0, 0, 100, 0}, // 蓝 {100, 0, 100, 0} // 紫 }, // 第2组:高饱和渐变 { {100, 30, 30, 0}, // 粉 {30, 100, 30, 0}, // 绿蓝 {30, 30, 100, 0}, // 靛蓝 {100, 100, 30, 0}, // 金黄 {100, 30, 100, 0}, // 洋红 {30, 100, 100, 0}, // 青绿 {50, 50, 50, 0} // 灰 }, // 第3组:柔和渐变(含白色) { {80, 20, 20, 20}, // 淡红 {80, 60, 20, 20}, // 淡橙 {80, 80, 20, 20}, // 淡黄 {20, 80, 20, 20}, // 淡绿 {20, 80, 80, 20}, // 淡青 {20, 20, 80, 20}, // 淡蓝 {80, 20, 80, 20} // 淡紫 }, // 第4组:暖色渐变 { {100, 20, 0, 10}, // 暖红 {100, 60, 0, 10}, // 暖橙 {100, 100, 20, 10}, // 暖黄 {60, 100, 0, 10}, // 暖绿 {20, 80, 40, 10}, // 暖青 {0, 40, 80, 10}, // 暖蓝 {60, 20, 80, 10} // 暖紫 } }; // 渐变模式全局变量 uint8_t current_gradient_group = 0; // 当前渐变组索引(0-3) uint8_t gradient_step = 0; // 组内渐变步骤(0-100) uint8_t gradient_from_idx = 0; // 起始颜色索引 uint8_t gradient_to_idx = 1; // 目标颜色索引 // 新增全局变量跟踪当前组和组内颜色 uint8_t current_color_group = 0; // 当前组索引(0-3) static uint8_t group_step_idx = 0; // 当前组内颜色索引(0-6) // 6组三色跳变组合 (每组3种颜色,每种颜色包含R/G/B/W分量) const uint8_t jump_color_groups[6][3][4] = { // 第1组:红→绿→蓝 {{100,0,0,0}, {0,100,0,0}, {0,0,100,0}}, // 第2组:黄→青→紫 {{100,100,0,0}, {0,100,100,0}, {100,0,100,0}}, // 第3组:橙→绿蓝→粉 {{100,50,0,0}, {0,50,100,0}, {100,30,70,0}}, // 第4组:暖白→冷白→中性白 {{80,40,10,30}, {10,40,80,50}, {40,40,40,80}}, // 第5组:深红→深绿→深蓝 {{50,0,0,0}, {0,50,0,0}, {0,0,50,0}}, // 第6组:红+白→绿+白→蓝+白 {{100,0,0,50}, {0,100,0,50}, {0,0,100,50}} }; uint8_t jump_group_index = 0; // 当前组合索引(0-5) uint8_t current_jump_color = 0; // 当前组内颜色索引(0-2) uint32_t jump_timer = 0; // 跳变计时器 uint16_t jump_interval = 800; // 每组颜色停留时间(ms) /** * @brief TIM1初始化,配置为1MHz计数(1us计数一次) * @retval None */ /*int fputc(int ch, FILE *f) { HAL_UART_Transmit(&UartHandle, (uint8_t *)&ch, 1, HAL_MAX_DELAY); return ch; }*/ typedef enum { RAINBOW_STOP = 0, RAINBOW_RUN } RainbowState_t; // 全局变量 static uint16_t cur[4] = {0}; // 当前占空比 static uint32_t last_tick = 0; void delay_us(uint32_t us) { uint32_t tickstart = IR_GetMicroseconds(); while ((IR_GetMicroseconds() - tickstart) < us); } int fputc(int ch, FILE *f) { HAL_UART_Transmit(&UartHandle, (uint8_t *)&ch, 1, HAL_MAX_DELAY); return ch; } //配置计数器 void TIM14_Init(void) { __HAL_RCC_TIM14_CLK_ENABLE(); // 对于24MHz的系统时钟,分频到1MHz TimHandle14.Instance = TIM14; TimHandle14.Init.Prescaler = 24 - 1; // 24分频得到1MHz TimHandle14.Init.CounterMode = TIM_COUNTERMODE_UP; TimHandle14.Init.Period = 0xffff; // 16位计数器 TimHandle14.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; TimHandle14.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; HAL_NVIC_SetPriority(TIM1_BRK_UP_TRG_COM_IRQn, 1, 0); HAL_NVIC_EnableIRQ(TIM1_BRK_UP_TRG_COM_IRQn); if (HAL_TIM_Base_Init(&TimHandle14) != HAL_OK) { APP_ErrorHandler(); } // 清空计数器 __HAL_TIM_SET_COUNTER(&TimHandle14, 0); // 启动定时器 HAL_TIM_Base_Start(&TimHandle14); HAL_NVIC_SetPriority(TIM14_IRQn, 1, 0); HAL_NVIC_EnableIRQ(TIM14_IRQn); } //配置pwm发生器 void APP_TimPwmConfig(void) { __HAL_RCC_TIM1_CLK_ENABLE(); // 对于24MHz的系统时钟,分频到1MHz TimHandle.Instance = TIM1; TimHandle.Init.Prescaler = 24 - 1; // 24分频得到1MHz TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP; TimHandle.Init.Period = 1000-1; // 重载值 TimHandle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; TimHandle.Init.RepetitionCounter = 0; TimHandle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; if (HAL_TIM_Base_Init(&TimHandle) != HAL_OK) { APP_ErrorHandler(); } // 清空计数器 __HAL_TIM_SET_COUNTER(&TimHandle, 0); // 启动定时器 HAL_TIM_Base_Start(&TimHandle); sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; /* OCN channel output high level effective */ sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH; /* Idle state OC1N output low level */ sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET; /* Idle state OC1 output low level*/ sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET; sConfigOC.Pulse = 0; /* Channel 1 configuration */ if (HAL_TIM_PWM_ConfigChannel(&TimHandle, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) { APP_ErrorHandler(); } sConfigOC.Pulse = 0; /* Channel 2 configuration */ if (HAL_TIM_PWM_ConfigChannel(&TimHandle, &sConfigOC, TIM_CHANNEL_2) != HAL_OK) { APP_ErrorHandler(); } sConfigOC.Pulse = 0; /* Channel 3 configuration */ if (HAL_TIM_PWM_ConfigChannel(&TimHandle, &sConfigOC, TIM_CHANNEL_3) != HAL_OK) { APP_ErrorHandler(); } sConfigOC.Pulse = 0; /* Channel 4 configuration */ if (HAL_TIM_PWM_ConfigChannel(&TimHandle, &sConfigOC, TIM_CHANNEL_4) != HAL_OK) { APP_ErrorHandler(); } HAL_TIM_PWM_Start(&TimHandle, RED_CHANNEL); HAL_TIM_PWM_Start(&TimHandle, GREEN_CHANNEL); HAL_TIM_PWM_Start(&TimHandle, BLUE_CHANNEL); HAL_TIM_PWM_Start(&TimHandle, WHITE_CHANNEL); __HAL_TIM_SET_COMPARE(&TimHandle, TIM_CHANNEL_1,1000); // 设置红色通道占空比 __HAL_TIM_SET_COMPARE(&TimHandle, TIM_CHANNEL_2,1000); // 设置绿色通道占空比 __HAL_TIM_SET_COMPARE(&TimHandle, TIM_CHANNEL_3, 1000); // 设置蓝色通道占空比 __HAL_TIM_SET_COMPARE(&TimHandle, TIM_CHANNEL_4, 1000); // 设置白色通道占空比 __HAL_TIM_MOE_ENABLE(&TimHandle); } // 设置RGB颜色 void set_rgb_color(uint16_t r, uint16_t g, uint16_t b) { __HAL_TIM_SET_COMPARE(&TimHandle, RED_CHANNEL, r); __HAL_TIM_SET_COMPARE(&TimHandle, GREEN_CHANNEL, g); __HAL_TIM_SET_COMPARE(&TimHandle, BLUE_CHANNEL, b); } /** * @brief TIM14更新中断处理函数 * @retval None */ void TIM14_IRQHandler(void) { // 只处理更新中断 if (__HAL_TIM_GET_FLAG(&TimHandle14, TIM_FLAG_UPDATE)) { __HAL_TIM_CLEAR_FLAG(&TimHandle14, TIM_FLAG_UPDATE); timer1_overflow_count++; } } uint32_t millis(void) { return timer1_overflow_count; } /** * @brief 获取当前微秒数(使用TIM1实现) * @retval 当前时间(us) */ uint32_t IR_GetMicroseconds(void) { uint32_t time; do { time = __HAL_TIM_GET_COUNTER(&TimHandle14); } while(time != __HAL_TIM_GET_COUNTER(&TimHandle14)); return time; } // 计算两个时间点之间的差值 uint32_t Calculate_Duration(uint32_t current, uint32_t last) { if(current >= last) { return current - last; } else { // 处理计数器溢出 return (0xFFFF - last) + current + 1; } } void LED_Init(void) { // 1. 使能LED所在GPIO端口的时钟(根据实际端口修改) __HAL_RCC_GPIOA_CLK_ENABLE(); // 若LED接GPIOA,则使能GPIOA时钟 // 2. 定义GPIO初始化结构体 GPIO_InitTypeDef GPIO_InitStruct; // 3. 配置LED引脚参数 GPIO_InitStruct.Pin = GPIO_PIN_1; // 选择LED引脚 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // 推挽输出(适合驱动LED) GPIO_InitStruct.Pull = GPIO_NOPULL; // 无上下拉(根据硬件电路决定) GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; // 低速模式(LED无需高速切换) // 4. 初始化GPIO HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // 5. 初始状态:关闭LED(根据硬件电路决定高低电平) // 假设LED为高电平点亮:初始输出低电平=关闭 HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1, GPIO_PIN_SET); } /** * @brief EXTI中断服务函数(双边沿触发) * @retval None */ void EXTI0_1_IRQHandler(void) { static uint32_t last_edge_time = 0; static uint8_t last_pin_state = 1; static uint8_t is_first_edge = 1; // 使用uint8_t代替bool if (__HAL_GPIO_EXTI_GET_FLAG(GPIO_PIN_0) != RESET) { __HAL_GPIO_EXTI_CLEAR_FLAG(GPIO_PIN_0); uint32_t current_time = IR_GetMicroseconds(); uint8_t current_pin_state = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0); if (is_first_edge) { is_first_edge = 0; // 使用0代替false last_edge_time = current_time; last_pin_state = current_pin_state; printf("First edge: level=%d\n", current_pin_state); return; } if (current_pin_state != last_pin_state) // 确认电平真的变化了 { uint32_t duration = Calculate_Duration(current_time, last_edge_time); // 过滤掉可能的噪声脉冲 if (duration >= 100) // 最小100us { IR_Decode(duration, current_pin_state); } last_edge_time = current_time; last_pin_state = current_pin_state; } } } void Test_Timer_Accuracy(void) { uint32_t start, end, elapsed; printf("Timer accuracy test:\r\n"); start = IR_GetMicroseconds(); HAL_Delay(1000); // 延时1秒 end = IR_GetMicroseconds(); elapsed = end - start; printf("1000ms delay = %lu us\r\n", elapsed); } /** * @brief 红外解码状态机 * @param duration: 脉冲持续时间(us) * @param level_type: 电平类型 (1=高电平结束, 0=低电平结束) * @retval None */ #define NEC_TOLERANCE 300 void IR_Decode(uint32_t duration, uint8_t level_type) { static uint8_t state = 0; static uint8_t bit_index = 0; static uint8_t data[4] = {0}; switch (state) { case 0: // 等待引导码高电平 if (level_type == 1 && abs(duration - 9000) < NEC_TOLERANCE) { state = 1; } break; case 1: // 等待引导码低电平 if (level_type == 0 && abs(duration - 4500) < NEC_TOLERANCE) { memset(data, 0, 4); bit_index = 0; state = 2; } else if (level_type == 0 && abs(duration - 2250) < NEC_TOLERANCE) { // 重复码 IR_ProcessRepeat(); state = 0; } else { state = 0; } break; case 2: // 等待位高电平(560us) if (level_type == 1 && abs(duration - 560) < NEC_TOLERANCE) { state = 3; } else { state = 0; } break; case 3: // 等待位低电平(判断逻辑0或1) if (level_type == 0) { if (abs(duration - 560) < NEC_TOLERANCE) { // 逻辑0,不设置位 } else if (abs(duration - 1690) < NEC_TOLERANCE) { // 逻辑1,设置位 data[bit_index / 8] |= (1 << (7 - (bit_index % 8))); } else { state = 0; return; } bit_index++; if (bit_index >= 32) { memcpy(ir_data, data, 4); IR_ProcessCommand(); state = 0; } else { state = 2; } } break; default: state = 0; break; } } //串口 void MX_USART1_UART_Init(uint32_t bound) { UartHandle.Instance = USART1; UartHandle.Init.BaudRate = bound; UartHandle.Init.WordLength = UART_WORDLENGTH_8B; UartHandle.Init.StopBits = UART_STOPBITS_1; UartHandle.Init.Parity = UART_PARITY_NONE; UartHandle.Init.Mode = UART_MODE_TX_RX; UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE; UartHandle.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&UartHandle) != HAL_OK) { APP_ErrorHandler(); } // 使能接收中断 __HAL_UART_ENABLE_IT(&UartHandle, UART_IT_RXNE); } void HAL_UART_spInit(UART_HandleTypeDef* huart) { GPIO_InitTypeDef GPIO_InitStruct = {0}; if(huart->Instance==USART1) { __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_USART1_CLK_ENABLE(); // -> USART_TX GPIO_InitStruct.Pin = GPIO_PIN_4; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Alternate = DEBUG_USART_TX_AF; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); // -> USART_RX GPIO_InitStruct.Pin = GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Alternate = DEBUG_USART_RX_AF; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); // 配置USART1中断 HAL_NVIC_SetPriority(USART1_IRQn, 0, 1); HAL_NVIC_EnableIRQ(USART1_IRQn); } } // 白光呼吸任务函数 void warm_breath_task(void) { if (keep_color != WARM_MODE) return; static uint8_t direction = 1; // 1=渐暗, 0=渐亮 static uint8_t brightness = 0; // 0=最亮, 100=最暗 static uint32_t last_update = 0; static uint8_t initialized = 0; // 用于初始化亮度 // 检查是否到达更新时间 if (HAL_GetTick() - last_update < breath_speed) return; last_update = HAL_GetTick(); // 获取当前亮度级别的最大值 const uint8_t max_bright = warm_max_brightness[warm_brightness_level]; // 初始化亮度为当前级别的最大值 if (!initialized) { brightness = max_bright; initialized = 1; } if (direction) { // 渐暗 (亮度值增加) if (brightness < 100) { // 最大亮度为100 brightness++; } else { direction = 0; // 切换为渐亮 } } else { // 渐亮 (亮度值减小) if (brightness > max_bright) { brightness--; } else { direction = 1; // 切换为渐暗 } } // 设置白灯亮度(RGB关闭) set_led_color(100, 100, 100, brightness); printf("速率:%d ms, 亮度:%d\n", breath_speed, brightness); } static void rgbw_fade_task(void) { if (keep_color != 1) { return; } // 根据当前组索引获取目标颜色 const uint16_t *tar = color_groups[current_color_group][group_step_idx]; uint8_t done = 1; for (uint8_t ch = 0; ch < 4; ch++) { if (cur[ch] < tar[ch]) { cur[ch] += 5; // 步进递增 if (cur[ch] > tar[ch]) cur[ch] = tar[ch]; done = 0; } else if (cur[ch] > tar[ch]) { cur[ch] -= 5; // 步进递减 if (cur[ch] < tar[ch]) cur[ch] = tar[ch]; done = 0; } } // 设置当前颜色(转换为0-100范围) set_led_color( cur[0] / 10, cur[1] / 10, cur[2] / 10, cur[3] / 10 ); // 颜色切换条件:当前颜色已到达目标,且停留时间超过1秒 if (done && (HAL_GetTick() - last_tick > 1000)) { // 切换到组内下一种颜色(0-6循环) group_step_idx = (group_step_idx + 1) % 7; last_tick = HAL_GetTick(); } } // 多组七彩渐变函数 void multi_group_gradient(uint8_t speed) { // 从当前组获取起始色和目标色 const uint8_t *from = gradient_groups[current_gradient_group][gradient_from_idx]; const uint8_t *to = gradient_groups[current_gradient_group][gradient_to_idx]; // 计算当前步骤的RGBW值(线性插值) uint8_t current_r = from[0] + (to[0] - from[0]) * gradient_step / 100; uint8_t current_g = from[1] + (to[1] - from[1]) * gradient_step / 100; uint8_t current_b = from[2] + (to[2] - from[2]) * gradient_step / 100; uint8_t current_w = from[3] + (to[3] - from[3]) * gradient_step / 100; // 设置当前颜色 set_led_color(current_r, current_g, current_b, current_w); // 步骤递增 gradient_step++; if (gradient_step > 100) { gradient_step = 0; // 切换到组内下一对颜色(循环7种颜色) gradient_from_idx = gradient_to_idx; gradient_to_idx = (gradient_to_idx + 1) % 7; } // 控制渐变速度 HAL_Delay(speed); } // 更新渐变任务调用 void gradient_task(void) { multi_group_gradient(30); // 调用多组渐变函数,速度30ms } // 三色跳变任务函数(在main循环中调用) void color_jump_task(void) { // 仅在跳变模式(keep_color=6)下执行 if (keep_color != 6) return; // 检查是否到达跳变时间 if (HAL_GetTick() - jump_timer >= jump_interval) { // 切换到组内下一种颜色 current_jump_color = (current_jump_color + 1) % 3; // 设置当前颜色 set_led_color( jump_color_groups[jump_group_index][current_jump_color][0], jump_color_groups[jump_group_index][current_jump_color][1], jump_color_groups[jump_group_index][current_jump_color][2], jump_color_groups[jump_group_index][current_jump_color][3] ); // 重置计时器 jump_timer = HAL_GetTick(); } } void reset_timer(void) { timer_state = TIMER_IDLE; timer_duration = 0; timer_end_time = 0; printf("定时器已重置\n"); } // 添加定时器状态处理函数 void timer_task(void) { switch (timer_state) { case TIMER_GRADIENT: // 显示红绿蓝渐变效果 if (HAL_GetTick() - gradient_start_time > 500) { // 每100ms更新一次 gradient_start_time = HAL_GetTick(); switch (gradient_steps) { case 0: // 红色 set_led_color(0, 100, 100, 100); break; case 1: // 绿色 set_led_color(100, 0, 100, 100); break; case 2: // 蓝色 set_led_color(100, 100, 0, 100); break; case 3: // 恢复原状态 // 启动定时器 timer_state = TIMER_RUNNING; timer_end_time = HAL_GetTick() + (timer_duration * 3600000); // 转换为毫秒 printf("定时器启动,将在 %d 小时后关灯\n", timer_duration); // 恢复原状态 keep_color = pre_timer_mode; set_led_color(pre_timer_r, pre_timer_g, pre_timer_b, pre_timer_w); return; } gradient_steps++; } break; case TIMER_RUNNING: // 检查是否到达定时结束时间 if (HAL_GetTick() >= timer_end_time) { timer_state = TIMER_EXPIRED; printf("定时结束,关闭灯光\n"); // 关闭所有灯光 led_off(); } break; case TIMER_EXPIRED: // 5秒后自动重置定时器 if (HAL_GetTick() - timer_end_time > 5000) { timer_state = TIMER_IDLE; printf("定时器已重置,可重新设置\n"); } break; default: break; } } /** * @brief Main program. * @retval int */ int main(void) { HAL_Init(); APP_SystemClockConfig(); __HAL_RCC_USART1_CLK_ENABLE(); // 确保USART1时钟先使能 MX_USART1_UART_Init(115200); HAL_UART_spInit(&UartHandle); // HAL_Delay(100); //串口初始化 // HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_1); // 初始化TIM1用于微秒级计时 TIM14_Init(); // 初始化GPIO和EXTI APP_GpioConfig(); APP_TimPwmConfig(); // 测试定时器精度 // Test_Timer_Accuracy(); // 初始化LED LED_Init(); current_gradient_group = 0; gradient_from_idx = 0; gradient_to_idx = 1; gradient_step = 0; // 初始化为第1组第一种颜色 current_color_group = 0; group_step_idx = 0; // 初始化当前占空比数组 memcpy(cur, color_groups[0][0], sizeof(cur)); // 初始关闭LED set_led_color(0, 0, 0, 0); printf("holle world\r\n"); //light_seven(); //set_led_color(0, 0, 0, 0); // 初始关闭所有LED while (1) { // 处理定时器任务 timer_task(); // 如果定时器处于渐变状态,跳过其他任务 if (timer_state != TIMER_GRADIENT && timer_state != TIMER_EXPIRED) { // 原有模式处理... if (keep_color == 0) { gradient_task(); // 渐变 } else if (keep_color == 1) { rgbw_fade_task(); // 跳变 } else if (keep_color == 6) { color_jump_task(); // 三色跳变 } else if (keep_color == WARM_MODE) { warm_breath_task(); // 白光呼吸 } } } } void USART1_IRQHandler(void) { HAL_UART_IRQHandler(&UartHandle); } static void APP_SystemClockConfig(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV1; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_24MHz; HAL_RCC_OscConfig(&RCC_OscInitStruct); RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSISYS; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0); } static void APP_GpioConfig(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); // 配置红,绿,蓝引脚 GPIO_InitStruct.Pin = LED_ALL_PINS; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF2_TIM1; //复用为TIM1 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); //配置白引脚 GPIO_InitStruct.Pin = LED_WHITE_PIN; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF3_TIM1; //复用为TIM1 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); // 配置红外接收引脚(PA0)为双边沿触发 GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // 配置外部中断 HAL_NVIC_SetPriority(EXTI0_1_IRQn, 0, 0); HAL_NVIC_EnableIRQ(EXTI0_1_IRQn); } /** * @brief 设置LED颜色 * @param r: 红色分量 (0-100) * @param g: 绿色分量 (0-100) * @param b: 蓝色分量 (0-100) * @param w: 白色分量 (0-100) * @retval None */ void set_led_color(uint8_t r, uint8_t g, uint8_t b, uint8_t w) { color_r = r; color_g = g; color_b = b; color_w = w; uint16_t rr = (uint16_t)r * PWM_MAX / 100 ; uint16_t gg = (uint16_t)g * PWM_MAX / 100 ; uint16_t bb = (uint16_t)b * PWM_MAX / 100 ; uint16_t ww = (uint16_t)w * PWM_MAX / 100 ; // uint16_t ww = PWM_MAX - (uint16_t)w * PWM_MAX / 100 ; // 反转计算 __HAL_TIM_SET_COMPARE(&TimHandle, RED_CHANNEL, rr); __HAL_TIM_SET_COMPARE(&TimHandle, GREEN_CHANNEL, gg); __HAL_TIM_SET_COMPARE(&TimHandle, BLUE_CHANNEL, bb); __HAL_TIM_SET_COMPARE(&TimHandle, WHITE_CHANNEL, ww); } // 12种DIY颜色(每组4种,共3组) static const uint8_t diy_colors[4][4][4] = { // R组(KEY_RED) { {100, 0, 0, 0}, // 纯红 {100, 30, 0, 0}, // 红橙 {100, 0, 30, 0}, // 红紫 {100, 50, 0, 0} // 深红 }, // G组(KEY_GREEN) { {0, 100, 0, 0}, // 纯绿 {30, 100, 0, 0}, // 黄绿 {0, 100, 30, 0}, // 青绿 {50, 100, 0, 0} // 草绿 }, // B组(KEY_BLUE) { {0, 0, 100, 0}, // 纯蓝 {30, 0, 100, 0}, // 紫蓝 {0, 30, 100, 0}, // 天蓝 {0, 0, 100, 50} // 冰蓝 }, { {100, 100, 100, 0}, // 纯蓝 {71, 84, 100, 45}, // 暖白 - 偏黄红色调 {44,68, 100, 88}, // 正白 - 均衡色调 } }; static uint8_t color_index[4] = {0}; // 每组当前颜色索引 /** * @brief 关闭所有LED * @retval None */ void led_off(void) { HAL_TIM_PWM_Stop(&TimHandle, RED_CHANNEL); HAL_TIM_PWM_Stop(&TimHandle, GREEN_CHANNEL); HAL_TIM_PWM_Stop(&TimHandle, BLUE_CHANNEL); HAL_TIM_PWM_Stop(&TimHandle, WHITE_CHANNEL); //HAL_TIM_Base_Start(&TimHandle); } void led_extinct(void) { set_led_color(100,100,100,100); } void three_color (void) { led_off(); HAL_TIM_PWM_Start(&TimHandle, RED_CHANNEL); led_off(); HAL_TIM_PWM_Start(&TimHandle, GREEN_CHANNEL); } /** * @brief 处理解码后的指令 * @retval None */ void IR_ProcessCommand(void) { // 如果定时器处于渐变状态,忽略所有按键 if (timer_state == TIMER_GRADIENT) { printf("渐变中,忽略按键\n"); return; } // 如果定时器已到期,只响应KEY_ON if (timer_state == TIMER_EXPIRED && ir_data[2] != KEY_ON) { printf("灯光已关闭,请按ON键开启\n"); return; // 忽略其他按键 } ir_last_cmd = ir_data[2]; // 保存命令 // 打印完整的NEC协议数据帧 printf("\r\n=== IR Code Received ===\r\n"); printf("Address: 0x%02X%02X\r\n", ir_data[0], ir_data[1]); printf("Command: 0x%02X\r\n", ir_data[2]); printf("Cmd Inverse: 0x%02X\r\n", ir_data[3]); printf("=====================\r\n"); HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_1); // 验证命令码和其反码是否匹配 if(ir_data[2] != (uint8_t)(~ir_data[3])) { printf("Warning: Command verification failed!\r\n"); return; } switch (ir_last_cmd) { case KEY_OFF: // 保存当前颜色 saved_r = color_r; saved_g = color_g; saved_b = color_b; saved_w = color_w ; led_off(); led_extinct(); break; case KEY_ON: // 如果定时器已到期,恢复定时前的状态 if (timer_state == TIMER_EXPIRED) { timer_state = TIMER_IDLE; // 恢复PWM输出 HAL_TIM_PWM_Start(&TimHandle, RED_CHANNEL); HAL_TIM_PWM_Start(&TimHandle, GREEN_CHANNEL); HAL_TIM_PWM_Start(&TimHandle, BLUE_CHANNEL); HAL_TIM_PWM_Start(&TimHandle, WHITE_CHANNEL); // 恢复之前的状态 keep_color = pre_timer_mode; set_led_color(pre_timer_r, pre_timer_g, pre_timer_b, pre_timer_w); printf("恢复定时前状态\n"); } else { // 正常处理KEY_ON HAL_TIM_PWM_Start(&TimHandle, RED_CHANNEL); HAL_TIM_PWM_Start(&TimHandle, GREEN_CHANNEL); HAL_TIM_PWM_Start(&TimHandle, BLUE_CHANNEL); HAL_TIM_PWM_Start(&TimHandle, WHITE_CHANNEL); set_led_color(saved_r, saved_g, saved_b, saved_w); } break; case KEY_RED: keep_color =2; //led_extinct(); set_led_color(0, 100, 100, 100); break; case KEY_FLASH: // 切换到下一组,第5次按回归第1组(0-3循环) current_color_group = (current_color_group + 1) % 4; // 重置组内颜色索引,从第一种颜色开始 group_step_idx = 0; // 立即切换到新组的第一种颜色 set_led_color( color_groups[current_color_group][group_step_idx][0] / 10, // 转换为0-100范围 color_groups[current_color_group][group_step_idx][1] / 10, color_groups[current_color_group][group_step_idx][2] / 10, color_groups[current_color_group][group_step_idx][3] / 10 ); // 重置跳变计时器 last_tick = HAL_GetTick(); // 打印当前组信息 printf("切换到七彩跳变组合 %d/4\r\n", current_color_group + 1); // 激活七彩跳变模式 keep_color = 1; break; case KEY_GREEN: keep_color =3; led_extinct(); //HAL_TIM_PWM_Start(&TimHandle, GREEN_CHANNEL); set_led_color(100, 0, 100, 100); break; case KEY_BLUE: keep_color =4; led_extinct(); //HAL_TIM_PWM_Start(&TimHandle, BLUE_CHANNEL); set_led_color(100, 100, 0, 100); break; case KEY_WHITE: keep_color =5; led_extinct(); //HAL_TIM_PWM_Start(&TimHandle, WHITE_CHANNEL); set_led_color(100, 100, 100, 0); break; case KEY_BRIGHT_UP: switch(keep_color) { case 2: // 当前为红色 color_r = (color_r < 5) ? 0 : color_r - 5; break; case 3: // 当前为绿色 color_g = (color_g < 5) ? 0 : color_g - 5; break; case 4: // 当前为蓝色 color_b = (color_b < 5) ? 0 : color_b - 5; break; case 5: // 当前为白色 color_w = (color_w < 5) ? 0 : color_w - 5; break; } set_led_color(color_r, color_g, color_b, color_w); // 刷新显示 break; case KEY_BRIGHT_DN: switch(keep_color) { case 2: // 当前为红色 color_r = (color_r + 15 > 90) ? 90 : color_r + 15; break; case 3: // 当前为绿色 color_g = (color_g + 15 > 90) ? 90 : color_g + 15; break; case 4: // 当前为蓝色 color_b = (color_b + 15 > 90) ? 90 : color_b + 15; break; case 5: // 当前为白色 color_w = (color_w + 15 > 90) ? 90: color_w + 15; break; } set_led_color(color_r, color_g, color_b, color_w); // 刷新显示 break; case KEY_WARM: // 切换到白光呼吸模式 keep_color = 7; // 循环切换三种亮度等级 warm_brightness_level = (warm_brightness_level + 1) % WARM_BRIGHTNESS_LEVELS; printf("白光呼吸模式: 亮度等级 %d/%d (最大亮度 %d%%)\r\n", warm_brightness_level + 1, WARM_BRIGHTNESS_LEVELS, warm_max_brightness[warm_brightness_level]); break; case KEY_TIMER: // 允许在空闲、渐变结束或定时结束状态下设置定时 if (timer_state == TIMER_IDLE || timer_state == TIMER_EXPIRED) { printf("定时按键被按下\n"); // 重置定时器状态 timer_state = TIMER_SETTING; timer_duration = 0; // 重置定时时长 // 增加定时时长(2小时步进,循环0-12小时) timer_duration = (timer_duration + 2) % 14; if (timer_duration == 0) timer_duration = 2; // 跳过0小时 // 保存当前灯光状态(仅在未过期时) if (timer_state != TIMER_EXPIRED) { pre_timer_mode = keep_color; pre_timer_r = color_r; pre_timer_g = color_g; pre_timer_b = color_b; pre_timer_w = color_w; } // 进入渐变显示状态 timer_state = TIMER_GRADIENT; gradient_start_time = HAL_GetTick(); gradient_steps = 0; // 重置渐变步骤计数器 printf("定时设置: %d小时后关灯\n", timer_duration); } break; case KEY_SPEED_UP: breath_speed = (breath_speed > 5) ? breath_speed - 5 : 5; printf("呼吸加快: %d ms\n", breath_speed); break; case KEY_SPEED_DOWN: printf("11111111111\r\n"); breath_speed = (breath_speed < 100) ? breath_speed + 10 : 100; printf("呼吸加快: %d ms\n", breath_speed); break; case KEY_SMOOTH: // 切换到下一组渐变,第5次按回归第1组(0-3循环) current_gradient_group = (current_gradient_group + 1) % 4; // 重置渐变参数,从新组第1种颜色开始 gradient_from_idx = 0; gradient_to_idx = 1; gradient_step = 0; // 立即显示新组的起始颜色 set_led_color( gradient_groups[current_gradient_group][0][0], gradient_groups[current_gradient_group][0][1], gradient_groups[current_gradient_group][0][2], gradient_groups[current_gradient_group][0][3] ); // 打印当前组信息 printf("切换到七彩渐变组合 %d/4\r\n", current_gradient_group + 1); // 激活渐变模式 keep_color = 0; break; case KEY_MAGENTA: // 切换到下一组组合,第7次按回归第1组 jump_group_index = (jump_group_index + 1) % 6; // 重置当前组内颜色索引,从第一种颜色开始 current_jump_color = 0; // 立即切换到新组的第一种颜色 set_led_color( jump_color_groups[jump_group_index][current_jump_color][0], jump_color_groups[jump_group_index][current_jump_color][1], jump_color_groups[jump_group_index][current_jump_color][2], jump_color_groups[jump_group_index][current_jump_color][3] ); // 重置计时器 jump_timer = HAL_GetTick(); // 打印当前组合信息 printf("切换到三色跳变组合 %d/6\r\n", jump_group_index + 1); // 激活跳变模式 keep_color = 6; break; default: // 未知命令 break; } } /** * @brief 处理重复码 * @retval None */ void IR_ProcessRepeat(void) { ir_last_cmd = ir_data[2]; // 保存命令 printf("Command: 0x%02X\r\n", ir_data[2]); static uint32_t last_repeat_time = 0; if (HAL_GetTick() - last_repeat_time < 500) return; last_repeat_time = HAL_GetTick(); switch (ir_last_cmd) { case KEY_RED: color_index[0] = (color_index[0] + 1) % 4; set_led_color( diy_colors[0][color_index[0]][0], diy_colors[0][color_index[0]][1], diy_colors[0][color_index[0]][2], diy_colors[0][color_index[0]][3] ); break; case KEY_GREEN: color_index[1] = (color_index[1] + 1) % 4; set_led_color( diy_colors[1][color_index[1]][0], diy_colors[1][color_index[1]][1], diy_colors[1][color_index[1]][2], diy_colors[1][color_index[1]][3] ); break; case KEY_BLUE: color_index[2] = (color_index[2] + 1) % 4; set_led_color( diy_colors[2][color_index[2]][0], diy_colors[2][color_index[2]][1], diy_colors[2][color_index[2]][2], diy_colors[2][color_index[2]][3] ); break; case KEY_WHITE: color_index[3] = (color_index[3] + 1) % 4; set_led_color( diy_colors[3][color_index[3]][0], diy_colors[3][color_index[3]][1], diy_colors[3][color_index[3]][2], diy_colors[3][color_index[3]][3] ); break; default: break; } } /** * @brief Error executing function. * @param None * @retval None */ void APP_ErrorHandler(void) { while (1) { } } 为什么我使用定时按键只能定时一次
最新发布
08-09
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值