好学天上 发表于 2024-8-5 10:02:12

梁工,请问我用STC8G1K08A的芯片驱动这个WS2812然后接了可能五百个灯,我就想用串口发送灯选择和颜色选择,每次一个灯亮就行应该怎么写呀,看这个代码里面看不懂{:4_184:}。就是比如说我发996W,就是第九九六个灯亮白色,亮度就最亮,然后其他的灯都是灭的。可以解惑一下莫{:4_197:}

梁工 发表于 2024-8-5 14:50:35

好学天上 发表于 2024-8-5 10:02
梁工,请问我用STC8G1K08A的芯片驱动这个WS2812然后接了可能五百个灯,我就想用串口发送灯选择和颜色选择, ...

WS2812是一个个往后传数据的,每个灯3个字节,每个灯接收到3个字节就旁路掉数据,之后的数据就往后传。你要点亮第996个灯,前面995个灯也要发数据,不亮就发0x00,要先发995*3个字节,接着发3个字节才是第996个灯的数据。

好学天上 发表于 2024-8-5 15:02:06

梁工 发表于 2024-8-5 14:50
WS2812是一个个往后传数据的,每个灯3个字节,每个灯接收到3个字节就旁路掉数据,之后的数据就往后传。你 ...

#define         MAIN_Fosc                11059200        //定义主时钟

#include        "STC8Hxxx.h"
#include"intrins.h"

#define                WS2812                P54                //GPIO
#define                LED                1             //灯珠个数
unsigned char RED,GREEN,BLUE;

/*----------------------------延时10us@STC-Y6@11.0592MHz----------------------------*/
void Delay_10us(void)
{
      unsigned char i;
      i=35;
      while(--i);
}

/*----------------------------延时x10us----------------------------*/
void Delay_x10us(unsigned char x)
{
      while(x--)
                Delay_10us();
}

/*----------------------------延时10ms@STC-Y6@11.0592MHz----------------------------*/
//void Delay_10ms(void)
//{
//      unsigned char i,j;
//      _nop_();
//      _nop_();
//      i=144;
//      j=157;
//      do
//      {
//                while(--j);
//      }while(--i);
//}

/*----------------------------延时x10ms----------------------------*/
//void Delay_x10ms(unsigned char x)
//{
//      while(x--)
//                Delay_10ms();
//}

void WS2812_Reset(void)
{
      WS2812=0;
      Delay_x10us(10);
}

void WS2812_Write_Byte(unsigned char data temp)      //STC-Y6@11.0592MHz 0:375ns+1350ns 1:925ns+1350ns
{
      unsigned char data i=8;
      while(i)
      {
                temp<<=1;
                WS2812=1;
                if(CY)
                {
                        _nop_();
                        _nop_();
                        _nop_();
                        _nop_();
                        _nop_();
                        _nop_();
                        _nop_();
                        _nop_();
                }
                WS2812=0;
                _nop_();
                _nop_();
                _nop_();
                _nop_();
                _nop_();
                _nop_();
                _nop_();
                _nop_();
                i--;
      }
}

unsigned int LED_ON = 5;      //第几个亮

void WS2812_Write(void)

{
      unsigned int i;
      WS2812_Reset();
      i=0;

      while(1)
      {
                if(i==LED_ON)
                {
                        WS2812_Write_Byte(GREEN);
                        WS2812_Write_Byte(RED);
                        WS2812_Write_Byte(BLUE);
                        break;

                }
                else
                {
                        WS2812_Write_Byte(0);
                        WS2812_Write_Byte(0);
                        WS2812_Write_Byte(0);
                        i++;

                }
      }
}

void Init(void)
{
            P5M0 = 0x10;
                                                P5M1 = 0x00;

}

void main(void)
{
      Init();
      while(1)
      {
                RED=255;      //红 0~255
                GREEN=0;      //绿 0~255
                BLUE=0;      //蓝 0~255
                WS2812_Write();
      }
}

我这样整但他还是全亮,然后颜色也是白色

梁工 发表于 2024-8-5 16:12:10

好学天上 发表于 2024-8-5 15:02
我这样整但他还是全亮,然后颜色也是白色

时序明显不对,发数据位0时全部是高电平,这是不对的。
数据0:高电平0.9us,低电平大于等于0.35us。
数据1:高电平0.3us,低电平大于等于0.95us。

好学天上 发表于 2024-8-5 17:30:06

梁工 发表于 2024-8-5 16:12
时序明显不对,发数据位0时全部是高电平,这是不对的。
数据0:高电平0.9us,低电平大于等于0.35us。
数 ...

按照这个要几个nop函数呀,我看百度说12MHZ一个nop()是1微秒,可是我要延时零点几微秒叻

好学天上 发表于 2024-8-5 17:35:45

梁工 发表于 2024-8-5 16:12
时序明显不对,发数据位0时全部是高电平,这是不对的。
数据0:高电平0.9us,低电平大于等于0.35us。
数 ...

void send_L(void)
{
       WS2812=0;
       _nop_();
       _nop_();
       WS2812=1;
                        _nop_();
                        _nop_();
                        _nop_();

                        _nop_();
                        _nop_();
                        _nop_();
       WS2812=0;
}
void send_H(void)
{
       WS2812=0;
       _nop_();
       _nop_();
       _nop_();
             _nop_();
       _nop_();

       WS2812=1;
                        _nop_();
                        _nop_();
                        _nop_();               
       WS2812=0;
}
void rest(void)
{
       WS2812=0;
       _nop_();
       _nop_();
       _nop_();
             _nop_();
       _nop_();
       _nop_();       
       WS2812=0;
}
void send_one_byte(unsigned char in_data)
{
          unsigned char temp1=0;
                unsigned char temp2=0;
                unsigned char temp3=0;
                unsigned char i=0;
           temp1=in_data;
          for(i=0;i<8;i++)//八位,循环八次
                        {
                                if(temp1&0x01)
                                        send_H();
                                else
                                        send_L();
                                temp1 >>= 1;//从最低位到最高位
                        }
}

void set_one_led(unsigned char R_data,unsigned char G_data,unsigned char B_data)
{
send_one_byte(R_data);
        send_one_byte(G_data);
        send_one_byte(B_data);
}

void WS2812_Write(void)

{
      unsigned int i;
      WS2812_Reset();
      i=0;

      while(1)
      {
                if(i==LED_ON)
                {
                        set_one_led(RED,GREEN,BLUE);
                        break;

                }
                else
                {
                        set_one_led(0,0,0);
                        i++;
                }
      }
}
这样写还是不行,还是全亮{:4_184:}

梁工 发表于 2024-8-5 17:51:57

好学天上 发表于 2024-8-5 17:35
这样写还是不行,还是全亮
你H和L反了,并且时间也不对。还不知道STC是单周期的?一个NOP是一个时钟。如此简单的时序:
对于12MHz,发数据1:
DIN = 1;
10个NOP;
DIN=0;
3个NOP;

对于12MHz,发数据0:
DIN = 1;
3个NOP;
DIN=0;
10个NOP

好学天上 发表于 2024-8-5 18:22:57

本帖最后由 好学天上 于 2024-8-5 18:25 编辑

梁工 发表于 2024-8-5 17:51
你H和L反了,并且时间也不对。还不知道STC是单周期的?一个NOP是一个时钟。如此简单的时序:
对于12MHz, ...
<ol class="code_ol_R87" style="list-style-position: initial; list-style-image: initial; font-family: monospace; white-space: pre; background-color: rgb(240, 240, 240);"><li style="padding-left: 5px; list-style-position: initial; list-style-image: initial; border-left: 1px solid rgb(205, 205, 205) !important;"><div class="blockcode"><blockquote>void send_L(void)
{
       WS2812=1;
                        _nop_();
                        _nop_();
                        _nop_();
       WS2812=0;
                        _nop_();
                        _nop_();
                        _nop_();
        _nop_();
                        _nop_();
                        _nop_();
        _nop_();
        _nop_();
                        _nop_();
                        _nop_();
}
void send_H(void)
{
          WS2812=1;
                        _nop_();
                        _nop_();
                        _nop_();
                _nop_();
                        _nop_();
                        _nop_();
        _nop_();
                        _nop_();
                        _nop_();
        _nop_();
       WS2812=0;
                        _nop_();
                        _nop_();
                        _nop_();
}void send_one_byte(unsigned char in_data)
{
          unsigned char temp1=0;
                unsigned char temp2=0;
                unsigned char temp3=0;
                unsigned char i=0;
           temp1=in_data;
          for(i=0;i<8;i++)//八位,循环八次
                        {
                                if(temp1&0x01)
                                        send_H();
                                else
                                        send_L();
                                temp1 >>= 1;//从最低位到最高位
                        }
}

void set_one_led(unsigned char R_data,unsigned char G_data,unsigned char B_data)
{
send_one_byte(R_data);
        send_one_byte(G_data);
        send_one_byte(B_data);
}

void WS2812_Write(void)

{
      unsigned int i;
      WS2812_Reset();
      i=0;

      while(1)
      {
                if(i==LED_ON)
                {
                        set_one_led(RED,GREEN,BLUE);
                        break;

                }
                else
                {
                        set_one_led(0,0,0);
                        i++;
                }
      }
}

void Init(void)
{
            P5M0 = 0x10;
                                                P5M1 = 0x00;

}

void main(void)
{
      Init();
                                WS2812_Reset();
      while(1)
      {
                                       

//                RED=255;      //红 0~255
//                GREEN=0;      //绿 0~255
//                BLUE=0;      //蓝 0~255
          set_one_led(0,255,255);
                                        set_one_led(0,0,0);
                                        WS2812_Reset();
      }
}void WS2812_Reset(void)
{
      WS2812=0;
      Delay_x10us(10);
}这样还是不行

好学天上 发表于 2024-8-5 19:12:53

梁工 发表于 2024-8-5 17:51
你H和L反了,并且时间也不对。还不知道STC是单周期的?一个NOP是一个时钟。如此简单的时序:
对于12MHz, ...

真的想不通{:4_184:}在下愚钝

梁工 发表于 2024-8-5 22:42:03

好学天上 发表于 2024-8-5 19:12
真的想不通在下愚钝

仔细看下W2812的手册,MSB先发的哦。
示波器看下波形正常没有。
页: 1 2 3 4 5 6 7 8 9 [10] 11 12 13 14 15 16 17 18
查看完整版本: SPI-DMA输出控制WS2812三基色彩灯程序@8H系列/32G系列,不加反相器, CPU休息