你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

再发STM32驱动WS2811灯带  

[复制链接]
anny 发布时间:2017-6-14 09:02
本帖最后由 anny 于 2017-6-14 13:07 编辑

其实社区有朋友发帖子用STM32驱动WS2811灯带了,他们用的是硬件SPI,其实也可以用PWM。
今天我的驱动方式不是用单片机外设来驱动,而是用最古老的延时方式,这种方式不适合地方你们自己想了,优点是灵活,想在哪个IO口驱动随便换。
还有,我这个驱动方式可以兼容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
                {
             Light_SDA=1;
             delay_us(1);
            Light_SDA=0;
            __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
                }
                else                        //发送数据0
                {
            Light_SDA=1;//0
            __nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
             Light_SDA=0;
            delay_us(1);
                }
                dat <<= 1;
        }
}


void Reset(void)                 
{        
    Light_SDA=0;
    delay_ms(30);
}

基本的发数据程序就这样了
void send_data(u8 R,u8 G,u8 B)
{
                u8 i;
                for(i=0;i<led_size;i++)
                {
                        WS2811_SendByte(G);
                        WS2811_SendByte(R);
                        WS2811_SendByte(B);
                }
                   Reset();
}

void ls_mode(void)
{
        u8 i=0,ys=0,yz=0;
        for(i=led_size;i>0;i--)
        {
                if(i<=ls_t)
                {
                        if(ys<ls_t)
                        {
                          ys++;
                        }
                        else
                                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]);
                }
                else
                {
                        if(yz>0)
                        {
                          yz--;
                        }
                        else
                                yz=led_size-ls_t;
                        WS2811_SendByte(LED_data[yz%45][1]);
                        WS2811_SendByte(LED_data[yz%45][0]);
                        WS2811_SendByte(LED_data[yz%45][2]);
                }
        }
          Reset();
}


这是应用程序,其实就是PLAY一个数组,我刚刚开始的方法是完全用FOR来实现,发现哪样做每种流水方式都要重新写,太痛苦了。PLAY数组里面的内容相对会方便很多,当然也可以在函数名上加指针用来实现PLAY哪个数组,这个就自行改善吧!
const u8 LED_data[45][3]={
        {55,0,255},//G,R,B
        {100,0,200},
        {155,0,155},
        {200,0,100},
        {255,0,55},//5
        {255,0,0},
        {255,0,0},
        {255,0,0},
        {255,0,0},
        {255,0,0},
        {255,0,0},
        {255,0,0},
        {255,0,0},
        {255,0,0},
        {255,0,0},//15
        {255,55,0},
        {200,100,0},
        {155,155,0},
        {100,200,0},
        {55,255,0},//20
        {0,255,0},//G,R,B
        {0,255,0},
        {0,255,0},
        {0,255,0},
        {0,255,0},
        {0,255,0},
        {0,255,0},
        {0,255,0},
        {0,255,0},
        {0,255,0},//30
        {0,255,55},//G,R,B
        {0,200,100},
        {0,155,155},
        {0,100,200},
        {0,55,255},
        {0,0,255},//35
        {0,0,255},
        {0,0,255},
        {0,0,255},
        {0,0,255},
        {0,0,255},
        {0,0,255},
        {0,0,255},
        {0,0,255},
        {0,0,255}//45
                           };


这是要PLAY的数组,这次实现的是流水灯,在颜色链接的地方加上了渐变,这样更好看。当然也可以换上其它的方式
单单上面的程序流水灯是流不起来的,在定时中断用变量++来驱动:
void TIM2_IRQHandler(void)  // 1s enter
{
     if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)
     {
//                        ls_mode12();
                if(++t2>=ls_speed)
                {
                        t2=0;
                        if(++ls_t>=led_size) //注意!!
                                {
                                        ls_t=0;
                                }
                        }
        TIM_ClearITPendingBit(TIM2, TIM_IT_CC1 );        
     }  
}


这样在main函数调用ls_mode()灯就流起来了!!
漂亮的东西怎么没有视频:

P70614-085819.gif

评分

参与人数 4 ST金币 +11 收起 理由
勿忘初心ºº¹ + 1 赞一个!
pythonworld + 2 很给力!
shaoziyang + 5 很给力!
MrJiu + 3 赞一个!

查看全部评分

1 收藏 7 评论33 发布时间:2017-6-14 09:02

举报

33个回答
dream2010 回答时间:2017-11-3 23:09:05
我也做了一批这个控制器,插TF卡,将要显示的数据保存成文件放在卡里,STM32读取,DMA传送到 SPI口,256级灰度可调,能控制1000个以上的芯片,这种芯片对时间要求比较严,一屏数据要按时序一次发完,否则可能显示就有问题,一直想换成PWM,但是不知道怎么去实现不停控制精准的时间,用示波器调感觉太麻烦了
myccl 回答时间:2018-5-6 20:28:02
anny 发表于 2018-5-3 08:17
兄弟,分享一下SPI是怎么驱动的?

思路就是用MOSI脚驱动,然后直接发送数据,用逻辑分析仪看高低电平的时间,然后做调整,比如发SPI发送0xE0,其实就是发送了3个1,5个0,这样低电平的时间就肯定长,然后自己看着来调整就行了。
翔2018 回答时间:2021-5-20 14:03:56
dream2010 发表于 2017-11-3 23:09
我也做了一批这个控制器,插TF卡,将要显示的数据保存成文件放在卡里,STM32读取,DMA传送到 S ...

请问您这边有思路吗,我也是想只使用定时器的PWM实现,补寄有的单片机没有DMA控制器
MrJiu 回答时间:2017-6-14 09:11:49
看起来不错的样子!!!!!!!!!!
anobodykey 回答时间:2017-6-14 09:13:36
很炫酷那
shaoziyang 回答时间:2017-6-14 09:17:00
挺不错的
Stm32McuLover 回答时间:2017-6-14 09:24:50
帮顶。。。。
左岸右岸 回答时间:2017-6-14 09:42:22
waiman 回答时间:2017-6-14 10:06:50
MCU是跑72Mhz 吗?
jackten 回答时间:2017-6-14 10:37:56
厉害厉害               
lisingch 回答时间:2017-6-14 10:53:15
漂亮,赞!
黑皮男 回答时间:2017-6-14 12:41:24
挺炫的
zero99 回答时间:2017-6-14 12:57:21
酷炫
anny 回答时间:2017-6-14 13:06:49

是72M的
时光虫子 回答时间:2017-6-14 16:19:52
做的不错,看上去很炫啊
epochal 回答时间:2017-6-14 20:03:00
不错。赞一个!
pythonworld 回答时间:2017-6-14 21:00:09
功耗如何,费电吗?
123下一页

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版