feat: implement high-precision hardware SPI driver for FCOB-2.7 RGB LED with motor pin conflict resolution
This commit is contained in:
124
App/main.c
124
App/main.c
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user