RGB三色呼吸灯 跑马

//#include "stm32f0xx.h"

#include "head.h"// #include "bsp.h"

// ========== 用户可修改的宏定义 ==========

#define LED_NUM 4 // RGB灯数量

#define BREATH_CYCLE 1200//2000 // 呼吸周期(ms),范围500-3000

#define PHASE_DELAY 100 // 灯间延迟(ms)

#define xdata const

unsigned char xdata sine_tab130 = { //正弦呼吸表

7, 13, 19, 25, 31, 37, 43, 49, 56, 62, 67, 73, 79, 85, 91, 97, 102, 108, 114, 119, 124, 130, 135, 140, 145, 150, 155, 160, 165, 170, 174, 179, 183, 187, 191, 195, 199, 203, 207, 210, 214, 217, 220, 223, 226, 229, 232, 234, 237, 239, 241, 243, 245, 247, 248, 249, 251, 252, 253, 254, 254, 255, 255, 255, 255, 255, 255, 255, 254, 254, 253, 252, 251, 249, 248, 247, 245, 243, 241, 239, 237, 234, 232, 229, 226, 223, 220, 217, 214, 210, 207, 203, 199, 195, 191, 187, 183, 179, 174, 170, 165, 160, 155, 150, 145, 140, 135, 130, 124, 119, 114, 108, 102, 97, 91, 85, 79, 73, 67, 62, 56, 49, 43, 37, 31, 25, 19, 13, 7, 1

};

#define GPIO_t GPIO_InitTypeDef//

#define GPIO_PIN_SET 1

#define GPIO_PIN_RESET 0

#define HAL_GPIO_WritePin(GPIOx,GPIO_Pin_x,val) GPIO_WriteBit((GPIO_TypeDef*)GPIOx,GPIO_Pin_x,val)// val?(GPIOx->ODR |=GPIO_Pin_x):(GPIOx->ODR &=GPIO_Pin_x)// std_gpio_set_pin(GPIOx,GPIO_Pin_x)

#define HAL_GPIO_Init GPIO_Init //std_gpio_get_pin_mode(GPIOx,GPIO_Pin_x);std_gpio_set_pin_output_type(GPIOx,GPIO_Pin_x, GPIO_OUTPUT_PUSHPULL)

// GPIO配置数组(用户需根据实际电路修改)

GPIO_TypeDef* portLED_NUM3 = { // ... 填充所有LED的端口

{GPIOB, GPIOB, GPIOB}, // 灯1: R,G,B

{GPIOA, GPIOA, GPIOA}, // 灯2: R,G,B

{GPIOA, GPIOA, GPIOA}, // 灯3: R,G,B

{GPIOF, GPIOB, GPIOF}, // 灯4: R,G,B

};

uint16_t pinLED_NUM3 = { // ... 填充所有LED的引脚

{GPIO_PIN_2,GPIO_PIN_0, GPIO_PIN_1, }, // 灯1引脚 R G B

{GPIO_PIN_9, GPIO_PIN_8, GPIO_PIN_10}, // 灯2引脚

{GPIO_PIN_12, GPIO_PIN_11, GPIO_PIN_15},// 灯3引脚

{GPIO_PIN_0, GPIO_PIN_8, GPIO_PIN_1}, // 灯4引脚

};

// ========== 全局变量 ==========

volatile uint32_t global_tick = 0; // 200us计时器

uint8_t pwm_counter = 0; // PWM周期计数器(0-100)

int16_t pwm_valLED_NUM3 = {0}; // 各灯RGB当前PWM值

// ========== GPIO初始化 ==========

void GPIO_init_led() {

RCC->AHBENR |= RCC_AHBENR_GPIOAEN|RCC_AHBENR_GPIOBEN|RCC_AHBENR_GPIOCEN|RCC_AHBENR_GPIODEN|RCC_AHBENR_GPIOFEN; // 启用GPIOA时钟(按需添加其他端口)

// for(int i=0; i<LED_NUM; i++) {

// for(int j=0; j<3; j++) {

// std_gpio_set_pin_mode(portij, pinij, GPIO_MODE_OUTPUT); }}

for(int i=0; i<LED_NUM; i++) {

for(int j=0; j<3; j++) {

GPIO_t gpio = {0};

gpio.GPIO_Pin = pinij;//gpio.Pin = pinij;

gpio.GPIO_Mode = GPIO_MODE_OUTPUT;// gpio.Mode = GPIO_MODE_OUTPUT_PP;

//gpio.Speed = GPIO_SPEED_FREQ_HIGH;

gpio.GPIO_PuPd = GPIO_PuPd_NOPULL;

HAL_GPIO_Init(portij, &gpio);

HAL_GPIO_WritePin(portij, pinij, GPIO_PIN_RESET);

}

}

}

// ========== 定时器配置(200us中断) ==========

void TIM_Init(TIM_TypeDef * TIMx) {

if(TIMx==TIM14)

{

RCC->APB1ENR |= RCC_APB1ENR_TIM14EN; // 启用TIM14时钟

NVIC_EnableIRQ(TIM14_IRQn); // 使能中断

NVIC_SetPriority(TIM14_IRQn, 0); // 最高优先级

}

else if(TIMx==TIM3)

{

RCC->APB1ENR |= RCC_APB1ENR_TIM3EN; // 启用TIM3时钟

NVIC_EnableIRQ(TIM3_IRQn); // 使能中断

NVIC_SetPriority(TIM3_IRQn, 0); // 最高优先级=0;最低=3;

}

else if(TIMx==TIM1)

{

RCC->APB2ENR |= RCC_APB2Periph_TIM1; // 启用TIM1时钟

NVIC_EnableIRQ(TIM1_BRK_UP_TRG_COM_IRQn); // 使能中断

NVIC_SetPriority(TIM1_BRK_UP_TRG_COM_IRQn, 0); // 最高优先级

}

TIMx->PSC = 48 - 1; // 48MHz/48 = 1MHz

TIMx->ARR = 200 - 1; // 1MHz/200 = 5kHz (200us)

TIMx->DIER |= TIM_DIER_UIE; // 使能更新中断

TIMx->CR1 |= TIM_CR1_CEN; // 启动定时器

}

// HSV转RGB函数(输入H:0-360 颜色, S:0-1饱和度, V:0-1 亮度;输出R/G/B:0-255)

void HSV2RGB(float h, float s, float v, uint8_t *r, uint8_t *g, uint8_t *b) {

float c = v * s;

float x = c * (1 - fabs(fmod(h/60, 2) - 1));

float m = v - c;

float rt, gt, bt;

if (h < 60) { rt = c; gt = x; bt = 0; }

else if (h < 120) { rt = x; gt = c; bt = 0; }

else if (h < 180) { rt = 0; gt = c; bt = x; }

else if (h < 240) { rt = 0; gt = x; bt = c; }

else if (h < 300) { rt = x; gt = 0; bt = c; }

else { rt = c; gt = 0; bt = x; }

*r = (rt + m) * 255;

*g = (gt + m) * 255;

*b = (bt + m) * 255;

}

// 呼吸效果主循环(示例)

void breathing_effect() {

// float time = get_system_time(); // 获取时间

// float h = fmod(time * 60, 360); // 色相每秒变化60°

// float v = (sin(time * 2) + 1) * 0.5; // 亮度呼吸频率2Hz

// uint8_t r, g, b;

// HSV2RGB(h, 1.0, v, &r, &g, &b); // 固定饱和度100%

// set_led_color(r, g, b); // 更新LED颜色

}

// ========== 中断服务函数 ==========

void TIM3_IRQHandler() {

if(TIM3->SR & TIM_SR_UIF) {

TIM3->SR &= ~TIM_SR_UIF; // 清除中断标志

//void rgb_bright(){

global_tick++; // 全局时间+200us

pwm_counter = (pwm_counter + 1) % 100; // PWM周期计数

// 每10ms更新一次PWM目标值(降低计算频率)

if(global_tick % 50 == 0) { // 50*200us=10ms

for(int i=0; i<LED_NUM; i++) {

// 计算带延迟的本地时间

uint32_t local_time = global_tick - (i * PHASE_DELAY * 5);

float cycle_pos = (local_time % (BREATH_CYCLE * 5)) / (float)(BREATH_CYCLE * 5);

// 分三段计算RGB值

int segment = (int)(cycle_pos * 3);

float seg_pos = (cycle_pos * 3) - segment;

#if 1

switch(segment) {

case 0: // 红灯↑ 绿灯↓

pwm_vali0 = (int)(seg_pos * 100);

pwm_vali1 = 100 - (int)(seg_pos * 100);

pwm_vali2 = 0;

break;

case 1: // 蓝灯↑ 红灯↓

pwm_vali2 = (int)(seg_pos * 100);

pwm_vali0 = 100 - (int)(seg_pos * 100);

pwm_vali1 = 0;

break;

case 2: // 绿灯↑ 蓝灯↓

pwm_vali1 = (int)(seg_pos * 100);

pwm_vali2 = 100 - (int)(seg_pos * 100);

pwm_vali0 = 0;

break;

}

#else

float time = global_tick;//get_system_time(); // 获取时间

float h = fmod(time * 60, 360); // 色相每秒变化60°

float v = 1;//(sin(time * 2) + 1) * 0.5; // 亮度呼吸频率2Hz

uint8_t r, g, b;

//HSV2RGB(h, 1.0, v, &r, &g, &b); // 固定饱和度100%

//HSV2RGB(h, 1.0, v, &pwm_vali0, &pwm_vali1, &pwm_vali2);

switch(segment) {

case 0: HSV2RGB(h, 1.0, v, &pwm_vali0, &pwm_vali1, 0); break;

case 1: HSV2RGB(h, 1.0, v, &pwm_vali0, 0, &pwm_vali2); break;

case 2: HSV2RGB(h, 1.0, v, 0, &pwm_vali1, &pwm_vali2); break;

}

#endif

}

}

// 更新所有GPIO状态

for(int i=0; i<LED_NUM; i++) {

for(int j=0; j<3; j++) {

std_gpio_set_pin_mode(portij, pinij, GPIO_MODE_OUTPUT);

if(pwm_counter < pwm_valij) {

HAL_GPIO_WritePin(portij, pinij, GPIO_PIN_SET);

} else {

HAL_GPIO_WritePin(portij, pinij, GPIO_PIN_RESET);

}

}

}

// }

}

//// ========== 主函数 ==========

int main() {

HAL_Init();

GPIO_init_led();

TIM_Init(TIM3);

while(1) {

__WFI(); // 进入低功耗模式

}

}

相关推荐
Rocktech_ruixun2 小时前
机器人端侧大模型部署对主板有哪些要求?瑞迅主控板分级方案对比
人工智能·嵌入式硬件·机器人
Lzh编程小栈3 小时前
【嵌入式底层】SPI超透彻详解:通信原理、四线结构、四种模式、寄存器底层 + 面试全集
c语言·stm32·单片机·面试·职场和发展
Rocktech_ruixun3 小时前
机器人数据采集能力取决于什么?瑞迅科技RK3588/3576核心板方案深度解析
人工智能·嵌入式硬件·机器人
水果里面有苹果3 小时前
28-DRV8825PWPR步进电机驱动器
单片机
恒锐丰科技韩生3 小时前
率能 SS6625E|3.0~20V 单通道 H 桥直流电机驱动 SOP8 电子锁玩具机器人分享
嵌入式硬件·硬件工程
zlinear数据采集卡3 小时前
D223 ADC数据处理流水线:从原始采样值到工程单位的完整转换链
开发语言·arm开发·嵌入式硬件·fpga开发·开源·c#
Dr.kangder4 小时前
嵌入式面试总结(十八)——JTAG调试
嵌入式硬件·面试·职场和发展·架构·嵌入式
恒锐丰科技韩生5 小时前
率能 SS6226|2.4~7.2V 低压双通道双 H 桥电机驱动 SOP16 玩具小家电专用芯片
嵌入式硬件·硬件工程
Dr.kangder7 小时前
嵌入式面试总结(十九)——内存泄露
单片机·算法·面试·职场和发展·架构·硬件架构
萌新小白YXY9 小时前
SAE J1587/SAE J1708 协议笔记
笔记·单片机·嵌入式硬件