/
功能:LED灯慢慢变暗,再慢慢变亮。
用定时器模拟的PWM调制。
单片机:AT89S52
/
#include <reg52h>
#define V_TH0 0XFF //设定定时器0,高8位的初值
#define V_TL0 0XF6 //设定定时器0,低8位的初值
#define V_TMOD 0X01 //设定定时器0的工作方式为:方式1(计数位数是16位 //,由TL0作为低8位、TH0作为高8位)
#define uchar unsigned char
#define uint unsigned int
void init_sys(); //系统初始化函数
void delay(uint); //延时函数
unsigned char ZKB; //占空比
void main (void)
{
init_sys(); //初始化
while(1)
{
for(ZKB=5;ZKB<40;ZKB=ZKB+2) //每调节一次占空比,就延时大概8ms左右,这使得LED现象更明显
{
delay(8);
}
for(ZKB=40;ZKB>5;ZKB=ZKB-2)
{
delay(8);
}
}
}
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=100;y>0;y--);
}
void init_sys() /系统初始化函数/
{
/定时器初始化/
TMOD=V_TMOD;
TH0=V_TH0;
TL0=V_TL0;
TR0=1;
ET0=1;
EA=1;
}
void timer0(void) interrupt 1 using 2
{
static uchar click=0; //中断次数计数器变量
TH0=V_TH0; //重新恢复定时器初始值
TL0=V_TL0;
++click; //每计数10次,产生一个中断,并且click增加一个
if (click>=100)
click=0; //计满一百次,这重新计数。
/因为计一次数的时间是1us,10次产生一个中断,也就是一个中断10us。100个中断为1ms。
则,可以在这100个数中随便取值,用于表示占空比的多少,占空比的范围为(1~100)/
if (click<=ZKB) //当小于占空比值时输出低电平,高于时是高电平,从而实现占空比的调整
P1=0x00; //P1口接的是LED灯
else
P1=0xff;
}
此程序的总中断时间为100ms,即频率为:100KHZ,占空比从5 变为40(即5%~25%)。
#include <reg51h> // 包含头文件
// 延时函数
// 参数 in 为延时的时间长度(单位时间很短,大约一条指令的时间)
void delay(unsigned int in)
{
unsigned int i;
for(i=0;i<100;i++) {;}
}
// 由暗变亮的子函数
// 参数 ledn 为点第几位的灯
void off_on(unsigned char ledn)
{
unsigned int i,j;
for(i=0;i<100;i++)
{
for(j=0;j<100;j++)
{
if(i<=j)
{ // 模拟pwm的低电平输出
P0 = 0;
}
else
{ // 模拟PWM的高电平输出
P0 = 1<<ledn;
}
delay(10); // 这里的延时 根据灯的情况自己调整
}
}
}
// 由亮变暗的子函数
// 参数 ledn 为点第几位的灯
void on_off(unsigned char ledn)
{
unsigned int i,j;
for(i=100;i>1;i--)
{
for(j=0;j<100;j++)
{
if(i<=j)
{ // 模拟pwm的低电平输出
P0 = 0;
}
else
{ // 模拟PWM的高电平输出
P0 = 1<<ledn;
}
delay(10); // 这里的延时 根据灯的情况自己调整
}
}
}
// 主程序开始
void main()
{
unsigned char ledn;
while(1)
{
for(ledn=0;ledn<8;ledn++)
{
off_on(ledn);
on_off(ledn);
}
}
}
这个程序我简单测试了一下,效果还好,不知道这个效果是不是您想要的?
说明一下啊,我这个程序是高电平点的灯,就是P0口在输出高电平的时候灯才会亮,
如果调试程序的时候看见各个灯的亮暗顺序反了的话,仅仅需要调换一下亮暗的顺序或者改一下输出的电平关系就可以了。
先说呼吸灯,这个本质上是LED的亮度控制。
一般是用PWM方式控制LED亮度,PWM的输出按照一定的规律变化,就可以做出呼吸灯的效果。
再说30个LED的控制,如果要简单点做,30个LED可以串起来串一个电阻,接高点的电源电压,30个LED用同一个信号控制,当然,亮度也是同步变化的。如果要复杂,那就出30个信号分别控制30个LED串30个电阻,具体看你的追求的效果吧。
呼吸灯的程序,如果有硬件的PWM模块,是很简单的,按一定的规律让PWM的输出变化就可以。
像这样输出10%亮度,持续200ms,输出20%亮度,持续200ms,输出30%亮度,持续200ms。。。
如果没有硬件PWM模块,可以用软件来模拟,比如,输出10%亮度,持续200ms这两件事合在一起作,变成输出高电平10us,输出低电平90us,循环2000次。
你可以了解一下ws2812,这个会好很多。
想过这种程序,但因为没什么卵用就给我忘了。
pwm要挺高频率才行,不然会闪,试过3灯的rgb,原理上差不多,但是直接程序死循环都难受,不是很流畅,你也可以参考一下。。。
#include "reg52h"
#include "intrinsh"
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=t4;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() //@12000MHz
{
unsigned char i, j, k;
_nop_();
_nop_();
i = 10;
j = 31;
k = 147;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void Delay10us() //@12000MHz
{
unsigned char i;
_nop_();
_nop_();
i = 27;
while (--i);
}
一51没有这样的功能,STC12单片机才有这样的功能,不过你可以用延时函数来产生PWM波形,但比较浪费CPU时间。二还有一种方法可以用51来实现,但要消耗两个定时器,一个T0定时器控制PWM周期,另一个T1定时器控制PWM占空比。(T0装的初值要大于T1的初值)在定时器中断的时候都是对I/O口进行取反就可以了。一个定时器产生PWM波形,做不出来,要两个的(不过只赏0分太少了吧!!!)
以上就是关于STC12C5A60S2制作呼吸灯C语言程序怎么写全部的内容,包括:STC12C5A60S2制作呼吸灯C语言程序怎么写、求一个89c52单片机的呼吸灯程序 要边呼吸边移动的 就是相当于呼吸灯流水灯结合、51单片机呼吸灯很暗等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)