用了一片hc89s003,32个ws2812b灯珠(5050),8只104电容一个滚珠开关,一个带保护板的锂电池(160mAh),一个电源开关,一个USB口,简易充电电路,导线及0欧贴片电阻若干,还有30cm长的pvc线槽。
制作小技巧:
一、ws2812灯珠旋转个小角度,直接手拉手串接,电路简洁(图三,灯串两侧+-电源,第一灯外接输入);
二、滚珠开关斜向上45度左右安装;
三、usb口可用于充电,同时借用usb的D+/D-改为串口txd/rxd,接自制一条假usb真串口线时又可下载固件,很方便。下方串口下载四针仍保留;
四、电路除单片机(ssop20封装,图中转接板背面)和usb接口用了pcb板,其余均用导线加热熔胶方式,适合单件DIY;
五、软件参照论坛搜到的普通led灯摇摇棒程序,最低层改用了ws2812b驱动,延时参数边试边调整。
上加工后的实物图(摇时的闪烁图肉眼可见连续效果,手机拍不了)
制作小技巧:
一、ws2812灯珠旋转个小角度,直接手拉手串接,电路简洁(图三,灯串两侧+-电源,第一灯外接输入);
二、滚珠开关斜向上45度左右安装;
三、usb口可用于充电,同时借用usb的D+/D-改为串口txd/rxd,接自制一条假usb真串口线时又可下载固件,很方便。下方串口下载四针仍保留;
四、电路除单片机(ssop20封装,图中转接板背面)和usb接口用了pcb板,其余均用导线加热熔胶方式,适合单件DIY;
五、软件参照论坛搜到的普通led灯摇摇棒程序,最低层改用了ws2812b驱动,延时参数边试边调整。
上加工后的实物图(摇时的闪烁图肉眼可见连续效果,手机拍不了)
评分
/*
*32只WS2812+滚珠开关制作的摇摇棒*
*演示在上方16个LED上显示“你真棒”三个汉字
*CPU:HC89S003F4 16K bytes flash ROM, 256+256 bytes data RAM
*WS2812 接P22(推挽驱动) ,滚珠开关接P00(下降沿中断方式)
*晶振频率:32MHz,Fosc 16MHz
*程序版本:V1.00
*硬件平台:003F4 V1.00
*编写软件:Keil uVision4
*编写:xxd0708
*声明:本程序只供学习使用,未经作者许可,不得用于其它任何用途
*/
#define ALLOCATE_EXTERN
#include "HC89S003F4.h"
#include< intrins.h>
/**********************************************************
程序名称:LED摇摇棒显示64*16像素
简要说明:外部中断方式INT0显示;取模方式:纵向取模、字节倒序
(取点方式:纵向8点上高位,字节排列:上到下左到右)
**********************************************************/
sbit WS2812_IO = P2^2 ;
u8 KY; //防止重影的控制变量
u8 cont_rock=0;
u8 cont_col=0;
u8 col_r,col_g,col_b;
// 你(0) 真(1) 棒(2)
code u8 dat_word1[]=
{
0x00,0x80,0x01,0x00,0x06,0x00,0x1F,0xFF,0xE0,0x00,0x02,0x08,0x04,0x30,0x18,0xC0,
0xF0,0x02,0x10,0x01,0x13,0xFE,0x10,0x00,0x10,0x80,0x14,0x60,0x18,0x18,0x00,0x00,/*"你",3*/
0x00,0x08,0x20,0x08,0x20,0x09,0x2F,0xFA,0x2A,0xAC,0x2A,0xA8,0x2A,0xA8,0xFA,0xA8,
0x2A,0xA8,0x2A,0xA8,0x2A,0xAC,0x2F,0xFA,0x20,0x09,0x20,0x08,0x00,0x08,0x00,0x00,/*"真",4*/
0x08,0x20,0x08,0xC0,0x0B,0x00,0xFF,0xFF,0x09,0x00,0x08,0x80,0x22,0x48,0x2A,0x88,
0x2B,0x28,0x2E,0x28,0xFA,0xFF,0x2A,0x28,0x2B,0x28,0x2A,0x88,0x22,0x48,0x00,0x00,/*"棒",5*/
};
//延时子函数-16Mhz 1ms延时
void delayMs_16Mhz(u16 ms)
{
u16 j;
for(; ms>0; ms--)
for(j=1596; j>0; j--);
}
//延时函数-16Mhz 1us延时
void delayUs_16Mhz(u8 us)
{
for(; us>0; us--)
{
_nop_();
_nop_();
_nop_();
}
}
void ws2812_rst(void)
{
WS2812_IO = 0;
delayUs_16Mhz(80);
}
void ws2812_write_byte( u8 dat)
{
u8 i = 8;
dat<< = 1; //最高位进入CY
while(i)
{
//高电平时间小于0.45uS为逻辑0,大于时为逻辑1
WS2812_IO = 1;
//如果主频较高可在此处适当增加_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
WS2812_IO = CY;
_nop_();
_nop_();
_nop_();
_nop_();
//如果主频较高可在此处适当增加_nop_();
WS2812_IO = 0; //位发送完保持低电平,时间不大于50us。否则复位
_nop_();
_nop_();
_nop_();
_nop_();
dat<< = 1; //最高位进入CY
i--;
}
}
/*显示关闭*/
void display_off(void)
{
uchar i;
i=0;
while( i< 32 )
{
ws2812_write_byte( 0x00);
ws2812_write_byte( 0x00);
ws2812_write_byte( 0x00);
i++;
}
ws2812_rst();
}
/*显示子程序 在上方16个LED上显示三个汉字*/
void display_3word(void)
{
uchar i,j,temp;
//ws2812_rst();
i=0;
j=0;
while(j<96) //3个汉字3*16*2个字节
{
i=0;
while( i< 16 ) //下16不显示 可修改
{
//与普通LED主要更改点,有显示时发三个分量数据,否则发三个0
ws2812_write_byte( 0x00);
ws2812_write_byte( 0x00);
ws2812_write_byte( 0x00);
i++;
}
temp = dat_word1[j+1];//上方16位先送第二字节(依取模方式而定)
i=0;
while( i< 8 )
{
if(temp&0x01) //从低到高送显示位(依取模方式而定)
{
//与普通LED主要更改点,有显示时发三个分量数据,否则发三个0
ws2812_write_byte( col_g);
ws2812_write_byte( col_r);
ws2812_write_byte( col_b);
}
else
{
//与普通LED主要更改点,有显示时发三个分量数据,否则发三个0
ws2812_write_byte( 0x00);
ws2812_write_byte( 0x00);
ws2812_write_byte( 0x00);
}
i++;
temp = temp >>1; //下一位
}
temp = dat_word1[j]; //上方16位再送第一字节(依取模方式而定)
while( i< 16 )
{
if(temp&0x01) //从低到高送显示位(依取模方式而定)
{
//与普通LED主要更改点,有显示时发三个分量数据,否则发三个0
ws2812_write_byte( col_g);
ws2812_write_byte( col_r);
ws2812_write_byte( col_b);
}
else
{
//与普通LED主要更改点,有显示时发三个分量数据,否则发三个0
ws2812_write_byte( 0x00);
ws2812_write_byte( 0x00);
ws2812_write_byte( 0x00);
}
temp = temp >>1; //下一位
i++;
}
delayUs_16Mhz(200); //延时量自行调整,当摇的速度一定时,延时越大,字越宽但能显示字数减少
j +=2; //汉字下一列
}
//发送完三个汉字后清屏
display_off();
}
/*中断服务程序*/
void intersvr0(void) interrupt 0 using 1
{
//当从右向左摇时,产生中断,KY取反变为1,此时不显示,不运行下面的语句
delayMs_16Mhz(10);
if(~P0^0)//10mS消抖
{
cont_rock ++; //判断中断次数
if(cont_rock >= 20)
cont_rock = 20;
//每个摇动来回滚珠开关会在摆幅两端分别产生下降沿中断,只提取其中一次
delayMs_16Mhz(30); //延时量改变首字显示位置,越大越靠后
if((cont_rock&0x01) == 0) //偶数时显示(或奇数次,依初值和开关方向而定)
{
display_3word();
}
else
{
display_off();
}
}
PINTF0& = 0xFE;// HC89S003需软件清标志位INT0F
}
/**************************************************************************************
* @实现效果 将Fosc设置为16MHz,Fcpu设置为16MHz
**************************************************************************************/
void main()
{
/************************************系统初始化****************************************/
WDTCCR = 0x00; //关闭看门狗
//本例程为方便测试关闭看门狗,实际使用中,建议客户打开看门狗,详见WDT复位例程
CLKSWR = 0x51; //选择内部高频RC为系统时钟,内部高频RC 2分频,Fosc=16MHz
CLKDIV = 0x01; //Fosc 1分频得到Fcpu,Fcpu=Fosc
/**********************************相关配置初始化**************************************/
P2M1 = P2M1&0xF0|0x08; //WS2812信号 P22设置为推挽输出
P0M0 = P0M0&0xF0|0x06; //滚珠开关P00设置为带施密特上拉输入 (作为外部中断)
P00DBC = 0xFF; //滚珠开关P00端口消抖,约250uS
PITS0 = PITS0&0xFC|0x01; //外部中断0下降沿中断
EX0=1; //开外部中断
EA=1; //开总中断
cont_col = 0; //颜色索引初值
display_off();
while(1) //主程序中只检测按键
{
cont_rock = 0;
delayMs_16Mhz(1000);
if(cont_rock == 0) //检测1秒内摇摆次数,如无则颜色回初值
{
cont_col = 0;
}
else
{
//颜色索引每秒加一改变一次颜色
if(cont_col >=5) //暂用6种颜色
{
cont_col = 0;
}
else
{
cont_col ++; //改变颜色
}
//按索引赋显示颜色分量值
col_r = 0;
col_g = 0;
col_b = 0;
switch(cont_col)
{
case 0: col_r = 0x20;break;
case 1: col_g = 0x20;break;
case 2: col_b = 0x20;break;
case 3: col_r = 0x20;col_g = 0x20;break;
case 4: col_g = 0x20;col_b = 0x20;break;
case 5: col_b = 0x20;col_r = 0x20;break;
default: cont_col=0; col_r = 0x20;break;
}
}
}
}
评分
pwm是脉宽调制,即调节亮与灭的时间,亮时100%亮度,灭时0%亮度,理论上需要25%亮度时就让亮的时长占一个周期的25%,当时周期不能太大否则会感觉到闪烁。
现在看三色灯,如需RGB分量大小之比为3:2:1,pwm模式下其实是三色的时长为3:2:1,在灯珠静止时,那看起来是亮度之比(混色成某种橙黄色);而摇摇棒是动态的,所以看起来是摆动宽度之比,即此比例下实际一个周期有三段颜色,第一段RGB都亮(白色),第二段为R+G(黄色),第三段为R(红色),而不是合成色。
所以ws2812之类的彩灯如用于摇摇棒,实际只能显示8种颜色的点阵(R,G,B,R+G,R+B,G+B,R+G+B和0,即红绿蓝黄橙青白黑),数值的大小可改变8色之1的点阵扫过的宽度,但不能产生新的颜色。
综上,用ws2812灯时,静的时候可以混色,但不能产生平面效果;摇的时候可以产生平面效果,但只有8色。8色显字或简单图案,玩玩是够了,但真彩还是别想了。
一不小心在手机上输了这么多字 :-P
评分
ws2812b有三路独立的8位pwm,如果灯珠静止,占空比就表现为该静止点的三路灯的亮度,理论可显24位真彩。
但ws2812b的pwm周期为2.5mS(400Hz),未考虑到快速运动场景。故灯珠快速运动时(平移与旋转),占空比就表现为一个周期内运动幅度中亮灯状态运动长度的大小,而不能表现为某个单点的亮度,即在某个具体点三路灯各有亮或暗两种状态,共2的3次幂=8种组合,也就是只有8色之一。
所以我前文所指出的,静可显真彩但做不了摇摇棒或旋转屏,动可做摇摇棒或旋转屏但只有8色。