ws2812驱动相信有不少人都用过,大家对这款彩色LED真的是又爱又恨,爱的是它它使用简单,采用单总线通信方式,节约IO口,而且可以多级串联。而普通的彩色LED不是共阴就是共阳,每个颜色一个引脚,一般都是用PWM驱动,想要控制亮度、颜色就要分别控制每个引脚上的PWM占空比,想要驱动多个LED就更麻烦了。恨的是ws2812对时序的要求比较高,对低速单片机不太友好而且开发比较复杂。
今天我们就针对基于ME8S003硬件PWM如何快速实现控制ws2812的驱动。其中ME8S003提供的2路PWM模块可以轻松实现当下流行的LED驱动WS2812的通信,不需要过多占用CPU时间。敏矽微提供整套软、硬件解决方案,帮助用户快速开发;
1、概述
“WS2812”解决方案
ME8S003是内嵌8051兼容的1T高性能8位微控制器。该系列控制器具有高性能、高适应范围和超低成本特点。内置48MHz主时钟和独立的低速(30K/1.5M可切换)时钟,常用外设8路1M高速12位的ADC转换器,允许4路输入2个比较器,2+3通道PWM,2个UART串口,SPI接口,I2C总线接口,3通用16位计数器/定时器。低功耗支持深度睡眠和掉电模式。提供M2调试端口,实现系统仿真。
2、WS2812基本说明
“WS2812”快速解决方案
WS2812B是一款全彩LED控制IC,单总线控制,何为单总线我的理解就是数据线在一根线上传输的控制方式就是单总线。
WS2812是一个集控制电路与发光电路于一体的智能外控LED光源,外形一般为5050封装,每个LED灯珠为一个像素点,支持RGB无极调色,同时每颗灯珠内部集成有智能数字接口数据锁存信号整形放大驱动电路,还包含有高精度的内部振荡器和可编程定电流控制部分,有效保证了像素点光的颜色高度一致。
3、ME8S003使用PWM实现数据移位输出
“WS2812”快速解决方案
ME8S003内嵌一个PWM模块,可以支持两个独立的16位PWM输出。同时还可以配置成为两个定时器,或者两路PWM合并支持载波输出(如实现38K Irda应用),或者配置两个不同的PWM输出来对应bit数据0/1并合并在一起,从而实现使用PWM进行bit流数据的移位输出。
下面我们将讨论如何使用PWM模块实现bit流数据的移位输出:
首先,我们将对PWM0和PWM1进行周期和占空比分别配置,其中PWM0的周期(PWM0CRCH/ PWM0CRCL)和占空比(PWM0CCH/ PWM0CCL)将用来代表数据0,PWM1的周期(PWM1CRCH/ PWM1CRCL)和占空比(PWM1CCH/ PWM1CCL)将用来代表数据1。0和1的周期和占空比是不同的,以WS2812应用为例,PWM0的周期和占空比分别为1.2us和0.3us,PWM0的周期和占空比分别为1.2us和0.9us。
当我们使能PWM的数据移位功能时,要输出数据0,PWM移位输出管脚(PWMSHT)就PWM0配置的波形;要输出数据1,PWM移位输出管脚就PWM1配置的波形。
最后的问题就是如何连续输出一个bit数据流。ME8S003 PWM为这个移位功能设置一个乒乓缓存(PWMSHIFTDAT0/ PWMSHIFTDAT1),我们只需要来回切换并不断把需要发出的数据喂入乒乓缓存即可。
当所有数据传输结束,关闭PWM。
4、WS2812控制实程
“WS2812”快速解决方案
ME8S003提供了全套的驱动,其中关于PWM 移位数据功能有PWM配置函数和PWM数据移位输出函数;
PWM配置函数:
void PWM_DataShift_Cfg(unsigned long cyclefreq,unsigned char duty0inpercentage,unsigned char duty1inpercentage)
cyclefreq:PWM周期频率,单位hz
duty0inpercentage:数据0输出占空比的百分比
duty1inpercentage:数据1输出占空比的百分比
void PWM_DataShift_Cfg(unsigned long cyclefreq,unsigned char duty0inpercentage,unsigned char duty1inpercentage)
{
unsigned long temp,temp1;
unsigned char clkshift;
clkshift=(PWMCON0&0x07)+1;
if (clkshift>2)
temp=SystemClock>>clkshift;
else
temp=SystemClock;
temp=temp/cyclefreq;
PWM0CRCL=temp&0xFF;
PWM0CRCH=(temp>>8)&0xFF;
PWM1CRCL=PWM0CRCL;
PWM1CRCH=PWM0CRCH;
temp1=(temp*duty0inpercentage)/100;
PWM0CCL=temp1&0xFF;
PWM0CCH=(temp1>>8)&0xFF;
temp1=(temp*duty1inpercentage)/100;
PWM1CCL=temp1&0xFF;
PWM1CCH=(temp1>>8)&0xFF;
set_PWMCON1_SHIFTDIR;
}
PWM数据移位输出函数:
void PWM_DataShift(unsigned char * dataptr,unsigned char len)
dataptr:输出数据起始指针
len:数据长度
void PWM_DataShift(unsigned char * dataptr,unsigned char len)
{
PWMSHIFTDAT0=*dataptr++;
PWMSHIFTDAT1=*dataptr++;;
PWM_DATASHIFT_START;
len-=2;
//shift all data
while(len)
{
if (PWMSTA_DAT0BF==0)
{
PWMSHIFTDAT0=*dataptr++;
len--;
}
if (len==0)break;
if (PWMSTA_DAT1BF==0)
{
PWMSHIFTDAT1=*dataptr++;
len--;
}
}
while(PWM_DATASHIFT_BUSY);
PWM_DATASHIFT_STOP;
}
3个WS2812 驱动的LED灯实例程序:
Main.c
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include "me8s003.h" // SFR declarations
#include "io_mux.h"
#include "sfr_macro.h"
#include "sys.h"
#include "pwm.h"
//-----------------------------------------------------------------------------
// main() Routine
//-----------------------------------------------------------------------------
//3 ledunsigned char color_data[9]={0xFF,0x80,0x40,0x40,0xFF,0x80,0x80,0x40,0xFF};
unsigned char max_data_no=9;
unsigned int data_index;
void main (void)
{
Modify_System_Clock(HCLK_48M);
P0_5_INIT(P0_5_PIO);
P0_Output_Enable(IO_BIT5);
P1_2_INIT(P1_2_PWMSHT);
PWM_Init(PWM_CLK_DIVIDED_BY_1);
PWM_DataShift_Cfg(833000,25,75); //833K=~1.2us PWM cycle, 25%=~0.3us, 75%=~0.9us
while (1)
{
//shift data
PWM_DataShift(color_data,max_data_no);
//prepare next data
for(data_index=0;data_index<=max_data_no;data_index++)
{
color_data[data_index]=color_data[data_index]+1;
}
P0_5 =!P0_5; // Turn onoff LE
Ddelay(800); //Reset, >80us
}
}
来源:敏矽MCU
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。