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

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

怎么可能搞不了三路独立的呢楼下那位是被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语言程序等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/9313305.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-27
下一篇 2023-04-27

发表评论

登录后才能评论

评论列表(0条)

保存