当前位置: 首页 > news >正文

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_tab[130]  = { //正弦呼吸表
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* port[LED_NUM][3] = { // ... 填充所有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 pin[LED_NUM][3] = {     // ... 填充所有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_val[LED_NUM][3] = {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(port[i][j], pin[i][j], 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   = pin[i][j];//gpio.Pin = pin[i][j];
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(port[i][j], &gpio);
HAL_GPIO_WritePin(port[i][j], pin[i][j], 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_val[i][0] = (int)(seg_pos * 100);
pwm_val[i][1] = 100 - (int)(seg_pos * 100);
pwm_val[i][2] = 0;
break;
case 1: // 蓝灯↑ 红灯↓
pwm_val[i][2] = (int)(seg_pos * 100);
pwm_val[i][0] = 100 - (int)(seg_pos * 100);
pwm_val[i][1] = 0;
break;
case 2: // 绿灯↑ 蓝灯↓
pwm_val[i][1] = (int)(seg_pos * 100);
pwm_val[i][2] = 100 - (int)(seg_pos * 100);
pwm_val[i][0] = 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_val[i][0], &pwm_val[i][1], &pwm_val[i][2]);
switch(segment) {
case 0:   HSV2RGB(h, 1.0, v, &pwm_val[i][0], &pwm_val[i][1], 0);   break;
case 1:   HSV2RGB(h, 1.0, v, &pwm_val[i][0], 0, &pwm_val[i][2]);   break;
case 2:   HSV2RGB(h, 1.0, v, 0, &pwm_val[i][1], &pwm_val[i][2]);   break;
}
#endif
}
}

// 更新所有GPIO状态 
for(int i=0; i<LED_NUM; i++) {
for(int j=0; j<3; j++) {
std_gpio_set_pin_mode(port[i][j], pin[i][j], GPIO_MODE_OUTPUT);
if(pwm_counter < pwm_val[i][j]) {
HAL_GPIO_WritePin(port[i][j], pin[i][j], GPIO_PIN_SET);
} else {
HAL_GPIO_WritePin(port[i][j], pin[i][j], GPIO_PIN_RESET);
}
}
}
// }
}

//// ========== 主函数 ==========
int main() {
HAL_Init();
GPIO_init_led();
TIM_Init(TIM3);

while(1) {
__WFI(); // 进入低功耗模式 
}
}

http://www.dtcms.com/a/420288.html

相关文章:

  • 流处理和批处理
  • 企业网站 合同网站服务器哪个好
  • 理论网站建设实施方案网站百度云
  • java gui
  • 网站建设及安全规范无本钱一天挣1000
  • 平湖新埭哪里有做网站的免费广告设计app
  • 网站后台维护教程网站建设文本
  • 网站后台管理模板下载优秀网站建设模板
  • 双主业集团数据治理架构实战:从ERP核心到大数据平台的演进路径
  • Java JDBC将图片以二进制形式保存到MySQL数据库并从MySQL数据库中读取图片到本地
  • 宝丰网站制作公司静安区网站建设
  • 做透水砖的网站房屋中介做网站的
  • 移动端网站开发框架wordpress 禁用标
  • 做视频网站要多大的带宽有哪些网站可以做全景效果图
  • 华夏望子成龙网站开发背景深圳广胜达建设公司
  • QT问题和解决方案:Unable to locate ICU library icuin58.dll
  • 部署sapui5应用到linux
  • dumpsys media.camera 简介
  • 湛江建站程序厂房装修东莞网站建设
  • hslenc.c 代码提纲挈领分析
  • 怎么搭建mysql数据库网站广州注册公司需要什么资料
  • 优惠劵精选网站怎么做网站建设丩金手指排名壹陆
  • 旅游小镇网站建设方案网站建设需要材料
  • 鸿蒙Next NFC标签读写开发指南:从基础到实战
  • 微网站制作工具有哪些西安做网站公司报价
  • 淄博网站建设给力臻动传媒城市建设理论研究收录网站
  • wordpress去除标志站长查询seo是什么意思
  • 鸿蒙(HarmonyOS)应用开发技能栈
  • 网站的功能性合作网站制作
  • Node.js面试题及详细答案120题(69-80) -- 数据库操作篇