本帖最后由 anny 于 2017-6-14 13:07 编辑 & d) I6 d; I& ^ 其实社区有朋友发帖子用STM32驱动WS2811灯带了,他们用的是硬件SPI,其实也可以用PWM。 今天我的驱动方式不是用单片机外设来驱动,而是用最古老的延时方式,这种方式不适合地方你们自己想了,优点是灵活,想在哪个IO口驱动随便换。3 y& v/ v# C7 z: G. i2 j- X 还有,我这个驱动方式可以兼容UCS1903、SM16703等等这些灯带。 驱动芯片:STM32F103RBT6 频率:72M 说明:为了保护单片机我用了块74HC245来隔离,也算是做了电压转换,从3.3V变成了5V 好吧,上程序:2 n2 m8 Y( r- T0 Y1 m0 j, U5 K void WS2811_SendByte(u8 dat)//发送1BIT的数据% Z5 O5 f5 t; \8 u4 q { u8 i; for(i=0;i<8;i++) { if(dat & 0x80) //发送数据1" K# M: H7 ?0 u( w w# X' e' p {' R( j$ i. h* O6 Z# d) ]0 ? Light_SDA=1;. b I& q8 _. e- @3 t" E2 j delay_us(1); Light_SDA=0;3 s. E1 y4 C+ T. [ __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop(); }% o) s" T" R- | else //发送数据0 { Light_SDA=1;//0 __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop(); Light_SDA=0; delay_us(1); }7 y5 A, y) X3 r& ?* P; \- ] dat <<= 1; }( X+ d: Z. `! h" d } void Reset(void) { ) ^% N. i8 l$ {+ V$ W Light_SDA=0; delay_ms(30); }8 q4 d6 v, p9 W/ a$ r 基本的发数据程序就这样了; }% N9 S! F. u6 ]$ q U void send_data(u8 R,u8 G,u8 B) {5 O# X& _( c1 t, a u8 i;! k6 j0 K2 E9 A$ X for(i=0;i<led_size;i++)) I- {- ~( J3 S { WS2811_SendByte(G);# `" @ S! I5 M M1 A& W2 L WS2811_SendByte(R); ~" L$ q! P) R0 w! @6 r& A. B WS2811_SendByte(B);- i( P% Y0 P: f! Q }, J& z& \( r' r, B Reset(); }. N! j; H! {9 F7 W3 o4 x1 |* m void ls_mode(void)5 H, b* m9 y6 s0 i* i {" B" |8 g8 ]- Z- `+ j% T- v u8 i=0,ys=0,yz=0;( f. h* g$ L% Y& u8 `, |5 H for(i=led_size;i>0;i--) { if(i<=ls_t)' W' q, U9 \% {; Y9 Y" L& ^( J { if(ys<ls_t)% P' ^6 P! V. t( } { ys++; } else% y0 ~8 Z f" x ` ys=0; WS2811_SendByte(LED_data[45-(ys%45)][1]); WS2811_SendByte(LED_data[45-(ys%45)][0]); WS2811_SendByte(LED_data[45-(ys%45)][2]); }% X7 y' f' k- W else8 g v. w! X: L- z9 y { if(yz>0)* [: H* o- i! z { yz--;4 ?7 S# u3 i! o% m/ l% r: _* e4 l' O }, _8 l) C$ Q0 z else yz=led_size-ls_t;* a- _/ e, |* Z WS2811_SendByte(LED_data[yz%45][1]); WS2811_SendByte(LED_data[yz%45][0]); WS2811_SendByte(LED_data[yz%45][2]); }: P: W$ `1 p! T# b) m7 w }( T! k1 Y4 F( h# |: k y6 ~" v5 { Reset();8 i3 |- D8 j- [1 x/ T } 4 f% U# D/ ~+ N2 x, i 这是应用程序,其实就是PLAY一个数组,我刚刚开始的方法是完全用FOR来实现,发现哪样做每种流水方式都要重新写,太痛苦了。PLAY数组里面的内容相对会方便很多,当然也可以在函数名上加指针用来实现PLAY哪个数组,这个就自行改善吧! const u8 LED_data[45][3]={8 i; Z. ?4 V. a- N# F {55,0,255},//G,R,B {100,0,200},. w) Q* v9 N4 c5 z {155,0,155}, {200,0,100},2 i% ?. b8 a& n {255,0,55},//55 ~) \) `1 [1 h: q) `/ y+ s2 y# s {255,0,0}, {255,0,0}, {255,0,0}, {255,0,0},; U" E! u7 P4 E A: x {255,0,0},9 U; `8 k( ~/ j4 T6 @* R2 E {255,0,0}, {255,0,0},& h+ ?$ g6 A: b+ j. C9 } {255,0,0}, {255,0,0},( B6 d& n4 `; s4 ]7 K; e- s4 ~% A {255,0,0},//15 {255,55,0},7 m% z7 W" e5 n3 l {200,100,0}, {155,155,0}, {100,200,0}, {55,255,0},//20/ ^* F' k# C7 `0 }' I3 i9 n {0,255,0},//G,R,B {0,255,0}, {0,255,0},2 |, D3 z0 D! k) z+ d {0,255,0}, {0,255,0},0 L- c% r6 G: f: j3 S* a, u {0,255,0},. X1 j. h4 v1 Y7 H {0,255,0},4 Z9 s7 @$ L- V2 X/ \ {0,255,0},1 _2 [4 M2 k, V- | {0,255,0},5 |/ T6 m6 ~* |/ _; B" k {0,255,0},//30 {0,255,55},//G,R,B6 F% R/ }" ?; U- l0 m {0,200,100}, {0,155,155},( r! p" S# I h0 | {0,100,200},5 p6 s {* ^% Z2 Z% } {0,55,255},0 Y1 J" N' R3 r8 y. k5 b {0,0,255},//35" _8 e8 h+ V7 b; h, t' ]3 ?* Y9 I {0,0,255}, {0,0,255}, {0,0,255},6 H$ z- v" D! S$ v& Y6 ? {0,0,255}, {0,0,255}, {0,0,255}, {0,0,255},1 I8 h, F( Q) y1 z h* {' T {0,0,255},' G: s) {% [- g {0,0,255}//45 };' s* }# n- F- r2 j! H9 N0 S 6 {, h X4 E1 @, U$ b1 ^ 这是要PLAY的数组,这次实现的是流水灯,在颜色链接的地方加上了渐变,这样更好看。当然也可以换上其它的方式9 Q% @- F+ b( S" f 单单上面的程序流水灯是流不起来的,在定时中断用变量++来驱动: void TIM2_IRQHandler(void) // 1s enter {8 D; B2 N ?1 G9 W% _7 B& E if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET) { // ls_mode12();( n: P. D" g' h3 [% Y9 z8 H' A if(++t2>=ls_speed)) y3 v S8 L4 i" L0 e {# q% T1 e1 g; ^7 |' Z t2=0; if(++ls_t>=led_size) //注意!!( S1 d T: R. g6 R( H- V1 o# u- O { ls_t=0; }' f0 ]6 n+ c, f }, c& e8 P( g7 c TIM_ClearITPendingBit(TIM2, TIM_IT_CC1 ); } : \# r _% J0 Z9 T; B/ m* a7 K }8 b* \" {* x+ G' | & l+ v3 K# ]9 L+ ~; }' A0 | 这样在main函数调用ls_mode()灯就流起来了!!% m" U6 b: y, x% s6 s 漂亮的东西怎么没有视频:; b0 ]# h/ n) d- `1 C, s 6 O6 v4 j l9 ]( x# n# n) |% O |
参与人数 4 | ST金币 +11 | 收起 理由 |
---|---|---|
勿忘初心ºº¹ | + 1 | 赞一个! |
pythonworld | + 2 | 很给力! |
shaoziyang | + 5 | 很给力! |
MrJiu | + 3 | 赞一个! |
思路就是用MOSI脚驱动,然后直接发送数据,用逻辑分析仪看高低电平的时间,然后做调整,比如发SPI发送0xE0,其实就是发送了3个1,5个0,这样低电平的时间就肯定长,然后自己看着来调整就行了。
请问您这边有思路吗,我也是想只使用定时器的PWM实现,补寄有的单片机没有DMA控制器7 u6 k- }" n) Q
是72M的