找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4341|回复: 13
收起左侧

这个WS2812驱动程序,指定点亮具体的那一颗LED灯、什么颜色,应该怎么操作呢?

  [复制链接]
ID:856401 发表于 2021-7-5 19:50 来自手机 | 显示全部楼层 |阅读模式
5黑币

#include <STC15F2K60S2.H>
#include "intrins.h"

sbit WS2812 = P1^7;

#define numLEDs 8   //灯的个数
unsigned char buf_R[numLEDs] = {0};//颜色缓存
unsigned char buf_G[numLEDs] = {0};
unsigned char buf_B[numLEDs] = {0};

void RGB_Set_Up();  //送0码
void RGB_Set_Down(); //送1码



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


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

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


//1码,高电平850ns 低电平400ns 误差正负150ns
void RGB_Set_Up()
{
                WS2812 = 1;
          //经过逻辑分析仪调试的的延时
                _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();
          _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();_nop_();
                WS2812 = 0;
}

//1码,高电平400ns 低电平850ns 误差正负150ns
void RGB_Set_Down()
{
                WS2812 = 1;
          //经过逻辑分析仪调试的的延时
                _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();  
                WS2812 = 0;
}

//发送24位数据
void Send_2811_24bits(unsigned char G8,unsigned char R8,unsigned char B8)
{
          
          unsigned int n = 0;
          //发送G8位
                for(n=0;n<8;n++)
                {
                        G8<<=n;
                        if(G8&0x80 == 0x80)
                        {
                                RGB_Set_Up();
                        }
                        else  
                        {
                          RGB_Set_Down();
                        }
                }
                //发送R8位
                for(n=0;n<8;n++)
                {
                        R8<<=n;
                        if(R8&0x80 == 0x80)
                        {
                                RGB_Set_Up();
                        }
                        else  
                        {
                                RGB_Set_Down();
                        }
                       
                }
                //发送B8位
          for(n=0;n<8;n++)
                {
                        B8<<=n;
                        if(B8&0x80 == 0x80)
                        {
                                RGB_Set_Up();
                        }
                        else  
                        {
                          RGB_Set_Down();
                        }
                }
}
//复位码
void RGB_Rst()
{
                WS2812 = 0;
                Delay50us();
}
//把24位数据GRB码转RGB
void Set_Colour(unsigned char r,unsigned char g,unsigned char b)
{
          unsigned char i;
                for(i=0;i<numLEDs;i++)
          {
                                buf_R[i] = r; //缓冲
                          buf_G[i] = g;
                          buf_B[i] = b;
                }
                for(i=0;i<numLEDs;i++)
                {
                        Send_2811_24bits(buf_G[i],buf_R[i],buf_B[i]);//发送显示
                }
}
//某一个点显示的颜色
void SetPointColour(unsigned int num,unsigned char r,unsigned char g,unsigned char b)
{
          unsigned char 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[i],buf_R[i],buf_B[i]);//发送显示
                }
}

//颜色交换24位不拆分发
void SetPixelColor(unsigned char num,unsigned long c)
{
          unsigned char 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[i],buf_R[i],buf_B[i]);
                }
}

//复位
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));
    }
                PixelUpdate();
    HAL_Delay(wait);
  }
}

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

  for(j=0;j<256*5;j++)
        { // 5 cycles of all colors on wheel  车轮上所有颜色的5个循环
    for(i=0;i<numLEDs;i++)
         {
     SetPixelColor(i, Wheel(((i * 256 / numLEDs) + j) & 255));
    }
          PixelUpdate();
    HAL_Delay (wait);
  }
}

//Theatre-style crawling lights.呼吸灯
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();
    }
  }
}

//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  把每一个第三个像素关掉
      }
    }
  }
}

// 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 main()
{
          
                while(1)
                {
                          rainbow(45);
        rainbowCycle(40);
        theaterChase(Color(0,0,255),80); // Blue
                          theaterChase(Color(0,255,0),80); // Blue
                          theaterChase(Color(255,0,0),80); // Blue
                    theaterChaseRainbow(40);
                                colorWipe(255,255);
                }
}

回复

使用道具 举报

ID:390416 发表于 2021-7-6 20:26 | 显示全部楼层
回复

使用道具 举报

ID:885138 发表于 2021-7-7 18:52 来自手机 | 显示全部楼层
三个字节一组,第一个led显示最先发的第一组,并将之后的教据向后转发,第二个led留下第2组……直至无数据
回复

使用道具 举报

ID:885138 发表于 2021-7-7 18:54 来自手机 | 显示全部楼层
调用这个函数//发送24位数据 void Send_2811_24bits(unsigned char G8,unsigned char R8,unsigned char B8)
回复

使用道具 举报

ID:811711 发表于 2021-7-8 08:39 | 显示全部楼层
二楼基本正确
回复

使用道具 举报

ID:811711 发表于 2021-7-8 17:22 | 显示全部楼层
这代码也太长了把。。。
回复

使用道具 举报

ID:411116 发表于 2021-9-23 22:10 | 显示全部楼层
这句代码就可以控制SetPixelColor(5, 255);括号里第一个数字代表第几个LED,第二个数字代表颜色
回复

使用道具 举报

ID:399179 发表于 2021-12-11 21:34 来自手机 | 显示全部楼层
rong433 发表于 2021-9-23 22:10
这句代码就可以控制SetPixelColor(5, 255);括号里第一个数字代表第几个LED,第二个数字代表颜色

能具体帖个程序来吗?谢谢!
回复

使用道具 举报

ID:89515 发表于 2021-12-12 15:45 | 显示全部楼层
你需要显示第几个灯就将它前面的几个灯的占空比写0就行了,自己很容易封装一个函数出来
回复

使用道具 举报

ID:399179 发表于 2021-12-21 19:39 来自手机 | 显示全部楼层
mengzhixinheng 发表于 2021-12-12 15:45
你需要显示第几个灯就将它前面的几个灯的占空比写0就行了,自己很容易封装一个函数出来

我等小白能力不够啊!
回复

使用道具 举报

ID:962286 发表于 2021-12-22 11:12 | 显示全部楼层
做一个显存来存所有灯的状态,然后需要改变哪个灯或者哪几个灯的颜色或者亮度,就更改对应的显存,最后把显存的数据发送到WS2812的总线上。
回复

使用道具 举报

ID:860003 发表于 2022-1-14 12:27 | 显示全部楼层
三个字节一组,第一个led显示最先发的第一组,并将之后的教据向后转发,第二个led留下第2组……直至无数据。能做时钟!
回复

使用道具 举报

ID:1015077 发表于 2022-4-19 15:05 | 显示全部楼层
请问以下如何只改变灯的亮度而不改变颜色?我试着改变RGB值颜色也会改变。比如RGB(255,255,255),调成RGB(128,128,128)就会从白色变成灰色
回复

使用道具 举报

ID:844772 发表于 2022-4-19 15:39 | 显示全部楼层
Berri 发表于 2022-4-19 15:05
请问以下如何只改变灯的亮度而不改变颜色?我试着改变RGB值颜色也会改变。比如RGB(255,255,255),调成R ...

那是因为人眼睛对不同色光的敏感不同,对黄色相对更敏感,改变亮度时各个分色的数字不是同步减少,你可以用电脑调好数值。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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