|
本帖最后由 anny 于 2017-6-14 13:07 编辑 ) j ~+ h; V7 H: J 2 y/ E* O: [$ H/ m! ?8 U6 } 其实社区有朋友发帖子用STM32驱动WS2811灯带了,他们用的是硬件SPI,其实也可以用PWM。2 Y& `1 N. _! i6 v8 y- q 今天我的驱动方式不是用单片机外设来驱动,而是用最古老的延时方式,这种方式不适合地方你们自己想了 ,优点是灵活,想在哪个IO口驱动随便换。还有,我这个驱动方式可以兼容UCS1903、SM16703等等这些灯带。5 |9 s) ~' e3 j4 Y 驱动芯片:STM32F103RBT6 频率:72M 说明:为了保护单片机我用了块74HC245来隔离,也算是做了电压转换,从3.3V变成了5V( h3 j( h. {+ w$ L) K' h6 w; _ 好吧,上程序:9 F5 _, c6 t; A1 i* w" e4 U& |. b void WS2811_SendByte(u8 dat)//发送1BIT的数据 {6 a* L! w1 d1 H0 M2 v7 [ u8 i;) y1 B* |4 E: C3 A1 `' M" b3 a for(i=0;i<8;i++) { if(dat & 0x80) //发送数据1 {1 i$ w" Z9 K4 g+ d2 t Light_SDA=1; delay_us(1); Light_SDA=0; __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop(); } else //发送数据0 {8 D3 \- t5 l' A# S+ ]1 f Light_SDA=1;//02 h% G* K& Z# L( X5 `2 q/ J* a2 E6 Q __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop(); Light_SDA=0;' B+ `+ i$ A2 @) X8 g# M/ M1 P delay_us(1); }! \1 b8 v. \! l' o! G5 z6 @ dat <<= 1;: ^9 y7 H# K- z9 o& a$ }& N$ e }( \' B/ f) c5 O8 {% {) a }' O& k5 u. G6 v5 s' B# a j! d! Y( K " q8 x# r1 k; x. t/ V void Reset(void) { Light_SDA=0;& n( g: a+ W+ d5 u. _ delay_ms(30); } 基本的发数据程序就这样了 void send_data(u8 R,u8 G,u8 B)) t7 g, H( B5 H$ ?7 u! l4 ?3 z& ` { u8 i; for(i=0;i<led_size;i++) {- [- A/ o5 ]6 B u9 `8 r% O: d1 k7 P3 K* L0 z WS2811_SendByte(G);$ h5 B r3 v1 o+ `: V WS2811_SendByte(R); WS2811_SendByte(B);$ p/ `$ {* h* U }# E% U/ A9 Z* A6 h Reset();) Q' B. E+ p# z } 9 y: [4 S( }( D. n% k" W# O. T void ls_mode(void) { u8 i=0,ys=0,yz=0;0 V. T" p( S. q4 n) Y( d+ Z for(i=led_size;i>0;i--)* J# t+ }5 }- u# X { if(i<=ls_t)& m1 }1 {) }6 m4 \$ l {8 |, B, B3 k4 e& a1 i4 c if(ys<ls_t) { ys++;) L: v( }5 c" b& A } else ys=0; WS2811_SendByte(LED_data[45-(ys%45)][1]);$ ~; e* T: W- C w! C WS2811_SendByte(LED_data[45-(ys%45)][0]);) V, @ y3 w; x5 P, t7 g" N WS2811_SendByte(LED_data[45-(ys%45)][2]); } else4 P+ e$ ?; J1 n {* o& ^- ?' U V8 C0 A if(yz>0)5 |- O. t. N/ D( g- `% l { yz--; }8 p/ o' f* H. e! z else yz=led_size-ls_t;, I' a: G- P6 C* a WS2811_SendByte(LED_data[yz%45][1]); WS2811_SendByte(LED_data[yz%45][0]); WS2811_SendByte(LED_data[yz%45][2]);9 b+ Y: j( F* U Q4 r+ I } }& K( a: u: _1 P# I0 K9 v Reset();! c( K# i" C5 U } 8 \2 a1 R0 d, w# u! D 这是应用程序,其实就是PLAY一个数组,我刚刚开始的方法是完全用FOR来实现,发现哪样做每种流水方式都要重新写,太痛苦了。PLAY数组里面的内容相对会方便很多,当然也可以在函数名上加指针用来实现PLAY哪个数组,这个就自行改善吧!1 a8 g2 |; r8 K( i9 S/ ? g const u8 LED_data[45][3]={6 G) j& H5 i7 F, U. R {55,0,255},//G,R,B1 U8 c/ e3 ?4 @* P {100,0,200}, {155,0,155},4 k4 X, Z# z5 {5 k5 P4 Y) K: m {200,0,100},6 G, Y) s2 @0 d3 Y {255,0,55},//5. u# A9 j! ~% O# G2 D# T {255,0,0},9 P' S% i7 J! J" y+ j4 c {255,0,0},2 Y" q. Z% K2 o4 f5 _3 O- H {255,0,0},, I; v, W$ A" D/ {* H- X" Y {255,0,0}, {255,0,0},; w2 ?: E9 n& \, i: Q m1 _ {255,0,0},4 J7 _- y+ y! \7 w( i! H {255,0,0},0 `; w7 w8 f# ~5 I {255,0,0},$ a$ x! v- o6 { o2 U9 {! D {255,0,0}, {255,0,0},//15 {255,55,0}, {200,100,0},+ I0 H! Y8 ?6 Q4 Y1 h. i+ { {155,155,0},! v" Y# F1 p$ Q) B: d {100,200,0},1 Y* w0 T! o/ T4 T4 d {55,255,0},//20 {0,255,0},//G,R,B {0,255,0}, {0,255,0},. p+ E, ^& Z5 X$ x {0,255,0}, {0,255,0}, {0,255,0}, {0,255,0}, {0,255,0},3 u9 o) @# M8 A {0,255,0}, {0,255,0},//30 {0,255,55},//G,R,B; X. ?: P% I. F, ^; x& y8 u7 g {0,200,100},# [. k( T7 a9 ?& w/ v. G1 C {0,155,155},) n4 {: c0 k% `1 K, T/ q {0,100,200},! _4 R9 j* n: R5 [6 Z7 ], l' z {0,55,255},* H- C& ~7 M. n$ M( v7 u' b {0,0,255},//35, X0 G9 }% b: G0 D {0,0,255}, {0,0,255},5 b( E% ]9 I# \- W2 m6 `0 }7 q {0,0,255}, {0,0,255},' Z; G! h+ G; x {0,0,255},# t8 c! a5 _4 L {0,0,255}, {0,0,255},( f6 [+ B/ H2 W$ K2 C& d {0,0,255},- Q4 t* b/ _; F- V {0,0,255}//45 };& R# I( P5 D( C/ _; ? , k& c6 J0 c2 T; H' a2 q / x: K. S( Z" v W 这是要PLAY的数组,这次实现的是流水灯,在颜色链接的地方加上了渐变,这样更好看。当然也可以换上其它的方式% Y2 r# [) ?" ^; P 单单上面的程序流水灯是流不起来的,在定时中断用变量++来驱动: void TIM2_IRQHandler(void) // 1s enter { if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET) { // ls_mode12();4 g$ W0 y1 B5 P! F5 ]; ` if(++t2>=ls_speed) { t2=0;* N+ k7 k# V3 G: l if(++ls_t>=led_size) //注意!!, v- b4 F% I' h0 Z {; z1 u, q L; Z; h" P* t) c ls_t=0;/ n8 u' F& z2 I5 `8 d" V( [" D } }* {$ x* D- \! L' s$ X/ R TIM_ClearITPendingBit(TIM2, TIM_IT_CC1 ); } $ O- W8 x( Z1 `! L% N }+ V- h- y2 L# E f) X& l% @5 S 1 \$ _5 n9 a8 L3 V 这样在main函数调用ls_mode()灯就流起来了!! 漂亮的东西怎么没有视频:
|
| 参与人数 4 | ST金币 +11 | 收起 理由 |
|---|---|---|
|
|
+ 1 | 赞一个! |
|
|
+ 2 | 很给力! |
|
|
+ 5 | 很给力! |
|
|
+ 3 | 赞一个! |
微信公众号
手机版
思路就是用MOSI脚驱动,然后直接发送数据,用逻辑分析仪看高低电平的时间,然后做调整,比如发SPI发送0xE0,其实就是发送了3个1,5个0,这样低电平的时间就肯定长,然后自己看着来调整就行了。
请问您这边有思路吗,我也是想只使用定时器的PWM实现,补寄有的单片机没有DMA控制器
是72M的