找回密码
 立即注册

QQ登录

只需一步,快速开始

打印 上一主题 下一主题
开启左侧

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;
}

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 顶 踩
回复

使用道具 举报

沙发
 楼主| VECENT_LIN 发表于 5 小时前 | 只看该作者
用GPIO驅動就沒問題。
回复 支持 反对

使用道具 举报

高级模式
B Color Image Link Quote Code Smilies |上传

本版积分规则

新唐MCU