牛卧堂MCU技术交流
标题:
MS51FC0AE用SPI驅動WS2812的問題
[打印本页]
作者:
VECENT_LIN
时间:
4 小时前
标题:
MS51FC0AE用SPI驅動WS2812的問題
以下是用MS51FC0AE的SPI來驅動WS2812,不知道是哪里設置的問題,一直都不正常,請問哪位大神支支招,或者有現成的初始化程序嗎?謝謝!
// ================= 编码定义 =================
#define CODE_0 0xC0 // 1100 0000
#define CODE_1 0xFC // 1111 1100
// ================= 静态变量 =================
static unsigned char ws2812_grb_buf[LED_NUM * 3]; // GRB颜色缓存
static unsigned char ws2812_spi_buf[LED_NUM * 24]; // SPI编码缓存
/******************************************************************************
* 函数名: WS2812_Init
* 描述: WS2812 初始化
******************************************************************************/
void WS2812_Init(void)
{
// ---- 1. 配置 SPI 引脚(MS51FC0AE)----
// P0.0 = MOSI, 推挽输出
P0M1 &= ~0x01;
P0M2 |= 0x01;
// P1.7 = SCK, 推挽输出(不是 P1.0!)
P1M1 &= ~0x80;
P1M2 |= 0x80;
// P1.5 = SS, 推挽输出,拉高
P1M1 &= ~0x20;
P1M2 |= 0x20;
P15 = 1;
// 默认输出低电平
P00 = 0;
P17 = 0;
// ---- 2. 配置 SPI ----
SFRS = 0; // Page 0
SPCR = 0x00; // 先清零
SPCR |= 0x80; // SPEN = 1(SPI 使能)
SPCR |= 0x20; // MSTR = 1(主机模式)
// CPOL=0, CPHA=0(模式 0)
// LSBFE=0(MSB 优先)
// SSOE=0(禁止 SS 自动输出)
SPCR |= 0x02; // SPR = 10 -> /8 -> 24MHz/8 = 3MHz
SPSR = 0x00; // 清状态
}
/******************************************************************************
* 函数名: WS2812_Encode
* 描述: 将GRB数据编码为SPI数据
******************************************************************************/
static void WS2812_Encode(void)
{
unsigned int spi_idx = 0;
unsigned char i, j, mask;
unsigned char grb[3];
for (i = 0; i < LED_NUM; i++)
{
// GRB顺序: WS2812要求先G后R再B
grb[0] = ws2812_grb_buf[i * 3]; // G
grb[1] = ws2812_grb_buf[i * 3 + 1]; // R
grb[2] = ws2812_grb_buf[i * 3 + 2]; // B
// 编码每个字节 (高位先发)
for (j = 0; j < 3; j++)
{
for (mask = 0x80; mask > 0; mask >>= 1)
{
if (grb[j] & mask)
ws2812_spi_buf[spi_idx++] = CODE_1;
else
ws2812_spi_buf[spi_idx++] = CODE_0;
}
}
}
}
/******************************************************************************
* 函数名: SPI_WriteByte
* 描述: SPI发送单字节 (阻塞方式)
* 参数: dat - 要发送的数据
******************************************************************************/
static void SPI_WriteByte(unsigned char dat)
{
SPDR = dat; // 写入发送寄存器
while (!(SPSR & 0x80)); // 等待SPIF标志置位
SPSR |= 0x80; // 清除SPIF标志
}
/******************************************************************************
* 函数名: WS2812_Send
* 描述: 发送WS2812数据
* 注意: 发送时会关闭中断,保证时序准确
******************************************************************************/
void WS2812_Send(void)
{
unsigned int i;
// ---- 1. 编码数据 ----
WS2812_Encode();
// ---- 2. 关中断 ----
EA = 0;
// ---- 3. 发送RESET信号 (低电平 > 50us) ----
P00 = 0;
for (i = 0; i < 200; i++); // 约60us (24MHz)
// ---- 4. 发送SPI数据 ----
for (i = 0; i < (LED_NUM * 24); i++)
{
SPI_WriteByte(ws2812_spi_buf[i]);
}
// ---- 5. 拉低MOSI ----
P00 = 0;
// ---- 6. 开中断 ----
EA = 1;
}
作者:
VECENT_LIN
时间:
4 小时前
用GPIO驅動就沒問題。
欢迎光临 牛卧堂MCU技术交流 (https://nuvoton-mcu.com/)
Powered by Discuz! X3.2