WS2811 使用时需要注意的东西:
1.发送0 1时的高低点平时间,建议使用逻辑分析仪或示波器进行波形查看,精准时间大小。
2.WS281特性为发送数据后保存数据信息,若灯不更换其他颜色,请勿输入数据。
3.注意代码使用过程的规范。精准定位问题出现原因
此处只给出了WS2811的驱动代码。
整个工程请转至我的个人github:https:///lengmudemao/WS2811
WS2811.h
#ifndef _WS2811_H
#define _WS2811_H
#include "sys.h"
#define WS2811_CONTROL PAout(0)
#define HIGH 1
#define SEND_TIMES 20
#define LIGHT_TIME 500 单位:秒
//控制函数声明/
void WS2811_Init(void);
void TIM3_Int_Init(u16 arr,u16 psc);
void l_dat0(void);
void l_dat1(void);
void Reset(void);
void send_single_data(const u8 *data);
void send_string_data(const u8 *data,u8 size);
void RGB_open(const u8 *data);
void RGB_Lighting(void);
void RGB_ALARM(void);
/
#endif
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
WS2811.c
#include "WS2811.h"
static void delay(unsigned long int us);
static u8 Gard[3]={0}; // BLUE RED GREEN
static u16 TIM3_count=0;
static u8 Light_blue=0;
static u8 Light_red=0;
static u8 Light_green=0;
//==================================WS2811初始化======================================//
void WS2811_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//使能GPIOA时钟
//GPIOA0初始化设置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;//下拉拉
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化
Reset();
TIM3_Int_Init(1000,84); //TIM3 1KHZ
}
//==================================通用定时器3初始化================================//
//arr:自动重装值sc:时钟预分频数 定时器溢出时间计算方法:Tout=((arr+1)*(psc+1))/Ft us.
void TIM3_Int_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); ///使能TIM3时钟
TIM_TimeBaseInitStructure.TIM_Period = arr; //自动重装载值
TIM_TimeBaseInitStructure.TIM_Prescaler=psc; //定时器分频
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);//初始化TIM3
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE); //允许定时器3更新中断
TIM_Cmd(TIM3,ENABLE); //使能定时器3
NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn; //定时器3中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x01; //抢占优先级1
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x03; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
//定时器3中断服务函数
void TIM3_IRQHandler(void)
{
if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET){ //溢出中断
TIM3_count++;
if((TIM3_count%(LIGHT_TIME*3))==0){
Light_blue=1;
Light_red=0;
Light_green=0;
}
else if((TIM3_count%(LIGHT_TIME*3))==(LIGHT_TIME*1)){
Light_blue=0;
Light_red=1;
Light_green=0;
}
else if((TIM3_count%(LIGHT_TIME*3))==(LIGHT_TIME*2)){
Light_blue=0;
Light_red=0;
Light_green=1;
}
else if(TIM3_count>(LIGHT_TIME*3))
TIM3_count=0;
}
TIM_ClearITPendingBit(TIM3,TIM_IT_Update); //清除中断标志位
}
//===============高速编码模式BIT0(高电平时间:0.5us 低电平时间:2us )===============//
void l_dat0(void)
{
WS2811_CONTROL|=HIGH;
delay(3);
WS2811_CONTROL&=~HIGH;
delay(15);
}
//===============高速编码模式BIT1(高电平时间:5us 低电平时间:0.5us)================//
void l_dat1(void)
{
WS2811_CONTROL|=HIGH;
delay(16);
WS2811_CONTROL&=~HIGH;
delay(2);
}
//===================================RGB复位====================================//
void Reset(void)
{
WS2811_CONTROL&=~HIGH;
delay(2000);
}
//============================发送RGB灰度数据===================================//
void send_single_data(const u8 *data) //数据格式:R7~R0~G7~G0~B7~B0
{
s8 i=0,j=0;
for(i = 0; i < 3; i++){
for(j = 7; j > -1; j--){
if((*(data+i)&(HIGH<<j))==(HIGH<<j))
l_dat1();
else
l_dat0();
}
}
}
void send_string_data(const u8 *data,u8 size)
{
u8 i=0;
for(i=0;i<size;i++){
send_single_data(data);
}
Reset();
}
//==================================RGB常亮=====================================//
void RGB_open(const u8 *data) //RGB常亮
{
send_single_data(data);
}
//=================================RGB闪烁========= BLUE RED GREEN ===============//
void RGB_Lighting(void)
{
if(Light_blue){
Gard[0]=255;
Gard[1]=0;
Gard[2]=0;
send_string_data(Gard,SEND_TIMES); //发送次数与灯管长度有关
Light_blue=0;
}
else if(Light_red){
Gard[0]=0;
Gard[1]=255;
Gard[2]=0;
send_string_data(Gard,SEND_TIMES);
Light_red=0;
}
else if(Light_green){
Gard[0]=0;
Gard[1]=0;
Gard[2]=255;
send_string_data(Gard,SEND_TIMES);
Light_green=0;
}
}
//=================================延时========= BLUE RED GREEN ===============//
static void delay(unsigned long int us)
{
unsigned long int j;
for (j = 5*us; j> 0; j--) ;
}