|
本帖最后由 anny 于 2017-6-14 13:07 编辑 ( D( b' K* a5 `% H, S3 } 5 y1 u+ [( g5 B: e% i; `$ C 其实社区有朋友发帖子用STM32驱动WS2811灯带了,他们用的是硬件SPI,其实也可以用PWM。 今天我的驱动方式不是用单片机外设来驱动,而是用最古老的延时方式,这种方式不适合地方你们自己想了 ,优点是灵活,想在哪个IO口驱动随便换。* Q( A( H6 P( q还有,我这个驱动方式可以兼容UCS1903、SM16703等等这些灯带。 驱动芯片:STM32F103RBT6 频率:72M 说明:为了保护单片机我用了块74HC245来隔离,也算是做了电压转换,从3.3V变成了5V 好吧,上程序: void WS2811_SendByte(u8 dat)//发送1BIT的数据 { u8 i; for(i=0;i<8;i++) { if(dat & 0x80) //发送数据1, q9 H7 j. V1 {8 \5 W {8 c, ^9 C4 E( O( q- |9 G( y. l Light_SDA=1; delay_us(1); Light_SDA=0; __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop(); } else //发送数据0 {+ S" \& P7 [8 J( k- C! N- w9 n Light_SDA=1;//0 __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();$ R% ~2 l5 A. a Light_SDA=0; delay_us(1); } dat <<= 1;6 K- n/ @( A$ E+ _+ I- {8 g }( f2 i( I6 O4 J0 `* P4 q1 O* Z } y W$ _* O7 f7 f - Q) V4 s" [, d) Z1 F( I# t" J void Reset(void) * L' Z' R) c- K+ t$ |( v* h9 n { Light_SDA=0;9 Q5 e: H$ _6 Z$ [ delay_ms(30);; M+ D( z# }6 s L$ W3 ]( j } 基本的发数据程序就这样了 void send_data(u8 R,u8 G,u8 B)& Y" `7 x8 ^) ^1 Z# _ {% W/ f8 ]1 n) e f' j8 W u8 i; for(i=0;i<led_size;i++)5 q2 f3 a# H" ]. e3 f3 B {' ~% C W! [# d! w( F WS2811_SendByte(G);: v# u$ M- Q2 e M0 a# C WS2811_SendByte(R); WS2811_SendByte(B);; [% h+ x. K- [7 @. `4 ^! }5 A } Reset(); }* y" J0 k: b w1 v' g / w. S8 Q: b% J3 d0 L# U void ls_mode(void)' d" h$ X+ Q o {6 r6 {) V# ]. W5 N6 F4 _4 K' _/ ] u8 i=0,ys=0,yz=0; for(i=led_size;i>0;i--), f0 s4 i5 P% I. w2 [0 u! o5 c {. L) P& p: o# k. p/ r) e. v1 ^ if(i<=ls_t)" p- J) p `0 [; Y7 O { if(ys<ls_t)( {# |, d& p2 @8 t { ys++; } else ys=0; WS2811_SendByte(LED_data[45-(ys%45)][1]);8 T* A6 D* ~) ^5 O: _ WS2811_SendByte(LED_data[45-(ys%45)][0]);3 V6 [# i0 w( W0 ?. e. y WS2811_SendByte(LED_data[45-(ys%45)][2]);$ j, } F v. P1 a' H( P) E } else |9 ~: H9 [, ^5 Q3 `" e { if(yz>0) { yz--; } else yz=led_size-ls_t;, a5 e+ W5 I- y$ s% P2 y WS2811_SendByte(LED_data[yz%45][1]);! C% J5 B( i6 D; d- J WS2811_SendByte(LED_data[yz%45][0]);8 I. P2 f) ^- @# j1 X* \ WS2811_SendByte(LED_data[yz%45][2]);2 W; R S7 P0 u } }+ ~+ M: ?3 G! k; r" U6 } Reset();; k+ Z0 H- _( |6 _0 Q7 E }+ e* ]- h' \5 S" d( S7 C 0 z9 o4 [' k6 m7 S7 V6 E. ^ 这是应用程序,其实就是PLAY一个数组,我刚刚开始的方法是完全用FOR来实现,发现哪样做每种流水方式都要重新写,太痛苦了。PLAY数组里面的内容相对会方便很多,当然也可以在函数名上加指针用来实现PLAY哪个数组,这个就自行改善吧!' F& X) B/ t7 J y7 n1 m: f* p7 _! e const u8 LED_data[45][3]={5 L' |4 y) \3 y: T {55,0,255},//G,R,B {100,0,200},' G4 Z" W) F3 C3 s+ c6 f {155,0,155},. T; G* s( x: s4 \ Z& g5 e# f- C {200,0,100}, {255,0,55},//5) c6 _% X E. W% v9 E7 ~, a% C {255,0,0},: E7 ^; { g2 ~: Y! K {255,0,0},: Q8 L1 y$ D6 f {255,0,0}, {255,0,0}, {255,0,0}, {255,0,0},4 q7 D" a, ? b! u& r {255,0,0}, {255,0,0}," Y! Z, ?* @. C- Q2 ^& _ Y! G {255,0,0}, {255,0,0},//15 {255,55,0}, {200,100,0},9 s0 J/ b# h/ c. P+ I- J1 ~ {155,155,0}, {100,200,0},+ T% a" d$ B4 K% ]$ l" e {55,255,0},//20 {0,255,0},//G,R,B {0,255,0},* w5 m5 v7 O9 ?% z- o {0,255,0},3 e1 O( q4 T4 K2 N: ]& ? {0,255,0},* o- R: S% s# u# X8 i {0,255,0}, {0,255,0}, {0,255,0}, {0,255,0}, {0,255,0}, {0,255,0},//30+ R; B6 a- W( e% x {0,255,55},//G,R,B {0,200,100}, {0,155,155}, {0,100,200}, {0,55,255},1 |9 \$ g1 |2 b! q" m7 U9 v% B {0,0,255},//35% t9 s4 R+ c, x! G9 _7 R {0,0,255},0 a( K+ E: Z0 W; ` e4 x2 Z) k) w {0,0,255}, {0,0,255},4 W- ^$ @: f; v, }) u! z {0,0,255},- i( c" N: i+ W4 C! Y0 n7 a" s {0,0,255},; n, J8 d3 t9 |* h" X; c {0,0,255},: @! N1 j3 R- A {0,0,255}, {0,0,255},& k7 z% T0 T( E& a5 u" J% z9 v- a) H9 d {0,0,255}//45 };, L* f+ w+ ^2 h$ {! l' I" x$ [1 c ! s0 r) `' }" M0 R8 V 这是要PLAY的数组,这次实现的是流水灯,在颜色链接的地方加上了渐变,这样更好看。当然也可以换上其它的方式 单单上面的程序流水灯是流不起来的,在定时中断用变量++来驱动: void TIM2_IRQHandler(void) // 1s enter( p! | E* N1 h% Y/ d, A { if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)4 I$ N% o/ i, w2 x+ a$ _ {1 t* t! T# a" S! E" [ // ls_mode12(); if(++t2>=ls_speed) {9 ]3 W; L, r# E7 D t2=0; if(++ls_t>=led_size) //注意!! { ls_t=0;; d( b8 c+ j' F1 R1 f }" R0 q/ t! p- T/ b% D3 V8 e6 C/ \ }% n' ]' J3 i3 t/ L. m TIM_ClearITPendingBit(TIM2, TIM_IT_CC1 ); 3 y4 F7 o: o3 I' H9 w# C% H } }3 J" p ^1 D- }1 M + N% h; a; H% |6 Q) J. w( j" Y [" O1 B& g2 A' m0 P 这样在main函数调用ls_mode()灯就流起来了!! 漂亮的东西怎么没有视频:* P) Y# h: a( n1 |& e: o - ^; H1 c" o1 p' J$ n3 C0 \# z
|
| 参与人数 4 | ST金币 +11 | 收起 理由 |
|---|---|---|
|
|
+ 1 | 赞一个! |
|
|
+ 2 | 很给力! |
|
|
+ 5 | 很给力! |
|
|
+ 3 | 赞一个! |
微信公众号
手机版
思路就是用MOSI脚驱动,然后直接发送数据,用逻辑分析仪看高低电平的时间,然后做调整,比如发SPI发送0xE0,其实就是发送了3个1,5个0,这样低电平的时间就肯定长,然后自己看着来调整就行了。
请问您这边有思路吗,我也是想只使用定时器的PWM实现,补寄有的单片机没有DMA控制器4 \6 k, I4 P \
是72M的