找回密码
 立即注册
查看: 3472|回复: 72

SPI DMA 输出控制WS2812三基色彩灯程序,不加反相器,STC8/STC32

[复制链接]

该用户从未签到

45

主题

2912

回帖

6546

积分

超级版主

积分
6546
发表于 2024-1-5 23:59:33 | 显示全部楼层 |阅读模式
使用 SPI-MOSI 输出直接驱动 WS2812 三基色彩灯, DMA传输STC8/STC32
SPI方案, 不加外部反相器:
只用到MOSI驱动WS2812,但由于SPI的3个信号是捆绑在一起的

===MISO、SCLK不能做它用。
本例使用P1.3-MOSI输出驱动信号,用户可以切换到别的脚。
===将 MISO 不做其他用途;
===将 MISO管脚 先设置为对外输出0;
===MOSI 发送完成后,对外停止时输出的是 MISO 读到的状态, 0 !

        这 STC-R&D 10年前 SPI 留了这么个绝活 支持 WS2812B !!!
本例驱动60个灯,接成环状。SPI发送720字节,DMA分3块发送,一块240字节,
SPI-DMA自动传送不占CPU时间,SPI-DMA 总耗时2.08mS
===但由于使用DMA中断处理,所以发送占CPU时间只有几uS
===实际几乎 不占 CPU 时间


每个灯3个字节,分别对应绿、红、蓝色,MSB先发.
800KHz码率, 数据0(1/4占空比): H=0.3125us  L=0.9375us, 数据1(3/4占空比): H=0.9375us  L=0.3125us, RESET>=50us.
高电平时间要精确控制在要求的范围内, 低电平时间不需要精确控制, 大于要求的最小值并小于RES的50us即可.

WS2812S的标准时序如下:
TH+TL = 1.25us±150ns, RES>50us
T0H = 0.25us±150ns = 0.10us - 0.40us
T0L = 1.00us±150ns = 0.85us - 1.15us
T1H = 1.00us±150ns = 0.85us - 1.15us
T1L = 0.25us±150ns = 0.10us - 0.40us
两个位数据之间的间隔要小于RES的50us.

SPI方案:
只用到MOSI驱动WS2812,但由于SPI的3个信号是捆绑在一起的,MISO、SCLK不能做它用。本例使用P1.3-MOSI输出驱动信号,用户可以切换到别的脚。
===将 MISO 不做其他用途;
===将 MISO管脚 先设置为对外输出0;
===MOSI 发送完成后,对外停止时输出的是 MISO 读到的状态, 0 ,这 STC-R&D 留了这么个绝活支持 WS2812B !!!

用SPI传输, 速度3.0~3.5MHz,以3.2MHz为最佳, MSB先发, 每个字节高4位和低4位分别对应一个WS2812位数据, 1000为数据0, 1110为数据1, 有DMA就使用DMA传输, 没有DMA就直接SPI发送.
MOSI数据位       D7 D6 D5 D4    D3 D2 D1 D0
MOSI数据          1    0   0   0      1   1   1   0
                     WS2812数据0    WS2812数据1
SPI数据高半字节对应的WS2812数据0-->0x80, 数据1-->0xE0,
SPI数据低半字节对应的WS2812数据0-->0x08, 数据1-->0x0E,
主频25.6MHz, SPI分频8 = 3.2MHz。最佳。本例使用。
主频24.0MHz, SPI分频8 = 3.0MHz。本例可用。
主频12.8MHz, SPI分频4 = 3.2MHz。最佳。用户要改下主频定义和SPI为4分频。
主频12.0MHz, SPI分频4 = 3.0MHz。用户要改下主频定义,SPI为4分频。

下面为跑马灯效果视频:


电路预览,文件包中有PDF:
截图202401052357299288.jpg
使用 SPI-MOSI 输出直接驱动 WS2812 三基色彩灯, DMA传输STC8/STC32
SPI方案, 不加外部反相器:
只用到MOSI驱动WS2812,但由于SPI的3个信号是捆绑在一起的

===MISO、SCLK不能做它用。
本例使用P1.3-MOSI输出驱动信号,用户可以切换到别的脚。
===将 MISO 不做其他用途;
===将 MISO管脚 先设置为对外输出0;
===MOSI 发送完成后,对外停止时输出的是 MISO 读到的状态, 0 !

        这 STC-R&D 10年前 SPI 留了这么个绝活 支持 WS2812B !!!
本例驱动60个灯,接成环状。SPI发送720字节,DMA 分 3块发送,一块240字节
SPI-DMA自动传送, 直接驱动 WS2812 不占CPU时间
===SPI-DMA 的SPI 总耗时2.08mS不加外部反相器
===但由于使用DMA中断处理,所以发送占CPU时间只有几uS
===实际几乎 不占 CPU 时间

2024/1/10开源演示程序文件, SPI-DMA直驱WS2812不加外部反相器
梁工:SPI驱动WS2812彩灯程序已完善更新 !
STC8H有4个程序:   SPI查询发送; SPI中断发送; SPI-DMA中断发送; DMA中断+比较器反相
STC32G的3个程序: SPI查询发送; SPI中断发送; SPI-DMA发送(不用中断,一次DMA发完720字节)
STC8H-SPI驱动WS2812彩灯程序.rar (1.01 MB, 下载次数: 181)
STC32G-SPI驱动WS2812彩灯程序.rar (817.69 KB, 下载次数: 93)
截图202401101426159848.jpg












回复 送花

使用道具 举报

  • TA的每日心情
    开心
    9 小时前
  • 签到天数: 131 天

    [LV.7]常住居民III

    37

    主题

    867

    回帖

    3934

    积分

    荣誉版主

    积分
    3934
    发表于 2024-1-6 07:17:52 | 显示全部楼层
    沙发!!!

    直接传输(非反相), 有两个问题,

    1. 第一次 DMA-SPI传输完成, 第二次 DMA-SPI传输开始的第一字节第一位, 假如 是 0 的话(加上停顿间隔高电平), 极易 变成 1, ( 当然, 你的例子, 特例, 第一字节第一位 是 1, 变不了).

    2. DMA-SPI传输, 中断必须最高级(一般显示刷新置最低级). 否则, 两次DMA-SPI传输 中间的 停顿间隔高电平, 必将 下一次 DMA-SPI传输开始的第一字节第一位, 从 0 变成 1 . 出现 错误 !!!

    点评

    1、我的程序,一个字节传输完成后,或SPI DMA传输完成后,MOSI都是低电平。 2、我的例子没有别的任务,所以SPI DMA中断优先级为最低,用户根据实际情况增加优先级(最下限两个宏): //DMA_SPI_CFG SPI_DMA配置寄存  详情 回复 发表于 2024-1-6 09:35
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    9 小时前
  • 签到天数: 131 天

    [LV.7]常住居民III

    37

    主题

    867

    回帖

    3934

    积分

    荣誉版主

    积分
    3934
    发表于 2024-1-6 07:44:10 | 显示全部楼层
    这一 BIT , 如果 是 0, 解码 成 1, 产生的 后果 是,

    如果是 熄灭, 可能 微亮, 如果是 颜色显示, 则 显示的 颜色 会变

    点评

    只要发的时序正确,WS2812不会误解码的,并且允许一定的容差,我的例子用25.6MHz是最佳,但是用24MHz也没有任何问题。  详情 回复 发表于 2024-1-6 09:37
    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    550

    主题

    9222

    回帖

    1万

    积分

    管理员

    积分
    13916
    发表于 2024-1-6 08:20:32 | 显示全部楼层
    梁工:SPI驱动WS2812彩灯程序已完善更新 !
    STC8H有4个程序,SPI查询发送、中断发送、DMA中断发送、DMA中断+比较器反相。
    STC32G的3个程序,SPI查询发送、中断发送、DMA发送(不用中断,一次DMA发完720字节)


    ====================================================
    我是建议我们几个版主先完善目前看起来没问题的不加反向器的版本

    ==== 大家一起来测试这个不加反向器的版本

    ==== 荣誉版主 王同学,也强势出击推出了 STC32F12K54 的不加反向器的版本
                自古英雄出少年,也是在鞭策我们要完善: 不加反向器的版本
    截图202401060820075593.jpg
    【新提醒】使用SPI-DMA无限驱动WS2812灯带!无需反相器,STC32F上验证成功 - 有ICache的STC32F12K54测试版块 - 国芯论坛-STC全球32位8051爱好者互助交流社区 - STC全球32位8051爱好者互助交流社区 (stcaimcu.com)



    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    7 小时前
  • 签到天数: 111 天

    [LV.6]常住居民II

    1

    主题

    34

    回帖

    585

    积分

    高级会员

    积分
    585
    发表于 2024-1-6 08:20:52 | 显示全部楼层
    学习了,程序里面已改加反相,只是目前好像还没办法用DMA传大量灯的数据,受Xdata大小限制。有点好奇市面上的控制2812的点数动不动就两千三千个点的,是怎么实现的

    点评

    使用双缓冲可以实现DMA传输间隔不中断,这时候其实灯带就不受限于xdata的大小了。 因为灯带的流动多是程序实时生成或者是数组预存花样,生成的自然算是任意长度都可以。 程序空间存储流水花样的,可以利用双缓冲的  详情 回复 发表于 2024-1-6 13:00
    要加反相器也是用MCU自带的模拟比较器实现。 使用SPI传输,一个字节才2位数据,一个灯要12个字节,1000个灯要12K字节SRAM。 而一些MCU专门针对WS2812设计有驱动电路,则一个灯3个字节,1000个灯是3K字节SRAM。 用模  详情 回复 发表于 2024-1-6 09:45
    STC32G12K128的 DMA缓冲区 最大 8K 字节 即使最后谁说外部还是要加反向器,也是 STC8H/STC32 的内部比较器 当 反相器 使用 ===没必要外部增加成本  详情 回复 发表于 2024-1-6 08:24
    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    550

    主题

    9222

    回帖

    1万

    积分

    管理员

    积分
    13916
    发表于 2024-1-6 08:24:53 | 显示全部楼层
    lihappy 发表于 2024-1-6 08:20
    学习了,程序里面已改加反相,只是目前好像还没办法用DMA传大量灯的数据,受Xdata大小限制。有点好奇市面上 ...

    STC32G12K128的 DMA缓冲区 最大 8K 字节
    ===用 双缓冲算法,就没必要那么大的缓冲区

    即使最后验证还是要加外部反向器 !
    那也是 STC8H/STC32 的 内部比较器 反相器 使用
    ===没必要外部增加成本


    STC8H/STC32 的 DMA 使用 xdata;
    CPU 尽量使用 idata/edata;
    如都使用到 xdata 时,内部有总线仲裁机制


    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    550

    主题

    9222

    回帖

    1万

    积分

    管理员

    积分
    13916
    发表于 2024-1-6 09:04:53 | 显示全部楼层
    STC8H8K64U 的 比较器轨到轨 比较器
    比较器的正级输入: P3.7, P5.0, P5.1, ADCx 的输入
    比较器的负级输入: P3.6 ,内部固定信号源 1.19V

    比较器的输出:内部标志,P3.4, P4.1, 输出结果还可以取反

    截图202401060904274831.jpg
    截图202401060904499670.jpg

    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    45

    主题

    2912

    回帖

    6546

    积分

    超级版主

    积分
    6546
     楼主| 发表于 2024-1-6 09:35:58 | 显示全部楼层
    LAOXU 发表于 2024-1-6 07:17
    沙发!!!

    直接传输(非反相), 有两个问题,

    1、我的程序,一个字节传输完成后,或SPI DMA传输完成后,MOSI都是低电平。
    2、我的例子没有别的任务,所以SPI DMA中断优先级为最低,用户根据实际情况增加优先级(最下限两个宏):

    //DMA_SPI_CFG SPI_DMA配置寄存器
    #define                DMA_SPIIE        1        // SPI DMA中断使能控制位,bit7, 0:禁止SPI DMA中断,     1:允许中断。
    #define                SPI_ACT_TX        1        // SPI DMA发送数据控制位,bit6, 0:禁止SPI DMA发送数据,主机只发时钟不发数据,从机也不发. 1:允许发送。
    #define                SPI_ACT_RX        0        // SPI DMA接收数据控制位,bit5, 0:禁止SPI DMA接收数据,主机只发时钟不收数据,从机也不收. 1:允许接收。
    #define                DMA_SPIIP        0        // SPI DMA中断优先级控制位,bit3~bit2, (最低)0~3(最高).
    #define                DMA_SPIBAP        0        // SPI DMA数据总线访问优先级控制位,bit1~bit0, (最低)0~3(最高).
    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    45

    主题

    2912

    回帖

    6546

    积分

    超级版主

    积分
    6546
     楼主| 发表于 2024-1-6 09:37:50 | 显示全部楼层
    LAOXU 发表于 2024-1-6 07:44
    这一 BIT , 如果 是 0, 解码 成 1, 产生的 后果 是,

    如果是 熄灭, 可能 微亮, 如果是 颜色显示, 则 显示的 ...

    只要发的时序正确,WS2812不会误解码的,并且允许一定的容差,我的例子用25.6MHz是最佳,但是用24MHz也没有任何问题。
    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    45

    主题

    2912

    回帖

    6546

    积分

    超级版主

    积分
    6546
     楼主| 发表于 2024-1-6 09:45:01 | 显示全部楼层
    lihappy 发表于 2024-1-6 08:20
    学习了,程序里面已改加反相,只是目前好像还没办法用DMA传大量灯的数据,受Xdata大小限制。有点好奇市面上 ...

    要加反相器也是用MCU自带的模拟比较器实现。
    使用SPI传输,一个字节才2位数据,一个灯要12个字节,1000个灯要12K字节SRAM。
    而一些MCU专门针对WS2812设计有驱动电路,则一个灯3个字节,1000个灯是3K字节SRAM。

    用模拟比较器实现的反相电路:
    截图202401060944563130.jpg

    回复 支持 反对 送花

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

    GMT+8, 2024-4-27 15:40 , Processed in 0.073595 second(s), 69 queries .

    Powered by Discuz! X3.5

    © 2001-2024 Discuz! Team.

    快速回复 返回顶部 返回列表