求51单片机PWM程序(一个定时器产生三路PWM 可独立运作) 简单来说就是用三路独立的pwm控制三个LED

两按键K1、K2 控制LED 1

两按键K3、K4 控制LED 2

两按键K5、K6 控制LED 3

用的是STC 12C5A60S2

希望前辈帮忙编写一下 万分感谢
原本现有的程序

#include <reg52.h>
sbit LED=P2^3;
sbit k1=P2^0;
sbit k2=P2^1;
unsigned char PWM =0x7f;
char code reserve[3] _at_ 0x3b;
void delay(unsigned int ms)
{
unsigned char i;
while(ms--)
{
for(i=0;i<114;i++);
}
}
void main()
{
LED= 0xff ;
TMOD=0x21;
TH0=0xfe;
TL0=0xfe;
TH1=PWM;
TL1=0;
EA=1;
ET0=1;
ET1=1;
while(1)
{
{
TR0=1;
LED=PWM;
delay(10);
}

do{
{
PWM++;
if (PWM<0xfe)
{PWM;delay(10);}
else
PWM=0xfe;
}
}
while(k1==0);
do{
{
PWM--;
if(PWM>0x02)
{PWM;delay(10);}
else
PWM=0x02;
}
}
while(k2==0);
}
}
void timer0() interrupt 1
{
TR1=0;
TH0=0xfe;
TL0=0xfe;
TH1=PWM;
TR1=1;
LED=0x00;
}
void timer1() interrupt 3
{
TR1=0;
LED=0xff;
}

怎么可能搞不了三路独立的呢?楼下那位是被STC12C5A60S2的硬件蒙蔽了视线,他认为,STC12C只有两路PWM,无法实现3路,你却忘记了最原始的办法,不要说STC12有PWM功能,即使是传统的AT89S52这类没有PWM功能的单片机也一样能够实现楼主的要求.
下面我简单的分析一下我的思路,楼主尝试编程,如果不懂,再追问:
你是用三路独立的PWM调光用的,PWM调光,为了保证不让人眼产生闪烁,理论上PWM的频率要大于20Hz,而在实际的测试用,一般PWM要大于25Hz才能保证不闪烁.为了保险起见,我们将PWM的频率设定在30Hz左右,那么,周期就是33.333333ms,假设,我们实现10级调光,那个 每级的时间是3.33333ms
然后设置三个变量和一个计数器,我描述不太清楚,你看一下程序:

sbit P1_0 = P1^0; //---P1.0,P1.1,P1.2是三路PWM输出
unsigned char Set_PWM0 = 0; //--Set_PWM0 Set_PWM1 Set_PWM2
//--分别是低电平占整个脉冲的百分比
//--他们最小取0,最大取9
unsigned char counter = 0;//--用于计数的
void ISR_Timer0(void) interrupt 1 //---我们就用定时器0来做,不用PWM硬件
{ //----3.3333ms中断一次
counter++;

if(counter >= 10) counter = 0;
if(counter >= Set_PWM0) P1_0 = 0; else P1_0 = 1;
if(counter >= Set_PWM1) P1_1 = 0; else P1_1 = 1;
if(counter >= Set_PWM2) P1_2 = 0; else P1_2 = 1;

}

这样,定时器0用于决定PWM的反占空比,你只要设置 Set_PWM0等三个参数就可以了.
怎么会实现不了呢?追问

谢谢您的指教
我的理解首先是

三路PWM输出
sbit P1_0 = P1^0;

sbit P1_1 = P1^1;
sbit P1_2 = P1^2;

(我在用unsigned char PWM =0x7f; 是否三个参数都是0x7f)
unsigned char Set_PWM0 = 0;
unsigned char Set_PWM1 = 0;
unsigned char Set_PWM2 = 0;

但下面的部分就不懂了
//--分别是低电平占整个脉冲的百分比
//--他们最小取0,最大取9
....
在上面的问题补充了 我现在的程序 有什么部分可以使用?

追答

你的程序很乱,而且语法虽然没有错误,但是很多地方不规范.
比如:
sbit LED = P2^3;你后面却又是 LED = 0xFF,LED = 0x00...LED只是一个位,你用0xFF,0x00来赋值反而影响效率
再比如:
if(PWM
/*
本程序功能,输出PWM,频率为 1/单片机定时器周期*255
占空比为: 9.8% ----- 90.2%
单片机定时器周期由系统晶振决定
*/
sbit LED=P2^3; //---LED灯
sbit k1=P2^0; //---按键1
sbit k2=P2^1; //---按键2
unsigned char PWM =220;
void delay(unsigned int ms)
{
unsigned char i;
while(ms--)
{
for(i=0;i 25) //---占空比最大25个定时器周期
{ //---占空比为9.8%
PWM--;
delay(10);
}

} while(k2==0);
}
}
void timer0() interrupt 1
{
LED=0;
TR0=0;
TH1=PWM;
TR1 = 1;
}
void timer1() interrupt 3
{
LED = 1;
TR1 = 0;
TH0 = 255-PWM;
TR0 = 1;
}

追问

大致上看得明白,所以我想问的问题就回到原本的

就是现在只有一个LED灯控制位
(sbit LED=P2^3; //---LED灯 )
可以用按键1 , 按键2控制

如何可以增加LED灯控制位至两或三个
同时又可以独立工作 不会互相影响

追答

这个,在你写的程序的基础上,做不到,因为你写的PWM程序,只用一个PWM控制,最重要的是,你的PWM占用了两个定时器,也就是说,你的PWM把两个硬件资源占用光了,所以无法再加独立的控制了.

而用我的思路,就是我的第一次回答的思路,则可以解决问题,因为我用了三个PWM变量,共享一个硬件资源,三个PWM相互不影响.

另外,我想问一下,我的思路你没看明白吗?

追问

看了GUEL86 前辈的proteus仿真实例,在此再次感谢GUEL86

开始可以明白你的思路, 但都是有一些疑问(我基础不好不好意思)
unsigned char Set_PWM0 = 0; = 16) 16级调光的问题
出现了一个奇怪现状,就是增加光量到达某一个情度 再按加制 led 就变成无光
有什么方法改善

追答

没事.
Set_PWM0参数不同,导致占空比不同,PWM主要参数是占空比.
用Set_PWM0调节占空比.

我举个例子,假设我还是10级调光,即counter的范围是0--9,包括0,也包括9.
Set_PWM0的值我设定为1,Set_PWM0的值我设定为5,Set_PWM2的值我设定为7
根据我的程序:
if(counter >= Set_PWM0) P1_0 = 0; else P1_0 = 1;
if(counter >= Set_PWM1) P1_1 = 0; else P1_1 = 1;
if(counter >= Set_PWM2) P1_2 = 0; else P1_2 = 1;

看下面的表格:我用H代表高电平,用L代表低电平,注意我上面的程序与下面表格对应关系

Count: 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4
LED0 H L L L L L L L L L H L L L L L L L L L H L L L L
LED1 H H H H H L L L L L H H H H H L L L L L H H H H H
LED2 H H H H H H H H L L H H H H H H H H L L H H H H H

通过以上程序和表格,你看出为什么一定要三个变量了吗?三个变量设置不同的数值,就得到不同的占空比,而且相互之间独立不影响.

第二,频率是30Hz,那么30Hz的周期是就33.3333ms,你要怎么设置定时器TH0和TL0,就要看你几级调光,
如果你是10级调光,那么,你就设置定时器0,让它每3.3333ms中断一次
如果你要20级调光,那么,你就设置定时器0,让它每1.66666ms中断一次
如果你要100级调光,那么,就设置定时器0,让它每 0.33333ms中断一次.

具体怎么设置,设置为多少,是要看你的调光级别和你的单片机的时钟周期的.

你不管多少级调光,假设你是N级调光,那么,counter,Set_PWM0,Set_PWM1,Set_PWM2这四个参数,都永远不能大于等于counter.就是说,上面四个参数,都要小于counter.

温馨提示:答案为网友推荐,仅供参考
第1个回答  2013-02-06
有与你要求一致的proteus仿真实例,可以显示PWM 波形,按键调整,可供参考追问

可否传送至[email protected] 作参考

追答

邮箱不对呀,
无法发送到, 原因是:收件人邮件地址([email protected])不存在,邮件无法送达。.

追问

不好意思, 应该是[email protected]

追答

发了

追问

收到了,感谢前辈 十分有帮助

第2个回答  2013-02-05
STC 12C5A60S2搞不了三路独立的,里面只有独立的两路追问

如果是这样, 可否做到按键转换当前控制的灯再加以控制

例如 两按键K1、K2 控制亮度
按键K3 就转换控制pwm的输出位

追答

楼上的说的有道理,但是软件实现,始终纯在失效的时候,所以硬件比较靠谱点,或者说比较简单点,用别的单片机吧,c8051f因该有三路独立的,或者pic吧