ws2812

WS2812驱动

时序

释义 时间
T0H 0码,高电平时间 400±150ns
T0H 1码,高电平时间 850±150ns
T0L 0码,低电平时间 850±150ns
T0L 1码,低电平时间 400±150ns
RES 复位低电平时间 >50us

配置

定时器

  • PWM通道
  • ARR = 时钟频率 * 1.2
  • 其余默认(0分频,向上计数,PWM1…)

DMA配置

  • DMA中断默认开启,时钟中断不需要开
  • 添加DMA,对应定时器和通道,Memory to Peripheral,Very High,
    Mode Normal,Increment Memory,Data Width Per=Half word,Mem = Word

控制代码

1.简单效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
#define LED_NUM	100
static uint32_t Led[LED_NUM];


LEDFUN Ledfun = STREAM_Y;

void Led_Func(LEDFUN sel)
{

uint32_t G = 0xff<<16;
uint32_t R = 0xff<<8;
uint32_t B = 0xff;
uint8_t i,temp;
static uint8_t cnt;
static uint8_t timecnt;
static uint32_t tick = 0;


if (++timecnt > 100)
timecnt = 0;
if (++cnt >LED_NUM*2)
cnt = 0;

for(i = 0;i < LED_NUM;i++)
{
Led[i] = 0;
}
switch (sel)
{
//OFF
case 0:

break;

//breath;
//----------------------------------------------------------
case BREATH_G:
for(i = 0;i < LED_NUM;i++)
{
if (timecnt<50)
Led[i] = (1<<16)*5*timecnt;
else
Led[i] = (1<<16)*5*(100-timecnt);
}
break;

case BREATH_R:
for(i = 0;i < LED_NUM;i++)
{
if (timecnt<50)
Led[i] = (1<<8)*5*timecnt;
else
Led[i] = (1<<8)*5*(100-timecnt);

}
break;

case BREATH_B:
for(i = 0;i < LED_NUM;i++)
{
if (timecnt<50)
Led[i] = 5*timecnt;
else
Led[i] = 5*(100-timecnt);
}
break;
case BREATH_Y:
for(i = 0;i < LED_NUM;i++)
{
if (timecnt<50)
Led[i] = (1<<16|1<<8)*5*timecnt;
else
Led[i] = (1<<16|1<<8)*5*(100-timecnt);
}
break;
case BREATH_GY:
for(i = 0;i < LED_NUM;i++)
{
if (timecnt<50)
Led[i] = (1|1<<8)*5*timecnt;
else
Led[i] = (1|1<<8)*5*(100-timecnt);
}
break;

case BREATH_D:
for(i = 0;i < LED_NUM;i++)
{
if (timecnt<50)
Led[i] = (5|3<<8)*timecnt;
else
Led[i] = (5|3<<8)*(100-timecnt);
}
break;
//flicker
//----------------------------------------------------------
case FLICKER_G:
for(i = 0;i < LED_NUM;i++)
{
if (timecnt%50 > 25)
Led[i] = G;
else
Led[i] = 0;
}
break;

case FLICKER_R:
for(i = 0;i < LED_NUM;i++)
{
if (timecnt%50 > 25)
Led[i] = R;
else
Led[i] = 0;

}
break;

case FLICKER_B:
for(i = 0;i < LED_NUM;i++)
{
if (timecnt%50 > 25)
Led[i] = B;
else
Led[i] = 0;

}
break;
case FLICKER_Y:
for(i = 0;i < LED_NUM;i++)
{
if (timecnt%50 > 25)
Led[i] = 0xffff00;
else
Led[i] = 0;

}
break;
case FLICKER_GY:
for(i = 0;i < LED_NUM;i++)
{
if (timecnt%50 > 25)
Led[i] = 0xffff;
else
Led[i] = 0;

}
break;
//stream
//----------------------------------------------------------

case STREAM_G:
for (i = 0;i < 16;i++)
{
Led[(i + cnt/2)%LED_NUM] = (i<<16)*16;
}
break;

case STREAM_R:
for (i = 0;i < 16;i++)
{
Led[(i + cnt/2)%LED_NUM] = (i<<8)*16;
}
break;

case STREAM_B:
for (i = 0;i < 16;i++)
{
Led[(i + cnt/2)%LED_NUM] = i*16;
}
break;
case STREAM_Y:
for (i = 0;i < 16;i++)
{
Led[(i + cnt/2)%LED_NUM] = (i|i<<8 )*16;
}
break;
//----------------------------------------------------------
case RAINBOW:
temp = LED_NUM/7;
for (i = 0; i < temp;i++)
{
Led[i+temp*0] = R;
Led[i+temp*1] = 0x85ff00;
Led[i+temp*2] = 0xffff00;
Led[i+temp*3] = G;
Led[i+temp*4] = 0xfc5c00;
Led[i+temp*5] = B;
Led[i+temp*6] = 0x0094d3;
}
break;
}
}

2.驱动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include "tim.h"
typedef struct
{
const uint32_t head[2];
uint32_t data[LED_NUM*24];
const uint32_t tail;
}DMA_Buffer;

DMA_Buffer P_Buffer=
{
.head[0] = 0,
.head[1] = 0,
.tail = 0,
};

void Led_Show(void)
{
uint16_t i,j;
static uint32_t tick = 0;
static uint32_t test_cnt = 0;

if (HAL_GetTick() - tick > 40)//调用频率
{
tick = HAL_GetTick();
}
else
{
return;
}
//----------------------------------------
//测试
if (++test_cnt > 200)
{
test_cnt = 0;
Ledfun++;
if (Ledfun == RAINBOW+1)
{
Ledfun =BREATH_G;
}
}
//----------------------------------------
Led_Func(Ledfun);
for (i = 0; i < LED_NUM;i++)
{
for (j = 0;j < 24;j++)
P_Buffer.data[24*i+j] = (Led[i] & (1 << (23-j)))? 40:20;//71:34;//根据实际修改
}
HAL_TIM_PWM_Start_DMA(&htim4, TIM_CHANNEL_1, (uint32_t *)&P_Buffer, 2 + LED_NUM * 24 + 1);
}
//中断回调
void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
{
HAL_TIM_PWM_Stop(&htim4,TIM_CHANNEL_1);
}

-->

请我喝杯咖啡吧~

支付宝
微信