数码之家

 找回密码
 立即注册
搜索
查看: 3524|回复: 5

[C51] DIY WS2812时钟

[复制链接]
发表于 2020-4-20 14:35:05 | 显示全部楼层 |阅读模式

爱科技、爱创意、爱折腾、爱极致,我们都是技术控

您需要 登录 才可以下载或查看,没有账号?立即注册

x
没事研究WS2812驱动,千辛万苦的搞到能带到1024支WS2812了后发现51速度太慢了,WS2812超过200支即使用到30M时钟也满足不了要求,最后也懒得优化程序了,做个半成品时钟就全拆了。
IMG20200420142110.jpg
IMG20200420142612.jpg

单片机STC15W4K 的时钟24M 如果只做时钟6M即可  乱七八糟,见谅

#include "REG51.h"   
#include "intrins.h"
#define  u8 unsigned char
sfr P0M1 = 0x93;
sfr P0M0 = 0x94;
sfr P1M1 = 0x91;
sfr P1M0 = 0x92;
sfr P2M1 = 0x95;
sfr P2M0 = 0x96;
sfr P3M1 = 0xb1;
sfr P3M0 = 0xb2;
#define ulint unsigned long int//宏定义
#define uchar unsigned char//宏定义
#define uint unsigned int//宏定义
   
long int TM;//LCD显示变量
uchar h1,h2,h3,h4,h5,h6,h7;//LCD显示变量
sbit WS2812 = P0^4;
sbit K1 = P2^3;
sbit K2 = P2^4;
sbit K3 = P2^5;
sbit K4 = P2^6;
#define numLEDs 60
unsigned char buf_R[numLEDs] = {0};//颜色缓存
unsigned char buf_G[numLEDs] = {0};
unsigned char buf_B[numLEDs] = {0};

void timer_init(void);//定时器初始化

void ws2812_write_byte(u8 dat);  

void Delay2000ms()        //@24.000MHz
{
    unsigned char i, j, k;

    _nop_();
    _nop_();
    i = 183;
    j = 100;
    k = 225;
    do
    {
        do
        {
            while (--k);
        } while (--j);
    } while (--i);
}

void HAL_Delay(unsigned int t)
{
        unsigned int x,y;
      for(x=114;x>0;x--)
      for(y=t;y>0;y--);
}


     
//复位延时
void Delay50us()        //@24.000MHz
{
    unsigned char i, j;

    i = 2;
    j = 39;
    do
    {
        while (--j);
    } while (--i);
}




//发送24位数据
void Send_2811_24bits(unsigned char G8,unsigned char R8,unsigned char B8)
{

ws2812_write_byte(G8);
ws2812_write_byte(R8);

   
//     ws2812_write_byte(G8);
//  ws2812_write_byte(R8);
     ws2812_write_byte(B8);
}
void ws2812_write_byte(u8 dat)
{
u8 i = 8;

    dat <<= 1;
    while(i)
    {
        WS2812 = 1;
        _nop_();_nop_();_nop_();_nop_();_nop_();             _nop_();   //22.1184M   //30M
        WS2812 = CY;
      _nop_();_nop_();_nop_();_nop_();_nop_();             _nop_();        
        WS2812 = 0;
        dat <<= 1;
        i--;
    }

}


//复位码
void RGB_Rst()
{
        WS2812 = 0;
        Delay50us();
}
//把24位数据GRB码转RGB
void Set_Colour(unsigned char r,unsigned char g,unsigned char b)
{
//      unsigned char i;
    unsigned int i;
        for(i=0;i<numLEDs;i++)
      {
                buf_R = r; //缓冲
              buf_G = g;
              buf_B = b;
        }
        for(i=0;i<numLEDs;i++)
        {
            Send_2811_24bits(buf_G,buf_R,buf_B);//发送显示
        }
}
//某一个点显示的颜色
void SetPointColour(unsigned int num,unsigned char r,unsigned char g,unsigned char b)
{
//      unsigned char i;
          unsigned int i;
        for(i=0;i<numLEDs;i++)
      {
                buf_R[num] = r;//缓冲
              buf_G[num] = g;
              buf_B[num] = b;
        }
        for(i=0;i<numLEDs;i++)
        {
            Send_2811_24bits(buf_G,buf_R,buf_B);//发送显示
        }
}

//颜色交换24位不拆分发
//void SetPixelColor(unsigned char num,unsigned long c)
void SetPixelColor(unsigned int num,unsigned long c)
{
//      unsigned char i;
          unsigned int i;
        for(i=0;i<numLEDs;i++)
      {
                buf_R[num] = (unsigned char)(c>>16);
              buf_G[num] = (unsigned char)(c>>8);
              buf_B[num] = (unsigned char)(c);
        }
        for(i=0;i<numLEDs;i++)
        {
            Send_2811_24bits(buf_G,buf_R,buf_B);
        }
}

//复位
void PixelUpdate()
{
    RGB_Rst();
}
//颜色
unsigned long Color(unsigned char r, unsigned char g, unsigned char b)
{
  return ((unsigned long)r << 16) | ((unsigned long)g <<  8) | b;
}

//颜色算法
unsigned long Wheel(unsigned char WheelPos)
{
  WheelPos = 255 - WheelPos;
  if(WheelPos < 85)
    {
    return Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if(WheelPos < 170) {
    WheelPos -= 85;
    return Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

//彩虹
void rainbow(unsigned int wait)
{
  unsigned int i, j;

  for(j=0; j<256; j++)
    {
    for(i=0; i<numLEDs; i++)
        {
    //  SetPixelColor(i, Wheel((i+j) & 255));
            SetPixelColor(i, Wheel((i*4+j)   & 255));
    }
        PixelUpdate();
    HAL_Delay(wait);
  }
}





//稍微不同的是,这使得彩虹均匀分布
void rainbowCycle(unsigned int wait)
{
  unsigned int i, j;

// for(j=0;j<256*5;j++)
    for(j=0;j<256;j++)
    {
    for(i=0;i<numLEDs;i++)
     {
    // SetPixelColor(i, Wheel(((i * 256 / numLEDs) + j) & 255));   
           SetPixelColor(i, Wheel(((i * 2048 / numLEDs) + j) & 255));
    }
      PixelUpdate();
    HAL_Delay (wait);
  }
}


void theaterChase(unsigned long c, unsigned int wait)
{
    int j,q;
    unsigned int i;
  for (j=0; j<10; j++)
    {  //do 10 cycles of chasing  做10个循环
    for (q=0; q < 3; q++)
        {
      for (i=0; i<numLEDs; i=i+3)
            {
        SetPixelColor(i+q, c);    //turn every third pixel on  把每一个第三个像素
      }
            PixelUpdate();
      HAL_Delay(wait);

      for (i=0; i<numLEDs; i=i+3)
            {
       SetPixelColor(i+q, 0);        //turn every third pixel off   把每一个第三个像素关掉
      }
            PixelUpdate();
    }
  }
}

void theaterChase2(unsigned long c, unsigned int wait)
{
    int j,q;
    unsigned int i;
  for (j=0; j<10; j++)
    {  //do 10 cycles of chasing  做10个循环
    for (q=0; q < 2; q++)
        {
      for (i=0; i<numLEDs; i=i+2)
            {
        SetPixelColor(i+q, c);    //turn every third pixel on  把每一个第三个像素
      }
            PixelUpdate();
      HAL_Delay(wait);

      for (i=0; i<numLEDs; i=i+2)
            {
       SetPixelColor(i+q, 0);        //turn every third pixel off   把每一个第三个像素关掉
      }
            PixelUpdate();
    }
  }
}



//Theatre-style crawling lights with rainbow effect
//带有彩虹效果的戏剧式爬行灯
void theaterChaseRainbow(unsigned int wait)
{
    int j,q;
    unsigned int i;
  for (j=0; j < 256; j++)
    {     // cycle all 256 colors in the wheel 在轮子上循环所有256色
    for (q=0; q < 3; q++)
        {
      for (i=0; i < numLEDs; i=i+3)
            {
        SetPixelColor(i+q, Wheel( (i+j) % 255));    //turn every third pixel off 把每一个第三个像素
      }
      PixelUpdate();

      HAL_Delay(wait);

      for (i=0; i < numLEDs; i=i+3)
            {
        SetPixelColor(i+q, 0);        //turn every third pixel off  把每一个第三个像素关掉
      }
    }
  }
}
void theaterChaseRainbow2(unsigned int wait)
{
    int j,q;
    unsigned int i;
  for (j=0; j < 256; j++)
    {     // cycle all 256 colors in the wheel 在轮子上循环所有256色
    for (q=0; q < 2; q++)
        {
      for (i=0; i < numLEDs; i=i+2)
            {
       // SetPixelColor(i+q, Wheel( (i+j) % 255));    //turn every third pixel off 把每一个第三个像素
                        SetPixelColor(i+q, Wheel( (i*8+j) % 255));    //turn every third pixel off 把每一个第三个像素
      }
      PixelUpdate();

      HAL_Delay(wait);

      for (i=0; i < numLEDs; i=i+2)
            {
        SetPixelColor(i+q, 0);        //turn every third pixel off  把每一个第三个像素关掉
      }
    }
  }
}

// Fill the dots one after the other with a color
//用一种颜色填充这些圆点
void colorWipe(unsigned long c, unsigned int wait)
{
    unsigned int i=0;
  for( i=0; i<numLEDs; i++)
    {
    SetPixelColor(i, c);
    PixelUpdate();
    HAL_Delay(wait);
  }
}

//单灯流水
    void Watercolor(unsigned long c, unsigned int wait)
    {
//      unsigned char i=0;
            unsigned int i=0;
      for( i=0; i<numLEDs; i++)
    {
        SetPixelColor(i, c);
      PixelUpdate();
        HAL_Delay(wait*5);
    SetPixelColor(i, 0);
       PixelUpdate();
        HAL_Delay(wait);
      }
    }

        
        
void timer_init(void)//定时器初始化                                     50MS
{
     TMOD=0x01;/////////设置工作方式1
      TH0=(65536-50000)/256;///////赋值
      TL0=(65536-50000)%256;
     EA=1;ET0=1;//开总中断;开定时器中断
     TR0=1;////////启动计数器
}
void timer0()interrupt 1  //定时中断
{

     TR0=0;
      TH0=(65536-50000)/256;///////赋初值
      TL0=(65536-50000)%256;
                                
     {
         
        if(h4>39)
        {
         h4=0;
            TM++;


    h1=TM/720;
    h2=TM%3600/60;
h3=TM%3600%60;
        
   



Set_Colour(0,0,0);
            SetPointColour(h1,0,127,0); // grb
             SetPointColour(h2,127,0,0); // grb  
            SetPointColour(h3,0,0,127); // grb
        
              
        }
        if(TM>43199)
        {
        TM=0;
        }
                 h4++;                           
        
    }

        
      
     TR0=1;
}        
        

void main()
{
    P0M0 = 0xFF;
    P0M1 = 0x00;
    P1M0 = 0x00;
    P1M1 = 0x00;
    P2M0 = 0x00;
    P2M1 = 0x00;
    P3M0 = 0x00;
    P3M1 = 0x00;
   colorWipe(0xff0000,0);
            //Set_Colour(0,0,0); //一下全黑
                        colorWipe(0x000000,0);  //彩虹7色
                    colorWipe(0xff7f00,0);
                        colorWipe(0x000000,0);        
                        colorWipe(0xffff00,0);
                        colorWipe(0x000000,0);        
                        colorWipe(0x00ff00,0);
                        colorWipe(0x000000,0);
                        colorWipe(0x00ffff,0);
                        colorWipe(0x000000,0);
                        colorWipe(0x0000ff,0);
                        colorWipe(0x000000,0);
                     colorWipe(0x8b00ff,0);
                        colorWipe(0x000000,0);
                                        Set_Colour(0,0,0); //一下全黑

   
   
//SetPointColour(9,255,0,0); // grb

//SetPointColour(19,255,0,0); // grb
//SetPointColour(20,255,0,0); // grb
//SetPointColour(23,255,0,0); // grb
//SetPointColour(24,255,0,0); // grb
//SetPointColour(31,255,0,0); // grb
//SetPointColour(32,255,0,0); // grb
//SetPointColour(39,255,0,0); // grb
//SetPointColour(41,255,0,0); // grb
//SetPointColour(46,255,0,0); // grb
//SetPointColour(50,255,0,0); // grb
//SetPointColour(53,255,0,0); // grb
//SetPointColour(59,255,0,0); // grb
//SetPointColour(60,255,0,0); // grb
Delay2000ms();

Set_Colour(0,0,0);
         timer_init();//定时器初始化   
//Delay3000ms();
//rainbowCycle(0);
//Set_Colour(0,0,0);
h5=01;
h6=10;
h7=0;

TM=h5*3600+h6*60+h7;

        while(1)
        {
            
            
            
            
        //    Set_Colour(16,16,16);
    //    rainbow(0);
         //    rainbowCycle(0);
            if(K1==0){
                rainbow(45);//彩虹
                Set_Colour(0,0,0); //一下全黑
            }//彩虹
            if(K2==0){
                rainbowCycle(0);////稍微不同的是,这使得彩虹均匀分布;
                Set_Colour(0,0,0); //一下全黑
            }//彩虹            
                        if(K3==0){
                   Watercolor(0xff0000, 255);//红色单灯流水

     Watercolor(0x00ff00, 255);//绿色单灯流水

      Watercolor(0x0000ff, 255);//蓝色单灯流水
                            Set_Colour(0,0,0); //一下全黑

            }
            
                                    if(K4==0){
             colorWipe(0xff0000,0);
            //Set_Colour(0,0,0); //一下全黑
                        colorWipe(0x000000,255);  //彩虹7色
                    colorWipe(0xff7f00,0);
                        colorWipe(0x000000,0);        
                        colorWipe(0xffff00,0);
                        colorWipe(0x000000,0);        
                        colorWipe(0x00ff00,0);
                        colorWipe(0x000000,0);
                        colorWipe(0x00ffff,0);
                        colorWipe(0x000000,0);
                        colorWipe(0x0000ff,0);
                        colorWipe(0x000000,0);
                     colorWipe(0x8b00ff,0);
                        colorWipe(0x000000,0);
                                        Set_Colour(0,0,0); //一下全黑

            }

  //Set_Colour(221,156,1);// 全屏颜色
  //        Watercolor(0xff0000, 0);//红色单灯流水
//         HAL_Delay(1000);
  //     Watercolor(0x00ff00, 0);//绿色单灯流水
  //       HAL_Delay(1000);
   //     Watercolor(0x0000ff, 0);//蓝色单灯流水
  //        HAL_Delay(1000);  ///延时是22m的 是多久 22M 0.17MS

//h4=6;
//SetPointColour(h2,255,0,0); // grb   
            

    //          theaterChase(Color(55,0,0),0); // 必须3的倍数
            //  theaterChase2(Color(0,0,255),80); // Blue
        
  //theaterChaseRainbow(0);  //带有彩虹效果的戏剧式爬行灯
        
    //                colorWipe(0xff0000,0);
            //Set_Colour(0,0,0); //一下全黑
    //                    colorWipe(0x000000,0);  //彩虹7色
//                    colorWipe(0xff7f00,0);
    //                    colorWipe(0x000000,0);        
    //                    colorWipe(0xffff00,0);
//                        colorWipe(0x000000,0);        
    //                colorWipe(0x00ff00,0);
    //                    colorWipe(0x000000,0);
    //                colorWipe(0x00ffff,0);
    //                    colorWipe(0x000000,0);
    //                    colorWipe(0x0000ff,0);
    //                    colorWipe(0x000000,0);
    //                colorWipe(0x8b00ff,0);
    //                    colorWipe(0x000000,0);
//theaterChaseRainbow2(0);
        }
}



打赏

参与人数 3家元 +48 收起 理由
人艰不拆了 + 10
家睦 + 30
zidian + 8

查看全部打赏

发表于 2020-4-20 16:31:15 | 显示全部楼层
这个好像速率要求大于1M吧,忘了,反正uno不特别处理是驱动不起来的,你的51能输出多快呢?:loveliness:
回复 支持 反对

使用道具 举报

发表于 2020-4-20 19:13:46 | 显示全部楼层
换STM32吧,DMA+SPI或者DMA+PWM,刷新WS2812可以达到其极限速率:lol:
回复 支持 反对

使用道具 举报

发表于 2020-4-21 00:57:55 | 显示全部楼层
请楼主讲讲 设计思路?
谢谢!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-4-23 08:07:19 | 显示全部楼层
不好意思 程序中有大BUG,中断里面干的活太多了,以至于一小时慢一分钟多,更改了一下,实验过了修正了错误,24小时走时正常。
void timer0()interrupt 1  //定时中断
{

        TR0=0;
          TH0=(65536-50000)/256;///////赋初值
          TL0=(65536-50000)%256;
                                                          
        {
               
       
                  h4++;         
                if(h4==40)
                {
            h4=0;
                        TM++;
              
      if(TM>43199)
                {
                TM=0;
                }

                h8=1;                         
                }
               
                                                                   
               
        }

               
         
        TR0=1;
}               


if(h8==1)
        {
        h1=TM/720;
  h2=TM%3600/60;
  h3=TM%3600%60;
               

      Set_Colour(0,0,0);
                        SetPointColour(h1,0,127,0); // grb
                        SetPointColour(h2,127,0,0); // grb  
                        SetPointColour(h3,0,0,127); // grb        
                h8=0;
        }
回复 支持 反对

使用道具 举报

发表于 2020-4-23 17:17:56 | 显示全部楼层
居然还是劳力士
壕!:time:
回复 支持 反对

使用道具 举报

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

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2024-4-20 14:38 , Processed in 0.327600 second(s), 17 queries , Redis On.

Powered by Discuz!

© 2006-2023 smzj.net

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