/****************************************************************************************
* 如果你找了很多资源,你灯颜色还是不对,你的时序还是乱,
* 那么我这里给你一点提示,关闭所有中断试试。
* 还不行?这是我的邮箱:784823702@qq.com
****************************************************************************************/
#include <stm32f10x.h>
#include "WS2811.h"
#include "SysTick.h"
#define nWs 50 // 有多少颗WS2811级联
/* 显存 */
unsigned long WsDat[nWs]={0x00ff00,0x0000ff,0x0000ff,0x0000ff,0xff0000
// ,0x0f0000,0xff0000,0xff0000,0xff0000,0xff0000,
// 0x0000ff,0x0000ff,0x0000ff,0x0000ff,0x0000ff,0x0000ff,0x0000ff,0x0000ff,0x0000ff,0x0000ff,
// 0xff0000,0xff0000,0xff0000,0xff0000,0xff0000,0xff0000,0xff0000,0xff0000,0xff0000,0xff0000,
// 0xff0000,0xff0000,0xff0000,0xff0000,0xff0000,0xff0000,0xff0000,0xff0000,0xff0000,0xff0000,
// 0x00ff00,0x00ff00,0x00ff00,0x00ff00,0x00ff00,0x00ff00,0x00ff00,0x00ff00,0x00ff00,0x00ff00,
};
void delayus(u32 i )
{
u32 j;
while(--i)
{
for(j=0;j<7;j++);
}
}
void delayms(u32 i )
{
u32 j;
while(--i)
{
delayus(1000);
}
}
void delay2us()
{
unsigned char i;
for(i=0; i<5; i++);
}
void delay05us()
{
unsigned char i=0;
for(;i<0;i++);
}
/***************************
* 发送一比特
****************************/
void TX0()
{
GPIOB->ODR |= 1<<4;
delay05us();
GPIOB->ODR &= ~(1<<4);
} // 发送0
void TX1()
{
GPIOB->ODR |= 1<<4;
delay2us();
GPIOB->ODR &= ~(1<<4);
} // 发送1
void WS_Reset()
{
GPIOB->ODR &= ~(1<<4);
delayus(30);
}
/**************************************************************************************
* 发送一字节
**************************************************************************************/
void WS_Set1(unsigned long dat)
{
unsigned char i;
for(i=0; i<24; i++)
{
if(0x800000 == (dat & 0x800000) ) TX1();
else TX0();
dat<<=1; //左移一位
}
}
/**************************************************************************************
* 发送所有字节
**************************************************************************************/
void WS_SetAll()
{
unsigned char j;
delay05us();
for(j=0; j<nWs; j++)
{
WS_Set1(WsDat[j]); // j / 0
}
WS_Reset();
}
void WS_Set()
{
unsigned char j;
for(j=0; j<nWs; j++)
{
WS_Set1(WsDat[0]); // j / 0
}
WS_Reset();
}
/********************************************
* 求绝对值
********************************************/
unsigned char abs0(int num)
{
if(num>0) return num;
num = -num;
return (unsigned char) num;
}
/***********************************************************************************
* 颜色渐变算法
* 误差 <= 2
************************************************************************************/
u32 ColorToColor(unsigned long color0, unsigned long color1)
{
unsigned char Red0, Green0, Blue0; // 起始三原色
unsigned char Red1, Green1, Blue1; // 结果三原色
int RedMinus, GreenMinus, BlueMinus; // 颜色差(color1 - color0)
unsigned char NStep; // 需要几步
float RedStep, GreenStep, BlueStep; // 各色步进值
unsigned long color; // 结果色
unsigned char i;
// 绿 红 蓝 三原色分解
Red0 = color0>>16;
Green0 = color0>>8;
Blue0 = color0;
Red1 = color1>>16;
Green1 = color1>>8;
Blue1 = color1;
// 计算需要多少步(取差值的最大值)
RedMinus = Red1 - Red0;
GreenMinus = Green1 - Green0;
BlueMinus = Blue1 - Blue0;
NStep = ( abs0(RedMinus) > abs0(GreenMinus) ) ? abs0(RedMinus):abs0(GreenMinus);
NStep = ( NStep > abs0(BlueMinus) ) ? NStep:abs0(BlueMinus);
// 计算出各色步进值
RedStep = (float)RedMinus / NStep;
GreenStep = (float)GreenMinus / NStep;
BlueStep = (float)BlueMinus / NStep;
// 渐变开始
for(i=0; i<NStep; i++)
{
Red1 = Red0 + (int)(RedStep * i);
Green1 = Green0 + (int)(GreenStep * i);
Blue1 = Blue0 + (int)(BlueStep * i);
color = Green1<<8| Red1<<16 | Blue1; // 合成 绿红蓝
WsDat[0] = color;
WS_Set(); // 输出
delayms(10); // 渐变速度
}
// 渐变结束
return color;
}