整个工程所有文件代码如下
main.c
#include "ws2812.h"
#include"timer.h"
/*功能说明
单片机8G1K08
WS2812引脚接P5.5
烧录时晶振选22.1184M
*/
void main( )
{
unsigned char i=0;
Ws2812Init();
cmdWorkCnt=forNumber;
for(i=0;i<taskNumber;i++)
{
if(taskLed[i]>max)
{
max=taskLed[i];
}
}
refreshNumber=max;
AUXR=0x00;
WriteRgbNumber(refreshNumber,BLACK);
Ws2812Refresh(refreshNumber);
ConfigTimer0(1);
WDT_CONTR = 0x25;//使能看门狗,溢出时间约为1.1s
EA=1;
while( 1 )
{
WDT_CONTR = 0x35; //清看门狗,溢出时间约为1.1s
if( (cmdWorkCnt>0)&&(cmdNumber==0)&&(Number_Down[Wait_delay]==0) )
{
if(cmdWorkCnt!=0xFF)cmdWorkCnt--;
cmdNumber=taskNumber;
taskStep=0;
refreshNumber=0;
}
if(cmdNumber>0)//1
{
if(Number_Down[Wait_delay]==0)2
{
if(taskLed[taskStep]<=LED_MAX)//3
{
if(taskLed[taskStep]==0)//4
{
refreshNumber=max;//接下来刷新最大数量
WriteRgbNumber(refreshNumber,taskColorR[taskStep],taskColorG[taskStep],taskColorB[taskStep]);
}else
{
if(taskLed[taskStep]>refreshNumber)refreshNumber=taskLed[taskStep];
WriteRgbOne(taskLed[taskStep],taskColorR[taskStep],taskColorG[taskStep],taskColorB[taskStep]);
}///4
}/3
Number_Down[Wait_delay]=taskWaitTime[taskStep];
taskStep++;//4
cmdNumber--;
styleFig=1;
}//2
}/1
if(Number_Down[WsOut_delay]==0)
{
if(styleFig==1)
{
styleFig=0;
if(refreshNumber>0)Ws2812Refresh(refreshNumber);
refreshNumber=0;//清0刷新数
对需要点亮的灯珠进行输出 降低开销
}
}
}
}
config.h
#ifndef __CONFIG_H
#define __CONFIG_H
#include
#include
#include "string.h"
#define FOSC 22118400L
#define TASK_MAX 92
typedef unsigned char u8;//给8位数据类型unsigned char取个名字
typedef unsigned int u16;//给16位数据类型unsigned int取个名字
enum //延时任务枚举 最后参数不要加,
{
Wait_delay,
WsOut_delay,
Time_Delay
};
#define Down_Task (Time_Delay+1)//向下减数组长度
extern unsigned int Number_Down[Down_Task]; //延时-- 数组
sfr P1M0 = 0x92;
sfr P1M1 = 0x91;
sfr P3M0 = 0xb2;
sfr P3M1 = 0xb1;
sfr P5M0 = 0xca;
sfr P5M1 = 0xc9;
sfr P5=0xC8;
sfr WDT_CONTR = 0xc1;
//sfr AUXR=0x8E;
#define BIT0 0x01
#define BIT1 0x02
#define BIT2 0x04
#define BIT3 0x08
#define BIT4 0x10
#define BIT5 0x20
#define BIT6 0x40
#define BIT7 0x80
//GPIO封装
#define GPIOP0 0x00
#define GPIOP1 0x01
#define GPIOP2 0x02
#define GPIOP3 0x03
#define GPIOP4 0x04
#define GPIOP5 0x05
#define GPIO_Mode_Out_IN 0x00//M1:M0=00为准双向口 01为推挽 10为高阻 11为开漏
#define GPIO_Mode_Out_PP 0x01
#define GPIO_Mode_AIN 0x02
#define GPIO_Mode_Out_OD 0x03
#define PIN_0 0x01
#define PIN_1 0x02
#define PIN_2 0x04
#define PIN_3 0x08
#define PIN_4 0x10
#define PIN_5 0x20
#define PIN_6 0x40
#define PIN_7 0x80
#define PIN_L4 0x0F
#define PIN_H4 0xF0
#define PIN_ALL 0xFF
//GPIO封装
sfr IPH = 0xB7;
sfr INTCLKO = 0x8f;
sfr AUXINTIF=0xEF;
sfr T2L = 0xd7;
sfr T2H = 0xd6;
sfr IE2 = 0xaf;
#define ET2 0x04
#define T2IF 0x01
void SetGpioMode(unsigned char gpio,unsigned char pin,unsigned char mode);//设置GPIO模式
void IoModeInit();//IO口模式初始化
void TaskDelay();//延时
#endif
config.c
#include "config.h"
//引脚配置数据缓存
/*
unsigned char P0M1Buf=0;
unsigned char P0M0Buf=0;
*/
unsigned char P1M1Buf=0;
unsigned char P1M0Buf=0;
/*
unsigned char P2M1Buf=0;
unsigned char P2M0Buf=0;
*/
unsigned char P3M1Buf=0;
unsigned char P3M0Buf=0;
/*
unsigned char P4M1Buf=0;
unsigned char P4M0Buf=0;
*/
unsigned char P5M1Buf=0;
unsigned char P5M0Buf=0;
//引脚配置数据缓存
unsigned int Number_Down[Down_Task]; //延时-- 数组
/*******************************************************************************
* 函数功能 : 任务延时
* 函数说明 : 中断1ms调用一次
*******************************************************************************/
void TaskDelay()
{
unsigned char i;
for(i = 0; i < Down_Task; i++)
{
if(Number_Down[i])//不为0就--
{
Number_Down[i]--; //不为0就--
}
}
}
void SetGpioMode(unsigned char gpio,unsigned char pin,unsigned char mode)//设置GPIO模式 自己写的函数 为了方便配置引脚
{
/*
if(gpio==0)
{
if(mode==0)//准双向
{
P0M1Buf&=~pin;// M1:M0=00为准双向口
P0M0Buf&=~pin;//
}else if(mode==1)//推挽
{
P0M1Buf&=~pin;// M1:M0=01为推挽
P0M0Buf|=pin;//
}else if(mode==2)//模拟输入
{
P0M1Buf|=pin;// M1:M0=10为高阻
P0M0Buf&=~pin;//
}else if(mode==3)//开漏
{
P0M1Buf|=pin;// M1:M0=11为开漏
P0M0Buf|=pin;//
}
}else */if(gpio==1)
{
if(mode==0)//准双向
{
P1M1Buf&=~pin;// M1:M0=00为准双向口
P1M0Buf&=~pin;//
}else if(mode==1)//推挽
{
P1M1Buf&=~pin;// M1:M0=01为推挽
P1M0Buf|=pin;//
}else if(mode==2)//模拟输入
{
P1M1Buf|=pin;// M1:M0=10为高阻
P1M0Buf&=~pin;//
}else if(mode==3)//开漏
{
P1M1Buf|=pin;// M1:M0=11为开漏
P1M0Buf|=pin;//
}
}/*else if(gpio==2)
{
if(mode==0)//准双向
{
P2M1Buf&=~pin;// M1:M0=00为准双向口
P2M0Buf&=~pin;//
}else if(mode==1)//推挽
{
P2M1Buf&=~pin;// M1:M0=01为推挽
P2M0Buf|=pin;//
}else if(mode==2)//模拟输入
{
P2M1Buf|=pin;// M1:M0=10为高阻
P2M0Buf&=~pin;//
}else if(mode==3)//开漏
{
P2M1Buf|=pin;// M1:M0=11为开漏
P2M0Buf|=pin;//
}
}*/else if(gpio==3)
{
if(mode==0)//准双向
{
P3M1Buf&=~pin;// M1:M0=00为准双向口
P3M0Buf&=~pin;//
}else if(mode==1)//推挽
{
P3M1Buf&=~pin;// M1:M0=01为推挽
P3M0Buf|=pin;//
}else if(mode==2)//模拟输入
{
P3M1Buf|=pin;// M1:M0=10为高阻
P3M0Buf&=~pin;//
}else if(mode==3)//开漏
{
P3M1Buf|=pin;// M1:M0=11为开漏
P3M0Buf|=pin;//
}
}/*else if(gpio==4)
{
if(mode==0)//准双向
{
P4M1Buf&=~pin;// M1:M0=00为准双向口
P4M0Buf&=~pin;//
}else if(mode==1)//推挽
{
P4M1Buf&=~pin;// M1:M0=01为推挽
P4M0Buf|=pin;//
}else if(mode==2)//模拟输入
{
P4M1Buf|=pin;// M1:M0=10为高阻
P4M0Buf&=~pin;//
}else if(mode==3)//开漏
{
P4M1Buf|=pin;// M1:M0=11为开漏
P4M0Buf|=pin;//
}
}*/else if(gpio==5)
{
if(mode==0)//准双向
{
P5M1Buf&=~pin;// M1:M0=00为准双向口
P5M0Buf&=~pin;//
}else if(mode==1)//推挽
{
P5M1Buf&=~pin;// M1:M0=01为推挽
P5M0Buf|=pin;//
}else if(mode==2)//模拟输入
{
P5M1Buf|=pin;// M1:M0=10为高阻
P5M0Buf&=~pin;//
}else if(mode==3)//开漏
{
P5M1Buf|=pin;// M1:M0=11为开漏
P5M0Buf|=pin;//
}
}
}
void IoModeInit()//IO口模式初始化
{
P1M1=P1M1Buf;// M1:M0=00为准双向口 01为推挽 10为高阻 11为开漏
P1M0=P1M0Buf;//
P3M1=P3M1Buf;// M1:M0=00为准双向口 01为推挽 10为高阻 11为开漏
P3M0=P3M0Buf;//
P5M1=P5M1Buf;// M1:M0=00为准双向口 01为推挽 10为高阻 11为开漏
P5M0=P5M0Buf;//
}
timer.h
#ifndef __TIMER_H
#define __TIMER_H
#include"config.h"
extern unsigned char T0RH; //T0重载值的高字节
extern unsigned char T0RL; //T0重载值的低字节
void ConfigTimer0(unsigned int ms);
#endif
timer.c
#include"timer.h"
unsigned char T0RH = 0; //T0重载值的高字节
unsigned char T0RL = 0; //T0重载值的低字节
/*******************************************************************************
* 函数功能 : T0配置函数
* 函数说明 :
*******************************************************************************/
void ConfigTimer0(unsigned int ms)
{
unsigned long tmp; //临时变量
tmp = FOSC / 12; //定时器计数频率
tmp = (tmp * ms) / 1000; //计算所需的计数值
tmp = 65536 - tmp; //计算定时器重载值
tmp = tmp; //补偿中断响应延时造成的误差
T0RH = (unsigned char)(tmp>>8); //定时器重载值拆分为高低字节
T0RL = (unsigned char)tmp;
TMOD &= 0xF0; //清零T0的控制位
TMOD |= 0x01; //配置T0为模式1模式:01为16位定时器,02为8位自动重装定时器
TH0 = T0RH; //加载T0重载值(自动重装模式只需计算TH0)
TL0 = T0RL;
ET0 = 1; //使能T0中断
TR0 = 1; //启动T0
}
stc_it.c
#include"timer.h"
/* T0中断服务函数,用于数码管显示扫描与按键扫描 */
void InterruptTimer0() interrupt 1
{
TH0 = T0RH; //重新加载初值
TL0 = T0RL;
TaskDelay();//延时 1MS执行1次
}
ws2812.h
#ifndef __WS2812_H
#define __WS2812_H
#include"config.h"
#define LED_MAX 8
sbit DIO=P5^5;
#define Wait400ns {_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();} //388
#define Wait850ns {_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();} //860
#define BLACK 0,0,0
#define RED 255,0,0
#define GREEN 0,255,0
#define BLUE 0,0,255
#define YELLOW 255,255,0
//#define YELLOW 255,128,0
//#define YELLOW 221, 156, 0
#define PURPLE 255,0,255//紫
#define CYAN 0,255,255//青
#define WHITE 255,255,255
extern unsigned char xdata ledDataR[LED_MAX];
extern unsigned char xdata ledDataG[LED_MAX];
extern unsigned char xdata ledDataB[LED_MAX];
extern unsigned int taskNumber;
extern unsigned char forNumber;
extern unsigned int xdata taskLed[TASK_MAX];
extern unsigned char xdata taskColorR[TASK_MAX];
extern unsigned char xdata taskColorG[TASK_MAX];
extern unsigned char xdata taskColorB[TASK_MAX];
extern unsigned int xdata taskWaitTime[TASK_MAX];
extern bit styleFig;
extern unsigned int refreshNumber;
extern unsigned char cmdWorkCnt;
extern unsigned int cmdNumber;
extern unsigned int taskStep;
extern unsigned char max;//灯最大编号
void Ws2812Init();
void WriteRgbOne(unsigned int num,unsigned char Red,unsigned char Green,unsigned char Blue);
void WriteRgbNumber(unsigned int num,unsigned char Red,unsigned char Green,unsigned char Blue);
void Ws2812Refresh(unsigned int count);
#endif
ws2812.c
#include "ws2812.h"
unsigned char xdata ledDataR[LED_MAX];//
unsigned char xdata ledDataG[LED_MAX];
unsigned char xdata ledDataB[LED_MAX];
unsigned int taskNumber=92;
unsigned char forNumber=1;
unsigned int xdata taskLed[TASK_MAX]={1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,7,7,6,6,5,5,4,4,3,3,2,2,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,1,1,2,2,3,3,4,4,5,5,6,6,7,1,1,2,2,3,3,4,4,5,5,6,1,1,2,2,3,3,4,4,5,1,1,2,2,3,3,4,1,1,2,2,3,1,1,2,1};
unsigned char xdata taskColorR[TASK_MAX]={255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,0xFF,255,0,255,0,255,0,255,0,255,0,255,0,0xFF,255,0,255,0,255,0,255,0,255,0,0xFF,255,0,255,0,255,0,255,0,0xFF,255,0,255,0,255,0,0xFF,255,0,255,0,0xFF,255,0,0xFF,0xFF};
unsigned char xdata taskColorG[TASK_MAX]={255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,0xFF,255,0,255,0,255,0,255,0,255,0,255,0,0xFF,255,0,255,0,255,0,255,0,255,0,0xFF,255,0,255,0,255,0,255,0,0xFF,255,0,255,0,255,0,0xFF,255,0,255,0,0xFF,255,0,0xFF,0xFF};
unsigned char xdata taskColorB[TASK_MAX]={255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,0xFF,255,0,255,0,255,0,255,0,255,0,255,0,0xFF,255,0,255,0,255,0,255,0,255,0,0xFF,255,0,255,0,255,0,255,0,0xFF,255,0,255,0,255,0,0xFF,255,0,255,0,0xFF,255,0,0xFF,0xFF};
unsigned int xdata taskWaitTime[TASK_MAX]={30,0,30,0,30,0,30,0,30,0,30,0,30,0,30,0,30,0,30,0,30,0,30,0,30,0,30,0,30,0,30,0,30,0,30,0,30,0,30,0,30,0,0x1E,30,0,30,0,30,0,30,0,30,0,30,0,0x1E,30,0,30,0,30,0,30,0,30,0,0x1E,30,0,30,0,30,0,30,0,0x1E,30,0,30,0,30,0,0x1E,30,0,30,0,0x1E,30,0,0x1E,0x1E};
bit styleFig=0;
unsigned int refreshNumber=0;
unsigned char cmdWorkCnt=0;
unsigned int cmdNumber=0;
unsigned int taskStep=0;
unsigned char max=0;//灯最大编号
void Ws2812Init()
{
SetGpioMode(GPIOP5,PIN_5,GPIO_Mode_Out_PP);//设置GPIO模式 GPIO_Mode_Out_IN准双向 GPIO_Mode_Out_PP推挽 GPIO_Mode_AIN高阻GPIO_Mode_Out_OD开漏
IoModeInit();
DIO=0;
}
void Send0(void)
{
DIO=1;
Wait400ns;
DIO=0;
Wait850ns;
}
void Send1(void)
{
DIO=1;
Wait850ns;
DIO=0;
Wait400ns;
}
void Ws2812Rest(void)
{
DIO=0;
Number_Down[WsOut_delay]=2;
}
void WriteRgbOne(unsigned int num,unsigned char Red,unsigned char Green,unsigned char Blue)
{
ledDataR[(num-1)]=Red;
ledDataG[(num-1)]=Green;
ledDataB[(num-1)]=Blue;
}
void WriteRgbNumber(unsigned int num,unsigned char Red,unsigned char Green,unsigned char Blue)
{
unsigned int i=0;
for(;i<num;i++)
{
ledDataR[i]=Red;
ledDataG[i]=Green;
ledDataB[i]=Blue;
}
}
void Ws2812Refresh(unsigned int count)
{
unsigned int i=0;
EA = 0; //关中断
for(;i<count;i++)
{
if((ledDataG[i]&0x80)==0) Send0(); else Send1();//G
if((ledDataG[i]&0x40)==0) Send0(); else Send1();
if((ledDataG[i]&0x20)==0) Send0(); else Send1();
if((ledDataG[i]&0x10)==0) Send0(); else Send1();
if((ledDataG[i]&0x08)==0) Send0(); else Send1();
if((ledDataG[i]&0x04)==0) Send0(); else Send1();
if((ledDataG[i]&0x02)==0) Send0(); else Send1();
if((ledDataG[i]&0x01)==0) Send0(); else Send1();
if((ledDataR[i]&0x80)==0) Send0(); else Send1();//R
if((ledDataR[i]&0x40)==0) Send0(); else Send1();
if((ledDataR[i]&0x20)==0) Send0(); else Send1();
if((ledDataR[i]&0x10)==0) Send0(); else Send1();
if((ledDataR[i]&0x08)==0) Send0(); else Send1();
if((ledDataR[i]&0x04)==0) Send0(); else Send1();
if((ledDataR[i]&0x02)==0) Send0(); else Send1();
if((ledDataR[i]&0x01)==0) Send0(); else Send1();
if((ledDataB[i]&0x80)==0) Send0(); else Send1();//B
if((ledDataB[i]&0x40)==0) Send0(); else Send1();
if((ledDataB[i]&0x20)==0) Send0(); else Send1();
if((ledDataB[i]&0x10)==0) Send0(); else Send1();
if((ledDataB[i]&0x08)==0) Send0(); else Send1();
if((ledDataB[i]&0x04)==0) Send0(); else Send1();
if((ledDataB[i]&0x02)==0) Send0(); else Send1();
if((ledDataB[i]&0x01)==0) Send0(); else Send1();
}
EA = 1; //开中断
Ws2812Rest();
}