找回密码
 立即注册

QQ登录

只需一步,快速开始

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

MS51FC0AE用SPI驅動WS2812的問題

[复制链接]
跳转到指定楼层
楼主
VECENT_LIN 发表于 昨天 13:33 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
以下是用MS51FC0AE的SPI來驅動WS2812,不知道是哪里設置的問題,一直都不正常,請問哪位大神支支招,或者有現成的初始化程序嗎?謝謝!
  1. // ================= 编码定义 =================
  2. #define CODE_0      0xC0    // 1100 0000
  3. #define CODE_1      0xFC    // 1111 1100

  4. // ================= 静态变量 =================
  5. static unsigned char ws2812_grb_buf[LED_NUM * 3];     // GRB颜色缓存
  6. static unsigned char ws2812_spi_buf[LED_NUM * 24];    // SPI编码缓存

  7. /******************************************************************************
  8. * 函数名: WS2812_Init
  9. * 描述: WS2812 初始化
  10. ******************************************************************************/
  11. void WS2812_Init(void)
  12. {
  13.     // ---- 1. 配置 SPI 引脚(MS51FC0AE)----
  14.     // P0.0 = MOSI, 推挽输出
  15.     P0M1 &= ~0x01;
  16.     P0M2 |=  0x01;

  17.     // P1.7 = SCK, 推挽输出(不是 P1.0!)
  18.     P1M1 &= ~0x80;
  19.     P1M2 |=  0x80;

  20.     // P1.5 = SS, 推挽输出,拉高
  21.     P1M1 &= ~0x20;
  22.     P1M2 |=  0x20;
  23.     P15 = 1;

  24.     // 默认输出低电平
  25.     P00 = 0;
  26.     P17 = 0;

  27.     // ---- 2. 配置 SPI ----
  28.     SFRS = 0;           // Page 0

  29.     SPCR = 0x00;        // 先清零
  30.     SPCR |= 0x80;       // SPEN = 1(SPI 使能)
  31.     SPCR |= 0x20;       // MSTR = 1(主机模式)
  32.     // CPOL=0, CPHA=0(模式 0)
  33.     // LSBFE=0(MSB 优先)
  34.     // SSOE=0(禁止 SS 自动输出)
  35.     SPCR |= 0x02;       // SPR = 10 -> /8 -> 24MHz/8 = 3MHz

  36.     SPSR = 0x00;        // 清状态
  37. }
  38. /******************************************************************************
  39. * 函数名: WS2812_Encode
  40. * 描述: 将GRB数据编码为SPI数据
  41. ******************************************************************************/
  42. static void WS2812_Encode(void)
  43. {
  44.     unsigned int spi_idx = 0;
  45.     unsigned char i, j, mask;
  46.     unsigned char grb[3];

  47.     for (i = 0; i < LED_NUM; i++)
  48.     {
  49.         // GRB顺序: WS2812要求先G后R再B
  50.         grb[0] = ws2812_grb_buf[i * 3];         // G
  51.         grb[1] = ws2812_grb_buf[i * 3 + 1];     // R
  52.         grb[2] = ws2812_grb_buf[i * 3 + 2];     // B

  53.         // 编码每个字节 (高位先发)
  54.         for (j = 0; j < 3; j++)
  55.         {
  56.             for (mask = 0x80; mask > 0; mask >>= 1)
  57.             {
  58.                 if (grb[j] & mask)
  59.                     ws2812_spi_buf[spi_idx++] = CODE_1;
  60.                 else
  61.                     ws2812_spi_buf[spi_idx++] = CODE_0;
  62.             }
  63.         }
  64.     }
  65. }

  66. /******************************************************************************
  67. * 函数名: SPI_WriteByte
  68. * 描述: SPI发送单字节 (阻塞方式)
  69. * 参数: dat - 要发送的数据
  70. ******************************************************************************/
  71. static void SPI_WriteByte(unsigned char dat)
  72. {
  73.     SPDR = dat;                     // 写入发送寄存器
  74.     while (!(SPSR & 0x80));         // 等待SPIF标志置位
  75.     SPSR |= 0x80;                   // 清除SPIF标志
  76. }

  77. /******************************************************************************
  78. * 函数名: WS2812_Send
  79. * 描述: 发送WS2812数据
  80. * 注意: 发送时会关闭中断,保证时序准确
  81. ******************************************************************************/
  82. void WS2812_Send(void)
  83. {
  84.     unsigned int i;

  85.     // ---- 1. 编码数据 ----
  86.     WS2812_Encode();

  87.     // ---- 2. 关中断 ----
  88.     EA = 0;

  89.     // ---- 3. 发送RESET信号 (低电平 > 50us) ----
  90.     P00 = 0;
  91.     for (i = 0; i < 200; i++);      // 约60us (24MHz)

  92.     // ---- 4. 发送SPI数据 ----
  93.     for (i = 0; i < (LED_NUM * 24); i++)
  94.     {
  95.         SPI_WriteByte(ws2812_spi_buf);
  96.     }

  97.     // ---- 5. 拉低MOSI ----
  98.     P00 = 0;

  99.     // ---- 6. 开中断 ----
  100.     EA = 1;
  101. }
复制代码

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

使用道具 举报

沙发
 楼主| VECENT_LIN 发表于 昨天 13:34 | 只看该作者
用GPIO驅動就沒問題。
回复 支持 反对

使用道具 举报

板凳
admin 发表于 7 小时前 | 只看该作者
WS2812 本身是单线归零码(NRZ)协议,不是 SPI 设备。所谓“SPI 驱动 WS2812”,其实是用 SPI 的 MOSI 引脚当“高速方波发生器”,把 WS2812 的 0/1 码编码成 SPI 字节。你可以发邮件联系我们。yhu@nuvoton.com
牛卧堂
回复 支持 反对

使用道具 举报

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

本版积分规则

新唐MCU