首页 > 编程知识 正文

RGB三色灯珠接线,RGB三色灯珠混色后偏蓝是什么原因

时间:2023-05-03 13:10:18 阅读:181500 作者:4067

原理分析WS2812B/WS2815B都是RGB三色灯泡,WS2815B是WS2812B的升级版。 不同之处在于,首先电源电压从5V变为12V,有效降低了整个像素点的工作电流,降低了线路板的压降,使像素点在远距离传输时达到良好的混光一致性。 接下来,添加了信号线,以便当一个像素点损坏时,不影响整体显示效果。

每个光控需要24位数据、8Bit绿色亮度、8Bit红色亮度、8Bit蓝色亮度,每个像素点的三原色颜色可以进行256级亮度显示,完成16777216色的全色显示。 典型的电路从WS2812B开始,将灯带的灯珠供电并联连接,将信号线连接为“串联”。 信号从DI进入灯珠,灯珠“吃掉”了24位的数据(锁存后,将剩下的数据整形放大后,通过DO端口输出到下一个级联的灯珠,经过灯珠的传输,信号减少24位。 当灯珠接收到280s以上的RESET数据时,灯珠根据自己锁存的数据完成对RGB三色灯的控制。 24位数据用归零码进行编码,位数据为高时发送1代码,位数据为低时发送0代码。 WS2815B增加了一个清新的灯针,连接到上一个灯珠的DI脚。 (灯带的第一个灯珠接地。 在新鲜灯泡接收到数据信号并舍弃了24比特的数据后,将DIN接收到的数据信号与新鲜灯泡的断开进行比较,如果DIN侧没有信号,则由于新鲜灯泡侧具有接收信号,切换到新鲜灯泡侧来接收输入信号,导致一个灯泡损坏

两种灯珠需要不同的灯盘。 (灯珠的包装不同。 但是,两种灯珠所需的嵌入式软件相同) )数据定义和归零码的编码可以相同)。

嵌入式代码位于嵌入式传输代码的实现中。 一般存在两种方式,一种是IO端口仿真,这种方式是以前玩51单片机的嵌入式工程师,如I2C、SPI等常见的通信协议总线在IO端口上仿真时序关于WS281XB的通信协议,没有像SPI那样的硬件能够实现的通信接口,这样想来,通过IO端口进行仿真是摆在桌面上的实现方式。 但是,IO端口模拟存在致命的弱点,中断会中断计时模拟。 以控制10盏灯为例,jsdbd的代码在模拟时间还没有发送来控制第10盏灯时就中断了。 此时,IO端口正好由仿真程序控制在较低水平,芯片运行相应的中断处理程序,运行280s(reset )以上,运行后返回继续发送第10个灯光的数据。 此时,您将看到发送控制的第10盏灯的数据

我们用SPI DMA的方法实现,使用芯片内部的SPI控制器发送灯珠的控制数据。 另外,由于采用了DMA发送,所以即使有中断,也能够保证芯片能够准确地按时发送灯珠的控制数据。

我的实现是STM32F10x系列的MCU,时钟的状况如下。

我在使用SPI3。 初始化代码如下所示。

voidSPI3_init(void ) gpio _ inittypedefgpio _ init structure; SPI _ inittypedefspi _ init structure; DMA _ inittypedefdma _ init structure; RCC _ AP B2 periphclockcmd (RCC _ AP B2 per iph _ gpiob,ENABLE ); gpio _ pinremapconfig (gpio _ remap _ swj _ JTAG disable,ENABLE ); gpio _ init structure.gpio _ pin=gpio _ pin _ 5; gpio _ init structure.gpio _ mode=gpio _ mode _ af _ PP; gpio _ init structure.gpio _ speed=gpio _ speed _ 50m Hz; gpio_init(gpiob,GPIO_InitStructure ); //初始化SPI发送IO端口RCC _ AP B1 periphclockcmd (RCC _ AP B1 per iph _ SPI 3,ENABLE ); SPI_I2s_deinit(SPI3; SPI _ init structure.SPI _ direction=SPI _ direction _1line _ tx; //SPI单线连接SPI _ init structure.SPI _ mode=SPI _ mode _ master; SPI _ init structure.SPI _ datasize=SPI _ datasize _ 8b; //发送数据宽度为8bit SPI _ init structure.SPI _ cpol=SPI _ cpol _ low; SPI _ init structure.SPI _ cpha=SPI _ cpha _2edge; SPI _ init structure.SPI _ NSS=SPI _ NSS _ soft; SPI _ init structure.SPI _ baudrate prescaler=SPI _ baudrate prescaler _ 4; //36/4=9M时,传输1比特时间=111 NSS pi _ init structure.SPI _ first bit=SPI _ first bit _ msb; SPI _ init structure.SPI _ CRC polynomial=

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; //11111100 int 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秒,自己实现此函数}}}

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。