赞
踩
● 智能反接保护,电源反接不会损坏IC。
● IC控制电路与LED点光源公用一个电源。
● 控制电路与RGB芯片集成在一个5050封装的元器件中,构成一个完整的外控像素点。
● 内置信号整形电路,任何一个像素点收到信号后经过波形整形再输出,保证线路波形畸变不会累加。
● 内置上电复位和掉电复位电路。
● 每个像素点的三基色颜色可实现256级亮度显示,完成16777216种颜色的全真色彩显示,扫描频率不低于
400Hz/s。
● 串行级联接口,能通过一根信号线完成数据的接收与解码。
● 任意两点传传输距离在不超过5米时无需增加任何电路。
● 当刷新速率30帧/秒时,级联数不小于1024点。
● 数据发送速度可达800Kbps。
这个信号是一帧数据传输完成的标志。当你完成对灯珠的写入,需要给灯珠一个帧单位信号,灯珠才会按写入的数据亮灯,否则,灯珠只会按上一回写入的数据亮灯。(可以理解为输出更新)。
在WS2812b中,零码的占空比为30%,一码的占空比为60%
使用TIM2输出比较通道1,GPIOA_Pin0
● 初始化DMA,TIM,GPIO外设
● 将PWM输出GPIO设为复用推挽输出
● 将TIM时基单元的时钟来源设为内部时钟(72M),预分频器(PSC)设为1-1,自动重装器(ARR)设为90-1。
800k=72M/90
● 开启输出比较寄存器(CRR)的影子寄存器,开启DMA请求。
解决办法:把第一个灯单独再灭一次(给第一个灯写入:0x000000)
#define Led_Num 30//灯珠数量
uint16_t WS2812_Value[24*Led_Num];//WS2812b数据存储区
void WS2812_rest()
{
TIM_Cmd(TIM2,DISABLE);//关闭PWM输出
GPIO_ResetBits(GPIOA,GPIO_Pin_0);//拉低DIN
Delay_ms(1);//等待一毫秒
}
void WS2812_Clear()
{
uint16_t i=0;
for(i=0;i<(24*Led_Num);i++)//Led_Num是灯珠数量
{
WS2812_Value[i]=30;//把占空比数据设为零码
}
}
Num:要传输的灯珠数据的数量
void WS2812_Show(uint8_t Num)
{
WS2812_rest();//WS2812b发送帧单位信号
DMA_SetCurrDataCounter(DMA1_Channel5, 24*(Num+1));//(设置待转移数据个数为(24*Num+1)
DMA_Cmd(DMA1_Channel5, ENABLE);//开启DMA转运
TIM_Cmd(TIM2, ENABLE);//开启TIM2
while (DMA_GetFlagStatus(DMA1_FLAG_TC5) != SET);//等待ws2812b数据传输完成
DMA_ClearFlag(DMA1_FLAG_TC5);//清除DMA转运完成标志位
DMA_Cmd(DMA1_Channel5, DISABLE);//关闭DMA转运
TIM_Cmd(TIM2, DISABLE);//关闭TIM2
WS2812_rest();//WS2812b发送帧单位信号(更新显示)
}
void WS2812_Init() { /*开启RCC时钟*/ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE); /*配置GPIO*/ GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure);//将GPIOA_Pin0配置为复用推挽输出 /*TIM2配置时基单元*/ TIM_InternalClockConfig(TIM2);//TIM2时钟来源设为内部时钟 TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;//时钟分频,不分频 TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//计数器模式,向上计数模式 TIM_TimeBaseInitStructure.TIM_Period = 90 - 1; //设为自动重装寄存器(ARR)的值为90 TIM_TimeBaseInitStructure.TIM_Prescaler = 1 - 1; //设为预分频器(PSC)的值为1 TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//没用 TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure); /*配置TIM2输出比较通道一*/ TIM_OCInitTypeDef TIM_OCInitStructure; TIM_OCStructInit(&TIM_OCInitStructure);//先把不需要的参数填入缺省值 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//输出比较模式,PWM模式1 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//有效电平为高电平 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//输出使能,使能 TIM_OCInitStructure.TIM_Pulse = 60; //这里设置输出比较寄存器(CRR)的值无所谓 TIM_OC1Init(TIM2, &TIM_OCInitStructure);//配置输出比较通道一 TIM_DMACmd(TIM2, TIM_DMA_CC1, ENABLE);//输出比较通道一DMA请求开启 TIM_OC1PreloadConfig(TIM2,TIM_OCPreload_Enable);//使用输出比较寄存器(CRR)的影子寄存器 TIM_CtrlPWMOutputs(TIM2, ENABLE);//高级定时器才有用 /*配置DMA1*/ DMA_InitTypeDef DMA_InitStructure; DMA_InitStructure.DMA_PeripheralBaseAddr=(uint32_t)&(TIM2->CCR1);//设置&(TIM2->CCR1)为外设基地址 DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_HalfWord;//外设站点的数据宽度为16bits DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable;//外设站点的地址不自增 DMA_InitStructure.DMA_MemoryBaseAddr=(uint32_t)WS2812_Value;//设置WS2812_Value为存储器基地址 DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_HalfWord;//存储器站点的数据宽度为16bits DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable;//存储器站点的地址自增 DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralDST;//将外设站点设为传输目的地 DMA_InitStructure.DMA_BufferSize=24;//没用,填什么无所谓 DMA_InitStructure.DMA_Mode=DMA_Mode_Normal;//不使用自动重装 DMA_InitStructure.DMA_M2M=DMA_M2M_Disable;//使用硬件触发 DMA_InitStructure.DMA_Priority=DMA_Priority_Medium;//优先级中等 DMA_Init(DMA1_Channel5,&DMA_InitStructure);//初始化DMA1通道5使用DMA_Init初始化。 DMA_Cmd(DMA1_Channel5,DISABLE);//先不使能DMA,需要时再使能 TIM_Cmd(TIM2, DISABLE);//先不使能TIM2,需要时再使能 /*WS2812灯带清零*/ DMA_SetCurrDataCounter(DMA1_Channel5, (24*Led_Num));//设置待转移数据个数为(24*灯珠个数) WS2812_Clear();//WS2812b数据清零 WS2812_rest();//WS2812b发送帧单位信号 DMA_Cmd(DMA1_Channel5,ENABLE);//开启DMA转运 TIM_Cmd(TIM2, ENABLE);//开启TIM2 while(DMA_GetFlagStatus(DMA1_FLAG_TC5)!= SET);//等待ws2812b数据传输完成 DMA_Cmd(DMA1_Channel5,DISABLE);//关闭DMA转运 DMA_ClearFlag(DMA1_FLAG_TC5);//清除DMA转运完成标志位 TIM_Cmd(TIM2, DISABLE);//关闭TIM2 WS2812_rest();//WS2812b发送帧单位信号 /*解决绿灯问题*/ DMA_SetCurrDataCounter(DMA1_Channel5, 24);/设置待转移数据个数为(24*1) WS2812_Clear();//WS2812b数据清零 WS2812_rest();//WS2812b发送帧单位信号 DMA_Cmd(DMA1_Channel5,ENABLE);//开启DMA转运 TIM_Cmd(TIM2, ENABLE);//开启TIM2 while(DMA_GetFlagStatus(DMA1_FLAG_TC5)!= SET);//等待ws2812b数据传输完成 DMA_Cmd(DMA1_Channel5,DISABLE);//关闭DMA转运 DMA_ClearFlag(DMA1_FLAG_TC5);//清除DMA转运完成标志位 TIM_Cmd(TIM2, DISABLE);//关闭TIM2 WS2812_rest();//WS2812b发送帧单位信号 }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。