
本帖最后由 anny 于 2017-6-14 13:07 编辑 ( b- s( i1 R1 f L6 a* V% v- F1 V 其实社区有朋友发帖子用STM32驱动WS2811灯带了,他们用的是硬件SPI,其实也可以用PWM。% Z3 ]1 W4 b$ [$ M2 F 今天我的驱动方式不是用单片机外设来驱动,而是用最古老的延时方式,这种方式不适合地方你们自己想了 ![]() 还有,我这个驱动方式可以兼容UCS1903、SM16703等等这些灯带。1 m, t& V% \0 }/ g 驱动芯片:STM32F103RBT6 频率:72M 说明:为了保护单片机我用了块74HC245来隔离,也算是做了电压转换,从3.3V变成了5V+ u0 `) W+ q+ H& q: V" D: c/ v 好吧,上程序: void WS2811_SendByte(u8 dat)//发送1BIT的数据 {% x; s% A \; Y: u. N i u8 i; for(i=0;i<8;i++) {% L/ x% X+ Y( {+ B5 J, `6 N8 D+ c2 W# ] if(dat & 0x80) //发送数据1 {; \# L x5 j+ Z$ ?' z4 S Light_SDA=1;& L! q0 p3 v2 w delay_us(1);7 g# p ?( l% d Light_SDA=0;" ?, K! z% E- v6 [5 ~0 C __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop(); }9 T9 k; D! t* l& x0 V" V else //发送数据0. U( ?" p& r- i+ b { Light_SDA=1;//08 y8 k. E$ X! s2 \, H3 W' W! e __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();; H3 @ v6 Z% N5 J$ I9 L; L Light_SDA=0; delay_us(1);: g/ C2 @; X6 L; Z5 h } dat <<= 1; } }! i* R. d2 ~3 e# | void Reset(void) 3 \4 o6 _2 i( F { % G( V) i9 I5 j7 D Light_SDA=0; delay_ms(30); } ; x5 W0 K! a: S' s/ h5 b 基本的发数据程序就这样了 void send_data(u8 R,u8 G,u8 B)+ e; M/ ?7 y/ o. n9 [6 p; d2 A {! J$ j8 _: v% k' t u8 i;+ }( W1 K) R. V. N$ ~$ ^ for(i=0;i<led_size;i++)" Q# L) b6 d" m% S0 K' Q { WS2811_SendByte(G); WS2811_SendByte(R);9 ^# u4 u) @5 c; ]' g ]: w; M% E9 @ WS2811_SendByte(B);2 ~+ {" j) P8 z } Reset(); } void ls_mode(void)& n8 b: S0 b4 U8 E0 k& H. Z9 Q { u8 i=0,ys=0,yz=0;: `) b6 A& A+ x- d t8 P) d for(i=led_size;i>0;i--)) ^% ~, d0 e& g. w8 Q/ T/ v7 G { if(i<=ls_t)* L7 x4 g) q C" x1 A5 R$ ~ f# E8 `+ O+ x { if(ys<ls_t) {. a. y; j. k5 V& s0 F ys++; }# K! K# T4 e- T& e% g( X else ys=0;: Z) U! j G I$ c3 t WS2811_SendByte(LED_data[45-(ys%45)][1]); WS2811_SendByte(LED_data[45-(ys%45)][0]); WS2811_SendByte(LED_data[45-(ys%45)][2]); } else3 @7 z( P% h3 S0 ] { if(yz>0) { yz--; } else yz=led_size-ls_t;+ T( o; M' I+ p( j WS2811_SendByte(LED_data[yz%45][1]);2 |7 t$ ~, A9 R: i WS2811_SendByte(LED_data[yz%45][0]); WS2811_SendByte(LED_data[yz%45][2]);% ^* @- S$ h: i! J: O% b } } Reset();. m* ]' }: B; S. c/ a0 U. v! Q }- E8 \ [2 v+ ? 1 ^( l) M" S9 o% t+ s 这是应用程序,其实就是PLAY一个数组,我刚刚开始的方法是完全用FOR来实现,发现哪样做每种流水方式都要重新写,太痛苦了。PLAY数组里面的内容相对会方便很多,当然也可以在函数名上加指针用来实现PLAY哪个数组,这个就自行改善吧!- Q* H9 ?0 A! p const u8 LED_data[45][3]={5 X( M( N' c2 Q4 R* _ {55,0,255},//G,R,B! L: w! J. D) m* E p6 g) p {100,0,200},3 U* ~* O5 ^: a8 R0 V, C {155,0,155},, f5 U. r O8 d) D2 u% { {200,0,100},( {' p+ S! F% `) w8 t* ? {255,0,55},//5 {255,0,0},- |$ F; E8 M" V3 }7 @6 e {255,0,0}, {255,0,0}, {255,0,0},2 g- P+ w& K+ N {255,0,0}, {255,0,0}, {255,0,0},1 e6 r3 l' E b0 l% X2 m& M, f; E/ o {255,0,0},& e g& x# ]& \4 Z1 x' o {255,0,0},% U. I1 Y+ x/ \/ M% _7 F, N% O- J {255,0,0},//154 Q4 Y& t, Q' c$ i. ?) [/ W4 @ {255,55,0}, {200,100,0},) g# h' q0 ?2 H5 i+ j {155,155,0},: w1 J7 s8 f7 U& S/ p8 ` {100,200,0}, {55,255,0},//20 {0,255,0},//G,R,B {0,255,0}, {0,255,0}, A4 _! ]2 P. S/ O! d7 F {0,255,0},, ?0 U, _! t9 y5 p8 a( h2 {. h- E {0,255,0},2 {1 S3 l+ i* _7 z {0,255,0},7 Q$ l. E% S, K6 |' ] {0,255,0}, {0,255,0}, {0,255,0}, {0,255,0},//30 {0,255,55},//G,R,B; ^1 Y# z: y& c: X+ @- e# m {0,200,100}, {0,155,155},# H* E9 C, e: b8 v& ~7 c& k {0,100,200},- I6 L+ N/ L2 Z, M6 S6 F2 n2 | {0,55,255}, {0,0,255},//35 {0,0,255}, {0,0,255}, {0,0,255}, {0,0,255},* h. ~$ T8 q$ \# ^8 _ ` {0,0,255}, {0,0,255},: o1 |5 o, F# l8 x- H1 V4 z" v {0,0,255},4 M; e6 _9 l! [$ D7 D! j* l {0,0,255}, {0,0,255}//45: Y& e( x* E; [: O9 q | };& E; V0 W7 u2 E! G) i2 V! k4 w , R1 @: m6 R$ M9 C' I! f8 t* j 这是要PLAY的数组,这次实现的是流水灯,在颜色链接的地方加上了渐变,这样更好看。当然也可以换上其它的方式 单单上面的程序流水灯是流不起来的,在定时中断用变量++来驱动:6 h b+ {3 d: ~1 `& l; C void TIM2_IRQHandler(void) // 1s enter { if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET) { // ls_mode12(); if(++t2>=ls_speed) {3 A( |' F- @6 G' {; S. M' T t2=0; if(++ls_t>=led_size) //注意!!) c6 }7 O. T X! E$ G/ P { ls_t=0; }" b" r1 r( }$ ` } TIM_ClearITPendingBit(TIM2, TIM_IT_CC1 ); } } N$ C& M, g E 这样在main函数调用ls_mode()灯就流起来了!! 漂亮的东西怎么没有视频:* ?: @. |5 y0 l* s - p! U8 N# `- C' @# |1 E+ Y G) l ![]() |
参与人数 4 | ST金币 +11 | 收起 理由 |
---|---|---|
|
+ 1 | 赞一个! |
|
+ 2 | 很给力! |
|
+ 5 | 很给力! |
|
+ 3 | 赞一个! |
思路就是用MOSI脚驱动,然后直接发送数据,用逻辑分析仪看高低电平的时间,然后做调整,比如发SPI发送0xE0,其实就是发送了3个1,5个0,这样低电平的时间就肯定长,然后自己看着来调整就行了。
请问您这边有思路吗,我也是想只使用定时器的PWM实现,补寄有的单片机没有DMA控制器
是72M的