#include "rgb.h" /* ====== SPI 寄存器定义 (如果 stc32g.h 没定义) ====== */ #ifndef P_SW1 sfr P_SW1 = 0xA2; sfr SPCTL = 0xCE; sfr SPSTAT = 0xCD; sfr SPDAT = 0xCF; #endif void SPI_Init(void) { P_SW1 = (P_SW1 & ~0x0C) | 0x04; // 映射 SPI 至第二组 (P2.2~P2.5) SPCTL = 0xD1; // SSIG=1, SPEN=1, MSTR=1, SPR0=1 (3.0 MHz) SPSTAT = 0xC0; // 清除标志 } void Encode_Byte(u8 val, u8 *out) { u32 spi_val = 0; u8 i; for (i = 0; i < 8; i++) { spi_val <<= 3; if (val & (0x80 >> i)) { spi_val |= 6; // 1码 -> 110 } else { spi_val |= 4; // 0码 -> 100 } } out[0] = (u8)(spi_val >> 16); out[1] = (u8)(spi_val >> 8); out[2] = (u8)spi_val; } void RGB_Send(u8 g1, u8 r1, u8 b1, u8 g2, u8 r2, u8 b2) { u8 idata spi_buf[18]; u8 i; // 转码 3-bit 编码 Encode_Byte(g1, &spi_buf[0]); Encode_Byte(r1, &spi_buf[3]); Encode_Byte(b1, &spi_buf[6]); Encode_Byte(g2, &spi_buf[9]); Encode_Byte(r2, &spi_buf[12]); Encode_Byte(b2, &spi_buf[15]); EA = 0; // 关中断 // 临时将 P2.5 (MOTOR) 配置为高阻输入以隔离时钟信号 P2M1 |= (1 << 5); P2M0 &= ~(1 << 5); SPI_Init(); // 启动 SPI for (i = 0; i < 18; i++) { SPDAT = spi_buf[i]; while (!(SPSTAT & 0x80)); // 等待发送完毕 SPSTAT = 0xC0; } SPCTL = 0; // 关闭 SPI // 配置 P2.3 (RGB_DIN) 为推挽输出并拉低 100us 做 Reset P2M1 &= ~(1 << 3); P2M0 |= (1 << 3); RGB_DIN = 0; for (i = 0; i < 200; i++) { _nop_(); _nop_(); _nop_(); } // 恢复 P2.5 (MOTOR) 为推挽输出以进行振动控制 P2M1 &= ~(1 << 5); P2M0 |= (1 << 5); MOTOR = 0; EA = 1; // 开中断 }