找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 8129|回复: 15
打印 上一主题 下一主题
收起左侧

STC8系列单片机WS2812驱动程序

  [复制链接]
跳转到指定楼层
楼主
依照STC-Y6指令集编写,编译时Keil优化选项默认,理论上STC8全系列通用。
只需配置IO口和系统工作时钟即可使用,系统时钟目前适配范围为5.5296-48MHz。
STC8H8K64S4U@12.0MHz驱动效果如下图:
(分别点亮三个灯,颜色为B,G,R)


主要使用的单字节数据发送函数如下:

  1. #include "ws2812.h"

  2. void WS2812_SendByte(unsigned char dat)
  3. {
  4.     unsigned char i = 8;
  5.     dat <<= 1;
  6.     while (i)
  7.     {
  8.         WS2812_IO = 1;

  9.         //5.5296 - 6.8
  10.         #if SYS_FREQ < 55296 || SYS_FREQ > 480000
  11.         #error 频率未适配, 不在 5.5296-48MHz
  12.         #else
  13.         _nop_();
  14.         #endif

  15.         //6.8 - 10.8
  16.         #if SYS_FREQ >= 68000
  17.         _nop_();
  18.         #endif

  19.         //10.8 – 21.4
  20.         #if SYS_FREQ >= 108000
  21.         _nop_();
  22.         _nop_();
  23.         #endif

  24.         //21.4 – 29.5
  25.         #if SYS_FREQ >= 214000
  26.         _nop_();
  27.         _nop_();
  28.         #endif

  29.         //29.5 – 35.0
  30.         #if SYS_FREQ >= 295000
  31.         _nop_();
  32.         _nop_();
  33.         #endif

  34.         //35.0 – 40.7
  35.         #if SYS_FREQ >= 350000
  36.         _nop_();
  37.         _nop_();
  38.         #endif

  39.         //40.7 – 46.8
  40.         #if SYS_FREQ >= 407000
  41.         _nop_();
  42.         _nop_();
  43.         #endif

  44.         //46.8 – 48
  45.         #if SYS_FREQ >= 468000
  46.         _nop_();
  47.         _nop_();
  48.         #endif

  49.         WS2812_IO = CY;
  50.         //5.5296 - 6.8
  51.         #if SYS_FREQ < 55296 || SYS_FREQ > 480000
  52.         #error 频率未适配
  53.         #else
  54.         _nop_();
  55.         #endif

  56.         //6.8 - 10.8
  57.         #if SYS_FREQ >= 68000
  58.         _nop_();
  59.         #endif

  60.         //10.8 – 21.4
  61.         #if SYS_FREQ >= 108000
  62.         _nop_();
  63.         _nop_();
  64.         #endif

  65.         //21.4 – 29.5
  66.         #if SYS_FREQ >= 214000
  67.         _nop_();
  68.         _nop_();
  69.         #endif

  70.         //29.5 – 35.0
  71.         #if SYS_FREQ >= 295000
  72.         _nop_();
  73.         _nop_();
  74.         #endif

  75.         //35.0 – 40.7
  76.         #if SYS_FREQ >= 350000
  77.         _nop_();
  78.         _nop_();
  79.         #endif

  80.         //40.7 – 46.8
  81.         #if SYS_FREQ >= 407000
  82.         _nop_();
  83.         _nop_();
  84.         #endif

  85.         //46.8 – 48
  86.         #if SYS_FREQ >= 468000
  87.         _nop_();
  88.         _nop_();
  89.         #endif
  90.         WS2812_IO = 0;
  91.         dat <<= 1;
  92.         i--;
  93.     }
  94. }

  95. void Send_WS2812RGB(unsigned char r, unsigned char g, unsigned char b)
  96. {
  97.     WS2812_SendByte(g);
  98.     WS2812_SendByte(r);
  99.     WS2812_SendByte(b);
  100. }

  101. void Send_WS2812(unsigned long dat)
  102. {
  103.     WS2812_SendByte(dat >> 8 & 0xff);
  104.     WS2812_SendByte(dat >> 16 & 0xff);
  105.     WS2812_SendByte(dat & 0xff);
  106. }
复制代码
附测试样例:
WS2812.zip (18.51 KB, 下载次数: 251)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

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

使用道具 举报

沙发
ID:836437 发表于 2021-1-12 12:49 | 只看该作者
方式不错
回复

使用道具 举报

板凳
ID:390416 发表于 2021-1-15 20:58 | 只看该作者
一开始就移位了,你确定这样数据不出错吗?
回复

使用道具 举报

地板
ID:877820 发表于 2021-1-20 17:54 | 只看该作者
如何点亮单个灯呢
回复

使用道具 举报

5#
ID:290373 发表于 2021-1-21 17:22 | 只看该作者
人人学会单片机 发表于 2021-1-15 20:58
一开始就移位了,你确定这样数据不出错吗?

数据是完整的,用了CY位存储的位移结果,其他运算在数据传输的循环里也不会影响CY。
这是传送了一字节的0x55的波形:

回复

使用道具 举报

6#
ID:290373 发表于 2021-1-21 17:23 | 只看该作者
1436405015 发表于 2021-1-20 17:54
如何点亮单个灯呢

送几个数据点几个灯
回复

使用道具 举报

7#
ID:325642 发表于 2021-1-24 21:06 | 只看该作者
这样的LED在颜色不变时,亮度怎么调呢
回复

使用道具 举报

8#
ID:718536 发表于 2021-3-4 01:19 | 只看该作者
冬天的野狼 发表于 2021-1-24 21:06
这样的LED在颜色不变时,亮度怎么调呢

RGB颜色 0-255级别亮度。0就是不亮。0,0,0就是三个颜色都灭了。
回复

使用道具 举报

9#
ID:973749 发表于 2021-11-1 17:19 | 只看该作者
冬天的野狼 发表于 2021-1-24 21:06
这样的LED在颜色不变时,亮度怎么调呢

按楼主程序,比如开始你是绿色最亮:
  1. Send_WS2812RGB(255,0,0);
复制代码

调整到一半亮度就是255/2=128:
  1. Send_WS2812RGB(128,0,0);
复制代码
回复

使用道具 举报

10#
ID:1015077 发表于 2022-4-19 14:54 | 只看该作者
eastwife 发表于 2021-11-1 17:19
按楼主程序,比如开始你是绿色最亮:

调整到一半亮度就是255/2=128:

可是例如RGB(255,255,255)的白色调到一半(128,128,128)变成了灰色,它颜色改变了呀,请问可以不改变颜色只改变亮度吗
回复

使用道具 举报

11#
ID:99525 发表于 2022-5-31 07:30 | 只看该作者
Berri 发表于 2022-4-19 14:54
可是例如RGB(255,255,255)的白色调到一半(128,128,128)变成了灰色,它颜色改变了呀,请问可以不 ...

白色变暗,那不就是灰色吗?
回复

使用道具 举报

12#
ID:136485 发表于 2022-5-31 08:48 | 只看该作者
刚好前段时间也有弄这个,下载下来参考参考
回复

使用道具 举报

13#
ID:399179 发表于 2023-4-10 21:15 来自手机 | 只看该作者
真在研究这个,谢谢!
回复

使用道具 举报

14#
ID:398094 发表于 2023-11-22 09:19 | 只看该作者
如何点亮单个灯呢
回复

使用道具 举报

15#
ID:373976 发表于 2023-11-26 10:12 | 只看该作者
想法不错,一会儿测试一下
回复

使用道具 举报

16#
ID:1104147 发表于 2023-12-13 17:18 | 只看该作者
这是IO口点的?
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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