有没有大佬帮看看代码
- #define MAIN_Fosc 40000000UL // 明确40MHz系统时钟(与硬件一致)
- #include "rgb.h"
-
- // 颜色定义(保持原逻辑,确保GRB顺序匹配WS2812)
- uint8 xdata rgb_red[3] = {0xff,0x00,0x00}; // 红色(RGB)→ GRB后为0x00,0xff,0x00
- uint8 xdata rgb_green[3] = {0x00,0xff,0x00}; // 绿色 → GRB后为0xff,0x00,0x00
- uint8 xdata rgb_blue[3] = {0x00,0x00,0xff}; // 蓝色 → GRB后为0x00,0x00,0xff
- uint8 xdata rgb_off[3] = {0x00,0x00,0x00}; // 熄灭
- uint8 xdata rgb_yellow[3] = {0xff,0xff,0x00}; // 黄色
- uint8 xdata rgb_purple[3] = {0xff,0x00,0xff}; // 紫色
- uint8 xdata rgb_cyan[3] = {0x00,0xff,0xff}; // 青色
- uint8 xdata rgb_white[3] = {0xff,0xff,0xff}; // 白色
- uint8 xdata rgb_black[3] = {0x00,0x00,0x00}; // 黑色
-
- // 呼吸灯颜色变量
- uint8 xdata breath_rgb_color[3];
-
- // WS2812编码缓冲区(3色×4SPI字节=12字节,单个灯,文档推荐缓冲区大小)
- uint8 xdata ws2812_buffer[12];
- bit B_SPI_DMA_busy = 0; // SPI-DMA忙标志(文档DMA状态管理规范)
-
- // 状态变量(保持原定义)
- static uint8 xdata current_rgb_color[3];
- static RGB_STATE_enum current_state = RGB_STATE_OFF;
- static RGB_COLOR_enum current_color = RGB_COLOR_BLACK;
- static RGB_STATE_enum target_state = RGB_STATE_OFF;
- static RGB_COLOR_enum target_color = RGB_COLOR_BLACK;
- static uint32 last_toggle_time = 0;
- static uint8 blink_state = 0;
- static uint32 last_breath_time = 0;
- static uint8 breath_direction = 1;
- static uint8 breath_brightness = 10;
-
- // 引脚定义(USART1 SPI通道3:P4.0-SS, P4.1-MOSI, P4.2-MISO, P4.3-SCK,文档2.1.3节管脚图)
- #define SPI_MOSI_PIN 0x02 // P4.1 (bit1)
- #define SPI_SCK_PIN 0x08 // P4.3 (bit3)
- #define SPI_MISO_PIN 0x04 // P4.2 (bit2)
- #define Pin2 0x04 // P4.2 (bit2)
-
- /**
- * @brief RGB模块初始化(适配40MHz时钟,遵循文档SPI/DMA配置规范)
- * @note 参考文档:第24章SPI()、第25章HSSPI()、第34章DMA()
- */
- void rgb_init(void)
- {
- // 1. SPI引脚配置(文档13章I/O口配置)
- // MOSI(P4.1)、SCK(P4.3):推挽输出+高速模式(40MHz下需高速驱动)
- P4M0 |= (SPI_MOSI_PIN | SPI_SCK_PIN);
- P4M1 &= ~(SPI_MOSI_PIN | SPI_SCK_PIN);
- // 使用标准寄存器操作替代SlewRateHigh函数
- P4SR &= ~(SPI_MOSI_PIN | SPI_SCK_PIN); // 高速输出,确保TH/TL时序
-
- // MISO(P4.2):高阻输入+下拉(文档24.4节SPI从机配置)
- // 使用标准寄存器操作替代函数调用
- P4M1 |= SPI_MISO_PIN; // 高阻输入模式
- P4M0 &= ~SPI_MISO_PIN; // 输入模式
- P4PU &= ~SPI_MISO_PIN; // 禁止上拉
- P4PD |= SPI_MISO_PIN; // 允许下拉,确保空闲低电平
-
- // 2. USART1-SPI模式配置(文档18章同步串口)
- USARTCR1 = 0x00; // 复位USART1
- USARTCR1 |= 0x08; // 使能SPI功能(bit3=1)
- USARTCR1 &= ~0x10; // 0=SPI模式(bit4=0)
- USARTCR1 |= 0x40; // 主机模式(bit6=1)
- USARTCR1 |= 0x80; // 使能USART1(bit7=1)
- USARTCR2 = 0x00; // CPOL=0, CPHA=0(WS2812要求)
- USARTCR3 = 0x00; // 8位数据长度(bit0-1=00)
-
- // 3. SPI波特率计算(40MHz→3.2MHz:Fosc/(2*(USARTBR+1))=3.2MHz → USARTBR=5,文档18.3.5节公式)
- USARTBRH = 0x00;
- USARTBRL = 0x05;
-
- // 4. 高速SPI配置(40MHz下时序补偿,文档25.1节)
- HSCLKDIV = 1; // 主时钟分频(高频稳定)
- SPI_CLKDIV = 1; // SPI时钟分频
- HSSPI_CFG = (2 << 4) | 3; // SS_HOLD=2, SS_SETUP=3(40MHz下补偿传输延迟)
- HSSPI_CFG2 = (1<<5) | (1<<4) | 3;// HSSPIEN=1(使能高速), FIFOEN=1(减少13个时钟延迟), SS_DACT=3
-
- // 5. DMA配置(USART1发送DMA,文档34.7节)
- DMA_UR1T_CR = 0x00; // 停止当前DMA
- DMA_UR1T_STA = 0x00; // 清除状态标志
- // DMA配置:中断使能+发送使能+优先级1+普通优先级
- DMA_UR1T_CFG = (1<<7) | (1<<6) | (1<<2) | 0;
- interrupt_set_priority(DMA_UR1T_VECTOR, 1); // 中断优先级1(文档14章中断)
-
- // 6. 初始化熄灭灯(确保初始状态可控)
- while(B_SPI_DMA_busy);
- send_color_data(rgb_off);
- }
-
- // 根据颜色枚举获取指针(保持原实现)
- uint8* get_color_ptr(RGB_COLOR_enum color)
- {
- switch(color)
- {
- case RGB_COLOR_RED: return rgb_red;
- case RGB_COLOR_GREEN: return rgb_green;
- case RGB_COLOR_BLUE: return rgb_blue;
- case RGB_COLOR_YELLOW: return rgb_yellow;
- case RGB_COLOR_PURPLE: return rgb_purple;
- case RGB_COLOR_CYAN: return rgb_cyan;
- case RGB_COLOR_WHITE: return rgb_white;
- case RGB_COLOR_BLACK: return rgb_black;
- default: return rgb_black;
- }
- }
-
- // 前向声明(保持原定义)
- void RGB_SPI_DMA_TxTRIG(uint8 xdata *TxBuf, uint16 num);
-
- // 发送颜色数据(保持原逻辑,增加SPI空闲检查)
- void send_color_data(uint8 *color)
- {
- while(B_SPI_DMA_busy); // 等待DMA空闲
- while(USARTCR1 & 0x20); // 等待SPI总线空闲(避免冲突)
-
- // 更新当前颜色
- current_rgb_color[0] = color[0];
- current_rgb_color[1] = color[1];
- current_rgb_color[2] = color[2];
-
- encode_ws2812_data(current_rgb_color); // 编码
- RGB_SPI_DMA_TxTRIG(ws2812_buffer, 12); // DMA发送
- while(B_SPI_DMA_busy); // 等待发送完成
-
- system_delay_us(50); // WS2812复位时间(≥50us)
- }
-
- /**
- * @brief 启动SPI DMA传输(遵循文档34.4.4节配置)
- * @param TxBuf:发送缓冲区地址
- * @param num:传输字节数(实际长度,内部转换为num-1)
- */
- void RGB_SPI_DMA_TxTRIG(uint8 xdata *TxBuf, uint16 num)
- {
- uint16 j = (uint16)TxBuf;
- // 扩展寄存器已在主函数使能,无需重复调用EAXSFR
-
- // 停止当前DMA并等待SPI空闲(文档34.4.4节)
- DMA_UR1T_CR = 0x00;
- while(USARTCR1 & 0x20); // 等待SPI_BUSY标志清除(bit5=0)
-
- // 配置DMA地址和长度(文档34.7.2节)
- DMA_UR1T_TXAH = (uint8)(j >> 8); // 发送地址高字节
- DMA_UR1T_TXAL = (uint8)j; // 发送地址低字节
- DMA_UR1T_AMTH = (uint8)((num-1)/256); // 总字节数=num-1(文档要求)
- DMA_UR1T_AMT = (uint8)((num-1)%256);
- // 移除不存在的寄存器
- // DMA_UR1T_ITVH = 0; // 无间隔时间
- // DMA_UR1T_ITVL = 0;
- DMA_UR1T_STA = 0x00; // 清除状态
-
- // 启动DMA传输(文档34.7.2节)
- DMA_UR1T_CR = (1<<7) | (1<<6) | 1; // DMA_EN=1, TRIG_M=1, CLRFIFO=1
- B_SPI_DMA_busy = 1;
- }
-
- // SPI DMA中断服务函数(保持原逻辑)
- void SPI_DMA_ISR (void) interrupt DMA_UR1T_VECTOR
- {
- EAXSFR(); // 使用宏替代直接寄存器访问
- DMA_UR1T_STA = 0; // 清除中断标志
- DMA_UR1T_CR = 0x00; // 停止DMA
- B_SPI_DMA_busy = 0; // 释放忙标志
- }
-
- // WS2812编码(保持原逻辑,确认GRB顺序)
- void encode_ws2812_data(uint8 *rgb_color)
- {
- static const uint8 code_table[4] = {0x88, 0x8E, 0xE8, 0xEE}; // 00=0x88, 01=0x8E, 10=0xE8, 11=0xEE
- uint8 dat;
- uint8 color_order[3];
-
- // 清空缓冲区(32位操作优化)
- *((uint32*)&ws2812_buffer[0]) = 0;
- *((uint32*)&ws2812_buffer[4]) = 0;
- *((uint32*)&ws2812_buffer[8]) = 0;
-
- // WS2812要求GRB顺序(原代码正确)
- color_order[0] = rgb_color[1]; // Green
- color_order[1] = rgb_color[0]; // Red
- color_order[2] = rgb_color[2]; // Blue
-
- // 编码Green通道
- dat = color_order[0];
- ws2812_buffer[0] = code_table[(dat >> 6) & 0x03];
- ws2812_buffer[1] = code_table[(dat >> 4) & 0x03];
- ws2812_buffer[2] = code_table[(dat >> 2) & 0x03];
- ws2812_buffer[3] = code_table[dat & 0x03];
-
- // 编码Red通道
- dat = color_order[1];
- ws2812_buffer[4] = code_table[(dat >> 6) & 0x03];
- ws2812_buffer[5] = code_table[(dat >> 4) & 0x03];
- ws2812_buffer[6] = code_table[(dat >> 2) & 0x03];
- ws2812_buffer[7] = code_table[dat & 0x03];
-
- // 编码Blue通道
- dat = color_order[2];
- ws2812_buffer[8] = code_table[(dat >> 6) & 0x03];
- ws2812_buffer[9] = code_table[(dat >> 4) & 0x03];
- ws2812_buffer[10] = code_table[(dat >> 2) & 0x03];
- ws2812_buffer[11] = code_table[dat & 0x03];
- }
-
- // RGB任务处理(保持原逻辑)
- void rgb_task(void)
- {
- uint8 *color_ptr;
- uint32 current_time = sys_tick_get();
-
- if (target_state != current_state || target_color != current_color) {
- current_state = target_state;
- current_color = target_color;
- color_ptr = get_color_ptr(current_color);
- blink_state = 0;
- breath_brightness = 10;
- breath_direction = 1;
- last_toggle_time = current_time;
- last_breath_time = current_time;
- }
-
- switch(current_state)
- {
- case RGB_STATE_OFF:
- send_color_data(rgb_off);
- break;
- case RGB_STATE_ON:
- color_ptr = get_color_ptr(current_color);
- send_color_data(color_ptr);
- break;
- case RGB_STATE_BLINK:
- if(current_time - last_toggle_time >= 500)
- {
- last_toggle_time = current_time;
- blink_state = !blink_state;
- send_color_data(blink_state ? get_color_ptr(current_color) : rgb_off);
- }
- break;
- case RGB_STATE_FAST_BLINK:
- if(current_time - last_toggle_time >= 200)
- {
- last_toggle_time = current_time;
- blink_state = !blink_state;
- send_color_data(blink_state ? get_color_ptr(current_color) : rgb_off);
- }
- break;
- case RGB_STATE_BREATH:
- if(current_time - last_breath_time >= 30)
- {
- last_breath_time = current_time;
- // 更新亮度
- if(breath_direction)
- breath_brightness = (breath_brightness >= 245) ? 255 : (breath_brightness + 10);
- else
- breath_brightness = (breath_brightness <= 10) ? 10 : (breath_brightness - 10);
- if(breath_brightness >= 255 || breath_brightness <= 10)
- breath_direction = !breath_direction;
-
- // 计算呼吸颜色
- color_ptr = get_color_ptr(current_color);
- breath_rgb_color[0] = (uint16)color_ptr[0] * breath_brightness / 255;
- breath_rgb_color[1] = (uint16)color_ptr[1] * breath_brightness / 255;
- breath_rgb_color[2] = (uint16)color_ptr[2] * breath_brightness / 255;
-
- // 避免完全熄灭
- if(breath_rgb_color[0] == 0 && breath_rgb_color[1] == 0 && breath_rgb_color[2] == 0)
- {
- if(color_ptr[0] > 0) breath_rgb_color[0] = 1;
- else if(color_ptr[1] > 0) breath_rgb_color[1] = 1;
- else if(color_ptr[2] > 0) breath_rgb_color[2] = 1;
- }
- send_color_data(breath_rgb_color);
- }
- break;
- default:
- send_color_data(rgb_off);
- break;
- }
- }
-
- // 设置RGB颜色和状态(保持原逻辑)
- void rgb_set_color_state(RGB_COLOR_enum color, RGB_STATE_enum state)
- {
- target_color = color;
- target_state = state;
- }
复制代码
|