求一个stc15w202s单片机的呼吸灯程序 要边呼吸边移动(波浪状), 就是相当于呼吸灯流水灯结合。

#include<reg51.h>
#include "PWM.h"
#define u8 unsigned char
#define u16 unsigned int
#define u32 unsigned long
sbit PWMOUT1 = P3^2;
sbit PWMOUT2 = P3^3;
u32 PeriodCnt = 0;
u8 HighRH = 0;
u8 HighRL = 0;
u8 LowRH = 0;
u8 LowRL = 0;
u8 T0RH = 0;
u8 T0RL = 0;
unsigned char j;
void ConfigPWM(u16 fr, u8 dc);
void ConfigTimer0(u16 ms);
void delay(unsigned int i);
void AdjustPWM(u8 dc);

//T2产生PWM波,T0来查表法改变占空比
void main()
{
EA = 1;
P1 = 0xFF;
P3 = 0xFF;
P5 = 0xFF;
ConfigPWM(100, 16);
ConfigTimer0(50);
while(1);
}
void ConfigPWM(u16 fr, u8 dc)
{
u16 high, low;
PeriodCnt = (11059200/12)/fr; //计算一个周期所有需的计数值。
high = (PeriodCnt*dc)/100; //计算高电平所需要的计数值。
low = PeriodCnt - high; //计算低电平所需要的计数值。
high = 65536 - high; //高电平定时器重载值。
low = 65536 - low; //低电平定时器重载值。
HighRH = (u8)(high>>8);
HighRL = (u8)high;
LowRH = (u8)(low>>8);
LowRL = (u8)low;
T2H = (u8)(high>>8); //定时器重载值拆分为高低字节
T2L = (u8)high;
AUXR |= 0x14; //辅助寄存器不12分频
IE2 |= 0X04; //使能T2定时器中断
}
void InterruptTimer2() interrupt 12
{
if(PWMOUT1 == 1)
{
T2H = LowRH;
T2L = LowRL;
PWMOUT1 = 0;
PWMOUT2 = 0;
PWMOUT3 = 0;
}
else
{
T2H = HighRH;
T2L = HighRL;
PWMOUT1 = 1;
PWMOUT2 = 1;
PWMOUT3 = 1;
}
}
void ConfigTimer0(u16 ms)
{
u32 tmp;
tmp = 11059200;
tmp = (tmp*ms)/1000;
tmp = 65536 - tmp;
T0RH = (u8)(tmp >> 8);
T0RL = (u8)tmp;
TH0 = T0RH >>8;
TL0 = T0RL;
TR0 = 1; //定时器开始计时
ET0 = 1; //使能定时器0中断
}
void InterruptTimer0() interrupt 1
{
static u8 dir = 0;
static u8 index = 0;
u8 code Table[] = {
16,16,17,17,18,18,19,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,
52,54,56,58,60,62,64,66,68,70,72,74,76,78,80,82,84,86,88,90,92,94,96,98,100
}; //48次循环
AdjustPWM(Table[index]);
if(dir == 0)
{
index++;
if(index == 47)
dir = 1;
}
if(dir == 1)
{
index--;
if(index == 0)
dir = 0;
}
}
void AdjustPWM(u8 dc)
{
u16 high, low;
high = (PeriodCnt*dc)/100; //高电平所需要的计数值。
low = PeriodCnt - high; //低电平所需要的计数值。
high = 65536 - high; //电高平计数初值。
low = 65536 - low; //低电平计数初值。
HighRH = (u8)(high>>8); //定时器高电平总数重载值拆分为高低字节
HighRL = (u8)high;
LowRH = (u8)(low>>8); //定时器低电平总数重载值拆分为高低字节
LowRL = (u8)low;
}
void delay(unsigned int i) //延时毫秒
{
for(i=0;i<100;i++) {;}
}
//可以在这个基础上优化吗?谢谢!!

你可以了解一下ws2812,这个会好很多。
想过这种程序,但因为没什么卵用就给我忘了。
pwm要挺高频率才行,不然会闪,试过3灯的rgb,原理上差不多,但是直接程序死循环都难受,不是很流畅,你也可以参考一下。。。
#include "reg52.h"
#include "intrins.h"
sbit r=P1^0;
sbit g=P1^1;
sbit b=P1^2;
void Delay200ms();
void play(char rz1,char gz1,char bz1,int t);
void Delay10us();
//占空比从0到100变化
void main(void)
{
while(1)
{char rz=0,gz=0,bz=0;
char x=0,y=0,z=0;
r=1;
g=1;
b=1;
Delay200ms(); //接线验证,rgb依次亮起
r=0;
Delay200ms();
r=1;
g=0;
Delay200ms();
g=1;
b=0;
Delay200ms();
b=1;
Delay200ms();
for(x=5;x>=0;x--) //彩色连续变化
{rz=100;gz=0;bz=0;
play(rz,gz,bz,1);
for(gz=0;gz<=100;gz++)
play(rz,gz,bz,1);
for(rz=100;rz>=0;rz--)
play(rz,gz,bz,1);
for(bz=0;bz<=100;bz++)
play(rz,gz,bz,1);
for(gz=100;gz>=0;gz--)
play(rz,gz,bz,1);
for(rz=0;rz<=100;rz++)
play(rz,gz,bz,1);
for(bz=100;bz>=0;bz--)
play(rz,gz,bz,1);
}
}
}
//显示色彩程序,pwm,显示某占空比颜色时间t
void play(char rz1,char gz1,char bz1,int t)
{
char i=rz1,j=gz1,k=bz1,yt;
for(t=t*4;t>=0;--t)
{
i=rz1;j=gz1;k=bz1;

for(yt=100;yt>=0;yt--)
{
if(i>0)
r=0;
else
r=1;
if(j>0)
g=0;
else
g=1;
if(k>0)
b=0;
else
b=1;
--i;
--j;
--k;
Delay10us();
}

}
r=1;g=1;b=1;
}
//延时程序组
void Delay200ms() //@12.000MHz
{
unsigned char i, j, k;
_nop_();
_nop_();
i = 10;
j = 31;
k = 147;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void Delay10us() //@12.000MHz
{
unsigned char i;
_nop_();
_nop_();
i = 27;
while (--i);
}追问

我这个程序已经实现单个灯的呼吸效果了,加上流水是否就可以实现波浪呼吸效果呢?如何加呢?

追答

本质就是8路pwm输出,流水效果可以通过一个8*128(即8灯,每个128种状态循环)的数组完成,每运行一段时间换一组,控制每个pwm。。。虽然我想这么说,但是如果手打确实很累。所以,你可以实时计算这个数组(8个元素),可以定时器中断,每10ms对其更新,然后主函数里面尽可能快地跑pwm。算法是核心。简化就是把所有比较在一起做,不用每个pwm输出单独做。反正我就差不多这个思路,也没做过,你可以试试看

温馨提示:答案为网友推荐,仅供参考
相似回答