原理分析

WS2812B/WS2815B均为RGB三色灯珠,WS2815B是WS2812B的升级版,区别在于两点,首先是供电电压由5V变为了12V供电,有效的降低了整个像素点的工作电流,降低线路板压降,最大限度保证像素点在很远距离传输时达到良好的混光一致性。其次是额外增加了一路信号线,在单个像素点损坏的情况下,不影响整体显示效果。

每个灯珠控制需要24位数据,8Bit绿色亮度+8Bit红色亮度+8Bit蓝色亮度,每个像素点的三基色颜色可实现256级亮度显示,完成16777216种颜色的全真色彩显示。 典型电路我们由WS2812B说起,灯带上的灯珠供电并联,信号线“串联”。信号由DI进到灯珠,灯珠在“吃掉”(锁存)24Bit数据后,将剩余数据整形放大后通过DO端口输出给下一个级联的灯珠,每经过一个灯珠的传输,信号减少24bit。当灯珠接收到280μs以上的RESET数据,灯珠根据自己锁存的数据完成对RGB三色灯的控制。24位数据采用归零码编码,Bit数据为高时,发送1码,Bit数据为低时,发送0码。

WS2815B多了一个BIN引脚,这个引脚接前一个灯珠的DI脚(灯带第一个灯珠接地)。BIN端接收到数据信号丢弃24bit数据后,再将DIN接收的数据信号与BIN断进行比较,若DIN端无信号,BIN端有接收到信号,切换到BIN端接收输入信号,这种措施可以确保在单个灯珠损坏时不至于影响到其余的灯珠,但是如果连续两个灯珠损坏,依然会导致后边的灯珠不受控制。
两种灯珠需要不同的灯板(灯珠封装不同),但是两种灯珠需要的嵌入式软件是一样的(数据的定义以及归零码的码制可以是一样的)

嵌入式代码

在嵌入式传输代码的实现上。一般都存在两种方式,一种为IO口模拟,这种方式一般见以前玩51单片机的嵌入式工程师,诸如I2C,SPI等常见的通信协议总线都习惯用IO口去模拟时序。对于WS281XB的通信协议,没有像SPI这种硬件帮我们实现的通信接口,这么看来用IO口去模拟是一个摆在桌面的实现方式。但是IO口模拟存在一个致命弱点,那就中断会打断你的时序模拟。以10个灯珠的控制为例,当你的代码正在模拟时序发到控制第10个灯还没有发的时候,中断来了,这个时候IO口正好被模拟程序控制为低,然后芯片去执行相应的中断处理程序,执行了超过280μs(RESET),执行完再回来继续发送第十个灯珠的数据,这时你会发现,你发送控制的第10个灯珠的数据其实发送给了第一个灯珠,因为两个数据之间因为中断的原因夹杂了一个RESET码。
我们采取的是SPI+DMA的方法来实现,使用芯片内部的SPI控制器去发送灯珠的控制数据,又因为我们采用的是DMA发送,能够保证中断来的时候芯片能依然准确的按照时序发送我们控制灯珠的数据。
我的实现是在STM32F10x系列的MCU,时钟的情况如下:

我使用的是SPI3,初始化代码如下:

void SPI3_Init(void)
{GPIO_InitTypeDef  GPIO_InitStructure;SPI_InitTypeDef   SPI_InitStructure;DMA_InitTypeDef DMA_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);;//初始化SPI发送IO口RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3,ENABLE);SPI_I2S_DeInit(SPI3);SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx;//SPI单线发送SPI_InitStructure.SPI_Mode = SPI_Mode_Master;SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;//发送数据宽为8BitSPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;//36/4=9M,则传输1Bit时间=111nsSPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;SPI_InitStructure.SPI_CRCPolynomial = 10;SPI_Init(SPI3, &SPI_InitStructure);SPI3->CR1 &= ((uint16_t)0xDFFF);//禁止CRC发送RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);DMA_DeInit(DMA2_Channel2);   DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&SPI3->DR;  //外设地址DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;  //DMA传输方向DMA_InitStructure.DMA_MemoryBaseAddr=(uint32_t)PixelBuffer;DMA_InitStructure.DMA_BufferSize = 0;  //需要发送的大小为0,初始不执行发送操作    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;  //外设为发送数据8bit宽DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte; //Ram存储数据8Bit宽DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;DMA_InitStructure.DMA_Priority = DMA_Priority_High ; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;  DMA_Init(DMA2_Channel2, &DMA_InitStructure);     SPI_I2S_DMACmd(SPI3,SPI_I2S_DMAReq_Tx,ENABLE); //使能SPI使用DMA通道发送SPI_Cmd(SPI3, ENABLE);//使能SPI控制器
}

当我们发送使用上述配置的SPI发送0xe0(11100000)时,SPI发送引脚高电平持续时间为111ns3=333ns,低电平时间持续的时间为111ns5=550,因为SPI为逐字节发送,用示波器量得SPI发送字节之间的间隙时间大约是100ns左右,则连续发送8字节数,则低电平持续的时间为550ns+100ns=650ns,正符合WS281xB对0码的要求。
于是,我们用发送一字节数据0xe0来模拟发送一个0码。同理可得用0xFC发送1码。用连续310个0x00来模拟发送RESET码。代码如下:

unsigned char PixelBuffer[PixelNumber*24+310] = {0};void DMA2_Star_SPI_TX()
{DMA2_Channel2->CNDTR=(PixelNumber*24+310); DMA2_Channel2->CMAR=(uint32_t)PixelBuffer; DMA_Cmd(DMA2_Channel2,ENABLE); //使能SPI3的DMA发送   while(!DMA_GetFlagStatus(DMA2_FLAG_TC2)); //循环等待发送完成,此时如果被中断打断,并不影响发送DMA_Cmd(DMA2_Channel2,DISABLE); DMA_ClearFlag(DMA2_FLAG_TC2);      return;
} void Set_All_Pixel_Color(uint8_t r, uint8_t g, uint8_t b)
{int i=0;for (i = 0; i < 64; i++)//灯带上有64个灯珠{Ws281x_Set_Pixel(Color_Show(r,g,b),i);}
}void Ws281x_Set_Pixel(uint32_t color,uint32_t position)//
{unsigned int positionin=position*3;//一个灯珠3种颜色uint8_t Red, Green, Blue; Red   = color>>16;Green = color>>8;Blue  = color;Ws281x_Set_Bits(Green,positionin);Ws281x_Set_Bits(Red,positionin+1);Ws281x_Set_Bits(Blue,positionin+2);
}void Ws281x_Set_Bits(uint8_t bits,uint32_t position)
{unsigned int positionin=0;    int zero = 0xe0; //11100000int one = 0xfC;  //11111100int i = 0x00;int j = 0x00;    positionin=position*8;//一个灯珠上的一种颜色,需要8位数表示亮度for (i = 0x80; i >= 0x01; i >>= 1){        PixelBuffer[position+j]=((bits & i) ? one : zero);j++;}
}
uint32_t Color_Show(uint8_t r, uint8_t g, uint8_t b)
{return ((uint32_t)r << 16) | ((uint32_t)g <<  8) | b;
}

下面的代码片是我们测试灯带的主函数,主要实现的是三色循环点亮。

int main(void)
{int i=0;unsigned int PixColorDa=0;uint8_t Red, Green, Blue;SPI3_Init();//初始化SPI3while(1){for(i=0;i<3;i++){PixColorDa=(0xff<<(8*i));//逐次点亮红绿蓝Blue=(PixColorDa>>16)&0xff;Green=(PixColorDa>>8)&0xff;Red=(PixColorDa)&0xff;Set_All_Pixel_Color(Red,Green,Blue);//设置灯带上所有灯的颜色为红色DMA2_Star_SPI_TX();//发送数据sleep(1);//睡眠1秒,自己实现此函数}               }
}

RGB三色灯珠WS2812B/WS2815B相关推荐

  1. ESP8266 Blinker RGB三色灯控制

    本程序通过Blinker滑动条控件控制RGB三色灯颜色,配网还是参考前面的,可手机或者app配网,也可以自己写到代码里 会三色控制了,冷暖白双色就类似了,取两个变量就可以了. 简单粗暴,代码如下: / ...

  2. FPGA驱动RGB灯带WS2812B

    记录一下短学期做的东西 -- FPGA驱动RGB灯带WS2812B 设计目标 1.有多种模式,按键调节模式等参数: 2.模式1:红绿蓝白四色循环显示,速度.亮度可调: 3.模式2:7彩虹+白色,闪烁, ...

  3. 基于RT_Thread连接中国移动onenet平台的RGB三色灯项目

    一.简介 1.RT_Thread简介 RT-Thread是一个集实时操作系统(RTOS)内核.中间件组件和开发者社区于一体的技术平台,由熊谱翔先生带领并集合开源社区力量开发而成,RT-Thread也是 ...

  4. 进阶之路(中级篇) - 015 串口控RGB三色灯

    本文由博主原创,如有不对之处请指明,转载请说明出处. 1 /********************************* 2 代码功能:串口控RGB三色灯 3 使用函数: 4 Serial.fl ...

  5. 【CC2530授课笔记】⑧ PWM实现呼吸灯,RGB三色灯,蜂鸣器播放音乐

    摘要 这篇文章通过定时器产生PWM波,控制LED实现呼吸灯的效果,并且通过三路PWM分别控制RGB三色灯,实现了颜色渐变.最后通过调制PWM频率,使用蜂鸣器实现了音乐播放. PWM简介 Pulse W ...

  6. Arduino——RGB三色灯

    我是基于arduino UNO R3套件来实现的RGB三色灯案例.在这整套的套件中,备有RGB三色灯集成器件. 关于RGB三色灯的电路原理,各位直接在网上就可以搜索到,这里就不过多赘述.接下来就是关于 ...

  7. 基于ESP8266网页控制RGB三色灯的颜色

    基于ESP8266网页控制RGB三色灯的颜色 首先让我们来了解一下的RGB三色灯的原理,RGB有四个引脚,最短的引脚接地,另外三个引脚接高电平,依次是亮红色,绿色,蓝色,这是三种最基本的配色,然而我们 ...

  8. 树莓派26/100 - Pico控制RGB三色灯

    RGB三色LED灯,相当于把三种颜色的LED灯组合在一起,它有4条腿,最长的那条腿是阴极或阳极,根据这个灯是共阴的,还是共阳的而定. 与以前接LED灯的情况类似,不过这次要接三个电阻,我把它们分别接到 ...

  9. 使用f031的SPI单引脚(MOSI)+DMA实现WS2812B三色灯的级联控制

    WS2812B是一种集成了电流控制芯片的低功耗的RGB三色灯, 关于这个灯的一些硬件分析我就不多说,百度一堆一堆的: 今天主要讲讲使用SPI的MOSI+DMA实现控制的方式: 主MCU:灵动微的 MM ...

  10. Arduino控制RGB灯(WS2812B)

    Arduino控制RGB灯 RGB灯.WS2812B介绍 软件准备 程序代码 功能演示 后续 RGB灯.WS2812B介绍 RGB灯是以三原色共同交集成像,此外,也有蓝光LED配合黄色荧光 粉,以及紫 ...

最新文章

  1. iOS 8 UITableView分隔符插入0不起作用
  2. ambari初始化登陆账号/密码假如不是admin/admin
  3. Android中用 adb 命令操作数据库
  4. 今日问题:操作必须使用一个可更新的查询。
  5. Libra教程之:Libra协议的关键概念
  6. 远控免杀专题11-Avoidz免杀
  7. 项目分层思路——管家婆
  8. python在input输入数字为何是str_Python基础笔记:input()输入与数据类型转换
  9. php有没有ispostback,php用什么表示IsPostBack?
  10. DOS批处理命令之for命令(批量安装APK)
  11. 18位身份证校验代码
  12. iPhoneSE3定价或跌穿3K,苹果不给安卓手机活路了?
  13. 史上最全的贝塞尔曲线(Bezier)全解(三):贝塞尔曲线实现满屏爱心
  14. 简单socket聊天小程序+socket简单封装
  15. Excel:如何批量将文本数字转为数值型数据
  16. mysql-5.7.27-winx64 安装教程
  17. hbase基于solr配置二级索引
  18. 相较国外代码托管平台 gitlab,咱们中国自己的代码托管平台有哪些优势?
  19. win7 关闭java自动更新
  20. 人生低谷一日感悟+收获

热门文章

  1. NXP:I2C总线技术规范和用户手册(中文版)(一)
  2. 绿竹生物冲刺港股:年期内亏损超5亿 泰格医药与北京亦庄是股东
  3. eclipse如何设置眼睛保护色
  4. python自动交易app_股票自动交易Python下单接口
  5. python清理浏览器缓存_浏览器缓存看这一篇就够了
  6. 不懂什么是锁?看看这篇你就明白了
  7. JAVA电影购票系统
  8. 信道检测手机软件 ios_wifi分析仪如何检测周围wifi信号 wifi分析仪使用方法【详解】...
  9. sql注入工具、检测及手工注入集合
  10. 键盘指示灯亮着 按键全部失效了怎么办