feat: implement high-precision hardware SPI driver for FCOB-2.7 RGB LED with motor pin conflict resolution

This commit is contained in:
2026-07-08 09:27:17 +08:00
parent f1777e0459
commit 680d8ea06f
4 changed files with 106 additions and 141 deletions

View File

@@ -87,6 +87,7 @@ char *code menu_items[5] = {
};
// 本地函数前置声明
void Delay10us(void);
void GPIO_Init(void);
void Timer1_Init(void);
u16 GetTimer0_Safe(void);
@@ -127,100 +128,67 @@ void UI_ShowSosPage(void);
* WS2812B 幻彩 LED 单线驱动函数 (24MHz 1T 模式下精准时序控制)
* ========================================================================= */
const u16 code SPI_LUT[16] = {
0x924, 0x926, 0x934, 0x936, 0x9A4, 0x9A6, 0x9B4, 0x9B6,
0xD24, 0xD26, 0xD34, 0xD36, 0xDA4, 0xDA6, 0xDB4, 0xDB6
};
void WS2812_EncodeByte(u8 v, u8 *buf)
{
u16 p1 = SPI_LUT[v >> 4];
u16 p2 = SPI_LUT[v & 0x0F];
buf[0] = p1 >> 4;
buf[1] = ((p1 & 0x0F) << 4) | (p2 >> 8);
buf[2] = p2;
}
void WS2812_Write24Bit(u8 g, u8 r, u8 b)
{
u8 i;
u8 xdata buf[9];
u8 m1_save, m0_save;
WS2812_EncodeByte(g, &buf[0]);
WS2812_EncodeByte(r, &buf[3]);
WS2812_EncodeByte(b, &buf[6]);
// 关全局中断,防止被其它高优先中断截断导致时序错乱
EA = 0;
// 绿光通道 (Green)
for (i = 0; i < 8; i++)
{
if (g & 0x80)
{
// 发送 "1" 码:高电平维持 ~0.8us,低电平维持 ~0.4us
WS2812_DI = 1;
_nop_(); _nop_(); _nop_(); _nop_(); _nop_();
_nop_(); _nop_(); _nop_(); _nop_(); _nop_();
_nop_(); _nop_(); _nop_(); _nop_(); _nop_();
WS2812_DI = 0;
_nop_();
}
else
{
// 发送 "0" 码:高电平维持 ~0.35us,低电平维持 ~0.9us
WS2812_DI = 1;
_nop_(); _nop_(); _nop_(); _nop_();
WS2812_DI = 0;
_nop_(); _nop_(); _nop_(); _nop_(); _nop_();
_nop_(); _nop_(); _nop_(); _nop_(); _nop_();
_nop_(); _nop_(); _nop_();
}
g <<= 1;
}
m1_save = P2M1 & (1 << 5);
m0_save = P2M0 & (1 << 5);
// 红光通道 (Red)
for (i = 0; i < 8; i++)
{
if (r & 0x80)
{
WS2812_DI = 1;
_nop_(); _nop_(); _nop_(); _nop_(); _nop_();
_nop_(); _nop_(); _nop_(); _nop_(); _nop_();
_nop_(); _nop_(); _nop_(); _nop_(); _nop_();
WS2812_DI = 0;
_nop_();
}
else
{
WS2812_DI = 1;
_nop_(); _nop_(); _nop_(); _nop_();
WS2812_DI = 0;
_nop_(); _nop_(); _nop_(); _nop_(); _nop_();
_nop_(); _nop_(); _nop_(); _nop_(); _nop_();
_nop_(); _nop_(); _nop_();
}
r <<= 1;
}
P2M1 |= (1 << 5);
P2M0 &= ~(1 << 5);
// 蓝光通道 (Blue)
for (i = 0; i < 8; i++)
{
if (b & 0x80)
{
WS2812_DI = 1;
_nop_(); _nop_(); _nop_(); _nop_(); _nop_();
_nop_(); _nop_(); _nop_(); _nop_(); _nop_();
_nop_(); _nop_(); _nop_(); _nop_(); _nop_();
WS2812_DI = 0;
_nop_();
}
else
{
WS2812_DI = 1;
_nop_(); _nop_(); _nop_(); _nop_();
WS2812_DI = 0;
_nop_(); _nop_(); _nop_(); _nop_(); _nop_();
_nop_(); _nop_(); _nop_(); _nop_(); _nop_();
_nop_(); _nop_(); _nop_();
}
b <<= 1;
}
SPCTL = 0xD1; // Enable SPI at SYSCLK/8 (3.0 MHz)
SPSTAT = 0xC0; SPDAT = buf[0]; while (!(SPSTAT & 0x80));
SPSTAT = 0xC0; SPDAT = buf[1]; while (!(SPSTAT & 0x80));
SPSTAT = 0xC0; SPDAT = buf[2]; while (!(SPSTAT & 0x80));
SPSTAT = 0xC0; SPDAT = buf[3]; while (!(SPSTAT & 0x80));
SPSTAT = 0xC0; SPDAT = buf[4]; while (!(SPSTAT & 0x80));
SPSTAT = 0xC0; SPDAT = buf[5]; while (!(SPSTAT & 0x80));
SPSTAT = 0xC0; SPDAT = buf[6]; while (!(SPSTAT & 0x80));
SPSTAT = 0xC0; SPDAT = buf[7]; while (!(SPSTAT & 0x80));
SPSTAT = 0xC0; SPDAT = buf[8]; while (!(SPSTAT & 0x80));
SPCTL = 0x90; // Disable SPI
WS2812_DI = 0;
P2M1 = (P2M1 & ~(1 << 5)) | m1_save;
P2M0 = (P2M0 & ~(1 << 5)) | m0_save;
// 开全局中断
EA = 1;
}
void WS2812_Reset(void)
{
SPCTL = 0x90;
WS2812_DI = 0;
// 维持低电平 100us 以上以完成数据锁存 (24MHz 计数约2400)
{
u16 cnt;
for (cnt = 0; cnt < 250; cnt++)
u8 i;
for (i = 0; i < 10; i++)
{
_nop_();
Delay10us();
}
}
}