怎么可能搞不了三路独立的呢楼下那位是被STC12C5A60S2的硬件蒙蔽了视线,他认为,STC12C只有两路PWM,无法实现3路,你却忘记了最原始的办法,不要说STC12有PWM功能,即使是传统的AT89S52这类没有PWM功能的单片机也一样能够实现楼主的要求
下面我简单的分析一下我的思路,楼主尝试编程,如果不懂,再追问:
你是用三路独立的PWM调光用的,PWM调光,为了保证不让人眼产生闪烁,理论上PWM的频率要大于20Hz,而在实际的测试用,一般PWM要大于25Hz才能保证不闪烁为了保险起见,我们将PWM的频率设定在30Hz左右,那么,周期就是33333333ms,假设,我们实现10级调光,那个 每级的时间是333333ms
然后设置三个变量和一个计数器,我描述不太清楚,你看一下程序:
sbit P1_0 = P1^0; //---P10,P11,P12是三路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硬件
{ //----33333ms中断一次
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等三个参数就可以了
怎么会实现不了呢
你用定时器开中断吧,如果只是简单的用IO口的话,得到的频率很不准确的!
思路:根据单片机的晶振大小计算定时器的初值,在中断程序里给对要输出脉冲的引脚取反 *** 作就是了,例如:P1^0=~P1^0;
还有脉冲频率不能太高哦,要保证定时器的计时时间大于中断程序执行时间~~
程序大体结构:
void Init_timer() //定时器初始化
{
}
void main() //主程序
{
}
void t0() interrupt 1//t0的中断程序
{
}
1、 利用定时器控制产生占空比可变的 PWM 波
按K1,PWM值增加,则占空比减小,电机减速。
按K2,PWM值减小,则占空比增加,电机加速。
当PWM值增加到最大值或减小到最小值时,蜂鸣器将报警。
2、例程:
//
#include<reg51h>
#include<intrinsh>
sbit K1 =P1^4 ; //PWM值增加键
sbit K2 =P1^5 ; //PWM值减少键
sbit BEEP =P3^7 ; //蜂鸣器
unsigned char PWM=0x7f ; //赋初值
void Beep();
void delayms(unsigned char ms);
void delay(unsigned char t);
//
void main()
{
P1=0xff;
TMOD=0x21 ;
TH0=0xfc ; //1ms延时常数
TL0=0x66 ; //频率调节
TH1=PWM ; //脉宽调节
TL1=0 ;
EA=1;
ET0=1;
ET1=1;
TR0=1 ;
while(1)
{
do{
if(PWM!=0xff)
{PWM++ ;delayms(10);}
else Beep() ;
}
while(K1==0);
do{
if(PWM!=0x02)
{PWM-- ;delayms(10);}
else Beep() ;
}
while(K2==0);
}
}
//
// 定时器0中断服务程序 (频率)
//
void timer0() interrupt 1
{
TR1=0 ;
TH0=0xfc ;
TL0=0x66 ;
TH1=PWM ;
TR1=1 ;
P0=0x00 ; //启动输出
}
//
// 定时器1中断服务程序 (脉宽)
//
void timer1() interrupt 3
{
TR1=0 ;
P0=0xff ; //结束输出
}
//
//蜂鸣器子程序
//
void Beep()
{
unsigned char i ;
for (i=0 ;i<100 ;i++)
{
delay(100) ;
BEEP=!BEEP ; //Beep取反
}
BEEP=1 ; //关闭蜂鸣器
delayms(100);
}
//
// 延时子程序
//
void delay(unsigned char t)
{
while(t--) ;
}
//
// 延时子程序
//
void delayms(unsigned char ms)
{
unsigned char i ;
while(ms--)
{
for(i = 0 ; i < 120 ; i++) ;
}
}
//
#include<reg51h>
#define uint unsigned int
uint pwm=50;
bit flag=0;
sbit pluse=P1^0;
sbit key=P1^4;
void t0isr() interrupt 1
{
if(flag)pluse=1;
else pluse=0;
flag=~flag;
}
main()
{
TMOD=0x02;
TH0=256-(char)(pwm28/100);
TL0=256-(char)(pwm28/100);
TR0=1;
ET0=1;
EA=1;
while(1)
{
if(key==0)
{
while(key==0);
pwm+=10;
if(pwm>=100)pwm=10;
}
if(flag)
{
TH0=256-(char)(pwm28/100);
TL0=256-(char)(pwm28/100);
}
if(!flag)
{
TH0=256-28+(char)(pwm28/100);
TL0=256-28+(char)(pwm28/100);
}
}
}
给个我自己写的程序你,我试过了,通过!
#include
#define
uchar
unsigned
char
#define
uint
unsigned
int
sbit
P0_0=P0^0;
uchar
a;
/
TH0和TL0是计数器0的高8位和低8位计数器,
计算办法:TL0=(65536-C)%256;
TH0=(65536-C)/256,
其中C为所要计数的次数即多长时间产生一次中断;
TMOD是计数器工作模式选择,0X01表示选用模式1,
它有16位计数器,最大计数脉冲为65536,最长时间
为1ms65536=65536ms
/
void
init_sys(void);
/系统初始化函数/
void
main
(void)
{
init_sys();
while(1);
}
void
init_sys(void)
{
TMOD=0x01;
TH0=(65536-10000)/256;
TL0=(65536-10000)%256;
EA=1;
ET0=1;
TR0=1;
}
void
timer0(void)
interrupt
1
{
TH0=(65536-100)/256;
TL0=(65536-100)%256;
a++;
if(a<=3)
{
P0_0=1;
if(a==3)
//改变低电平持续时间
{
//也即改变占空比
P0_0=~P0_0;
}
}
else
{
P0_0=0;
if(a==5)
//改变周期
{
a=0;
}
}
}
用两个定时器的方法是用定时器T0来控制频率,定时器T1来控制占空比。大致的的编程思路是这样的:T0定时器中断让一个I0口输出高电平,在这个定时器T0的中断当中起动定时器T1,而这个T1是让IO口输出低电平,这样改变定时器T0的初值就可以改变频率,改变定时器T1的初值就可以改变占空比。
用一个定时器时(如定时器T0),首先你要确定PWM的周期T和占空比D,确定了这些以后,你可以用定时器产生一个时间基准t,比如定时器溢出n次的时间是PWM的高电平的时间,则DT=nt,类似的可以求出PWM低电平时间需要多少个时间基准n'。
因为这里我们是产生周期为1ms(1000HZ)的PWM,所以可设置中断的时间基准为001ms,,然后中断100次即为1ms。在中断子程序内,可设置一个变量如time,在中断子程序内,有三条重要的语句:1、当time>=100时,time清零(此语句保证频率为1000HZ),2、当time>n时(n应该在0-100之间变化开),让单片相应的I/O口输出高电平,当time<n时,让单片相应的I/O口输出低电平,此时占空比就为%n。
参考资料:
pwm(uchar zkb)
{
uchar x =100;
led=0;
delay(xzkb/100);
led=1;
delay(xzkb/100);
}
#include <reg52h>
#define uint unsigned int
#define uchar unsigned char
uchar count ,z;
sbit key_1 = P3^7;
sbit key_2 = P3^6;
sbit PWM = P2^0;
void key_control();
void init ();
void create_PWM(uchar);
void delay(uint);
void main ()
{
init ();
while(1);
{
key_control();
create_PWM(count);
}
}
void delay(uint z)
{
uint x,y;
for(x = z;x>0;x--)
for(y = 110;y>0;y--);
}
void init()
{
TMOD = 0x10;
TH1 = (65536-4608)/256;//50sm
TL1 = (65536-4608)%256;
TR1 = 1;
}
void create_PWM(uchar count)
{
static i;
if(TF1 == 1)
{
TF1 = 0;
TH1 = (65536-4608)/256;//50sm
TL1 = (65536-4608)%256;
i++;
if(i == 100) i=0;
if(i <= count) PWM = 1;
else PWM = 0;
}
}
void key_control()
{
if(key_1 ==0)
{
delay(10);
if(key_1 == 0)
{
count+= 5;
if(count >= 100)count = 0;
}
}
if(key_2 ==0)
{
delay(10);
if(key_2 ==0)
{
count-= 5;
if(count <= 0)count =100;
}
}
}
以上就是关于求51单片机PWM程序(一个定时器产生三路PWM 可独立运作) 简单来说就是用三路独立的pwm控制三个LED全部的内容,包括:求51单片机PWM程序(一个定时器产生三路PWM 可独立运作) 简单来说就是用三路独立的pwm控制三个LED、51单片机怎样做PWM、有没有51控制pwm的c语言程序等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)