找回密码
 立即注册

QQ登录

只需一步,快速开始

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

STC15F104W 51单片机同系列芯片驱动WS2812彩灯程序

[复制链接]
跳转到指定楼层
楼主
使用的芯片为STC15F104W同系列的IRC15F107W,只有该型号的芯片能驱动WS2812的RGB彩灯!
因为该型号的芯片使用内置24Mhz时钟,而WS2812的时序要求精确到ns级别,于是对时钟的最低要求就是24Mhz
而且IRC15F107W同STC15F104W,只有8个引脚的简单封装,并且内部自带震荡源无须外部晶振,插上电直接就能用
最重要的是和其它C51单片机通用头文件,所以引用的时候只需要包含reg52.h文件即可!
所以该单片机非常适合新手入门,即便是小白看了也能学会!
/*
IRC15F107W 管脚(默认内部震荡源24Mhz)
1 P3.4
2 VCC  3.8--5.5V
3 P3.5
4 GND
5 P3.0 接烧录器的TXD
6 P3.1 接烧录器的RXD
7 P3.2
8 P3.3
*/

然后是代码部分,我用的双色流水灯做的范例
  1. #include "reg52.h"
  2. #include "intrins.h"
  3. #define WS2812_NUM 60  //灯的数量
  4. sbit Led_Pin = P3^0;    //控制灯的引脚
  5. unsigned short G_0=191;//流水灯第一个颜色定义
  6. unsigned short R_0=98;
  7. unsigned short B_0=10;
  8. unsigned short G_1=11;//流水灯第二个颜色定义
  9. unsigned short B_1=45;
  10. unsigned short R_1=14;
复制代码
然后就是用STC烧录软件自带的延时计算器一键推出的延迟函数
  1. void delay_ms(unsigned int ms)        //@24.000MHz
  2. {
  3.         unsigned char data i, j;
  4.   while(ms--){
  5.         _nop_();
  6.         i = 24;
  7.         j = 85;
  8.         do
  9.         {
  10.                 while (--j);
  11.         } while (--i);
  12. }
  13. }
  14. void Delay75us(void)        //@24.000MHz
  15. {
  16.         unsigned char data i, j;

  17.         i = 2;
  18.         j = 189;
  19.         do
  20.         {
  21.                 while (--j);
  22.         } while (--i);
  23. }
复制代码
然后是WS2812写入0和1的程序
  1. void ws2812_writebit1(void){
  2. Led_Pin=1;
  3. _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
  4. _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
  5.         Led_Pin=!Led_Pin;
  6. //_nop_();_nop_();_nop_();
  7. }

  8. void ws2812_writebit0(void){
  9. Led_Pin=1;
  10. _nop_();_nop_();_nop_();_nop_();_nop_();
  11. Led_Pin=!Led_Pin;
  12. _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
  13. _nop_();_nop_();_nop_();_nop_();
  14. }
复制代码
然后是写入单个颜色和总体颜色的程序
  1. void ws2812_writecolor(unsigned short dat){
  2. //由于STC8G1K08执行左移或者右移等移位操作耗时太久(2us,无符号短整型都这样),导致时序严重落后,所以用原始的if-else代码进行代替
  3.         if(dat&0x80)
  4.   ws2812_writebit1();
  5. else
  6.   ws2812_writebit0();
  7. if(dat&0x40)
  8.          ws2812_writebit1();
  9. else
  10.   ws2812_writebit0();
  11. if(dat&0x20)
  12.          ws2812_writebit1();
  13. else
  14.   ws2812_writebit0();
  15. if(dat&0x10)
  16.          ws2812_writebit1();
  17. else
  18.   ws2812_writebit0();
  19. if(dat&0x08)
  20.          ws2812_writebit1();
  21. else
  22.   ws2812_writebit0();
  23. if(dat&0x04)
  24.          ws2812_writebit1();
  25. else
  26.   ws2812_writebit0();
  27. if(dat&0x02)
  28.          ws2812_writebit1();
  29. else
  30.   ws2812_writebit0();
  31. if(dat&0x01)
  32.          ws2812_writebit1();
  33. else
  34.   ws2812_writebit0();
  35. }
  36. void ws2812_writeled(unsigned short green,unsigned short red,unsigned short blue){
  37. ws2812_writecolor(green);
  38. ws2812_writecolor(red);
  39. ws2812_writecolor(blue);
  40. }        
复制代码
然后是WS2812执行到最后一颗灯用的结尾程序,以及清屏程序
  1. void ws2812_rest()
  2. {
  3.         Led_Pin=0;
  4.         
  5.         Delay75us();
  6. }
  7. void ws2812_clear()
  8. {
  9.         static int j=0;
  10.         for(j=0;j<WS2812_NUM;j++)
  11.         {
  12.                 ws2812_writeled(0,0,0);
  13.         }
  14.         ws2812_rest();
  15.         ws2812_rest();
  16.         ws2812_rest();
  17. }
复制代码
流水灯主程序
  1. void WS2812_DIS()
  2. {
  3.         static int j=0;
  4.         int i;

  5.         j%=WS2812_NUM;
  6.         j++;

  7.         for(i=0;i<WS2812_NUM;i++)
  8.         {
  9.                 if(i>j&&(i<j+10))
  10.                 {
  11.                         ws2812_writeled(G_0,R_0,B_0);
  12.                 }
  13.                 else
  14.                 {
  15.                         ws2812_writeled(G_1,R_1,B_1);
  16.                         
  17.                 }
  18.         }
  19.         
  20. }

  21. void main(void)
  22. {
  23.         ws2812_clear();
  24.         while(1)
  25.   {
  26.                 WS2812_DIS();
  27.                 delay_ms(50);
  28.         }
  29. }
复制代码

希望大家能学到东西!完整代码在压缩包里!

20181222194755537.png (69.11 KB, 下载次数: 126)

WS2812时序图

WS2812时序图

STC15F104_WS2812.rar

24.59 KB, 下载次数: 46, 下载积分: 黑币 -5

代码本体

评分

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

查看全部评分

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

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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