关于PWM程序

关于PWM程序,第1张

include <stdioh>

#define N 3

void zz(int x[N][N])

{ int i,j,t;

for(i=0;i<N;i++)

for(j=0;j<i;j++)

{ t=x[i][j]; x[i][j]=x[j][i]; x[j][i]=t; }

}

void main()

{ int str[N][N]={1,2,3,4,5,6,7,8,9}, i,j;

zz(str);

for(i=0;i<N;i++)

{ for(j=0;j<N;j++) printf(“%3d”,str[i][j]) ;

printf("\n") ;

}

}

什么单片机呀,有8路PWM?如果是用定时器来模拟的话,还行。

uchar Led1, Led2,Led8; //灯亮度

void timer0() //定时器中断

{

static uchar num = 0;

num++;

if(num == Led1) L1 = 0;

if(num == Led2) L2 = 0;

if(num >= 255){ //255:亮度级数,

num = 0;

if(Led1 > 0) L1 = 1;

if(Led2 > 0) L2 = 1;

}

}

中断频率越高,灯闪烁越低。

PWM的意思是“脉冲宽度调制”

PWM有两个最基本的参数:频率、占空比。

频率就是每秒钟电平高低变化的次数,占空比是指高电平保持时间和整个脉冲周期中的比例关系。

对于用定时器来模拟,最基本的方法就是使用一个IO口循环设置其输出值为高电平和低电平。

那么定时器在这里起计时作用,而且需要两个时间:高电平持续时间、低电平持续时间。

只要做到这两个时间的计时,那么就可以实现基本的PWM了。

而要做到两个时间的计时,有两种方案:

1单计时器方案

int i;//计时变量

timer1(){//计时器1中断函数

  //此处示例每隔100个最小计时周期电平变化一次,即200个最小计时周期闪烁一次

  i++;

  if (i==200){

    i=0;//变量复位,完成一个周期,准备下一个周期    

  }

  else if (i==100){

    LED_OFF;//关灯

  }

  else if (i==0){

    LED_ON;//开灯

  }

}

2双计时器方案

//只需要设计好两个计时器的初值和周期,即可完成交替亮灭

timer1(){//计时器1中断函数

  //此处示例每隔100个最小计时周期电平变化一次,即200个最小计时周期闪烁一次

  LED_ON;//开灯

}

timer2(){

  LED_OFF;//关灯

}

这个问题不是在这个篇幅内能说清楚的。简短地说,交流电机调速有交流电机的pwm驱动方式,直流电机调速有直流电机的pwm驱动方式。

交流电机的pwm调速原理,主要通过一个频率可变的交流低频信号,去调制一个高频方波驱动电压,从而在电机电枢中得到一个随调制信号频率变化的驱动电流。于是交流电机电枢就在这个电流驱动下,产生与调制信号频率一致的旋转磁场,使得电机转子旋转速度发生改变。它的调制方式是调频。

直流电机的pwm调速原理与交流电机调速原理不同,它不是通过调频方式去调节电机的转速,而是通过调节驱动电压脉冲宽度的方式,并与电路中一些相应的储能元件配合,改变了输送到电枢电压的幅值,从而达到改变直流电机转速的目的。它的调制方式是调幅。

#include <reg52h >

#define uchar unsigned char

#define uint unsigned int

sbit s2=P3^7;

sbit s3=P3^6;

sbit fm=P2^3;

uchar pwm,num;

void delay(uint ms)

{

uchar i;

while(ms--)

{

for(i=0;i<120;i++);

}

}

void keyscan()

{

if(s2==0)

{

delay(80);

if(s2==0)

{

if(pwm<32)

{

pwm++;

delay(150);

}

else //如果大于32 蜂鸣器想

{

bee( );

}

}

}

if(s3==0)

{

delay(80);

if(s3==0)

{

if(pwm>1)

{

pwm--;

delay(50);

}

else //如果小于1 蜂鸣器想

{

bee( );

}

}

}

}

void init_t0( )

{

TMOD=0x01;

TH0=(65536-500)/256; //500ms

TL0=(65536-500)%256;

EA=1;

ET0=1;

TR0=1;

}

void t0( ) interrupt 1

{

TR0=0; //关计时器

TH0=(65536-500)/256;

TL0=(65536-500)%256;

num++;

if(num>32)

{

num=0;

}

if(num<=pwm )

{

P1=0xff;

}

else

{

P1=0x00;

}

TR0=1;

}

void main( )

{

init_t0( );

num=0;

pwm=0;

while(1)

{

keyscan();

}

}

/ 利用定时器控制产生占空比可变的 PWM 波

// 按K1,PWM值增加,则占空比减小,电机减速。

// 按K2,PWM值减小,则占空比增加,电机加速。

// 当PWM值增加到最大值或减小到最小值时,蜂鸣器将报警。

//

#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++) ;

}

}

//

你那个地方不明白?能具体说说吗?我看程序已经有不少注释了啊?

下面的比较多,复杂些,先简单的说下吧:

一、加速减速,就是增加或减少脉冲宽度,改变电机速度!脉冲的宽度由

1、CLK=0的状态持续,由T1的定时决定;

2、CLK=1的状态持续,由(T0-T1)的时间决定;

二、定时器中断TH0=0x00 ;   TL0=0x00 ;

1、T0定时器工作1方式,T0定时器启动后,从TH0、TL0赋值的计数值开始增加,增加到0XFFFF后,T0中断!

2、T0溢出后(中断),T0计数器不会自动停止,所以需要重新给T0定时器赋值!赋值后,进入下一个计数周期!

3、例子中,T0定时器从0x0000开始计数,也就是增加0xFFFF后进行中断!定时时间为 (0xFFFF / ( 晶振周期/12 ))) 秒,若晶振为12M,则定时为,65536ms!

分析程序,从main开始分析,先将起始开始的时序图画出:

如下图!

从时序图可以看出,CLK为PWM输出,

1、CLK=0的状态持续,由T1的定时决定;

2、CLK=1的状态持续,由T0-T1的时间决定;

而   main   函数中的  while(1)   部分,进行的就是PWM调整程序。

1、  if (K3==0)   //高电平逆时钟转,低电平顺时钟转

{

ZF=0;

}

else

{

ZF=1;

}

根据程序推测,程序若为电机控制,K3开关为0时,ZF=0,顺时针转,K3开关为1时,ZF=1,逆时针转。

2、

if(K1==0)   //按下加速键

{

delay(1);

PWML++;   //调宽值低四位加1

if(PWML==0x00)

{

PWMH++;

}   //调宽值高四位加1

if (PWMH==0xFF) //最大值时

{

PWMH=0xFE;

}

}

K1按键,加速按键,增加T1定时器计数起始时间,也就是减少T1计数时间,减少CLK=0的时间。

3、

if(K2==0) //按下减速键

{

delay(1);

PWML-- ;   //调宽值低四位减1

if (PWML==0x00)

{

PWMH--;

}    //调宽值高四位减1

if (PWMH==0x00)

{

PWMH=0x01;

}   //最小值时

}

K2按键,减速按键,降低T1定时器计数起始时间,也就是增加T1计数时间,增加CLK=0的时间。

4、不论加速、减速,T0的时间都不变,CLK=0和CLK=1总持续时间不变{ (Tclk0+Tclk1)=T0 }。

程序不难,图不好画啊!

#include<reg52h>

sfr CCON =0xD8;

sfr CMOD =0xD9;

sfr CCAPM0 =0xDA;

sfr CCAPM1 =0xDB;

sfr CCAPM2 =0xDc;

sfr CCAPM3 =0xDd;

sfr CL =0xE9;

sfr CH =0xF9;

sfr CCAP0L =0xEA;

sfr CCAP0H =0xFA;

sfr CCAP1L =0xEb;

sfr CCAP1H =0xFb;

sfr CCAP2L =0xEc;

sfr CCAP2H =0xFc;

sfr CCAP3L =0xEd;

sfr CCAP3H =0xFd;

sbit CR =0xDE;

voidinit_pwm()

{

//定时器的来源CPS1,CPS0

CMOD=0x02;//Setup PCA timer

CL=0x00;

CH=0x00;

}

//控制占空比

voidpulse_0(unsigned char p_on)

{

CCAP0L=p_on;//Set the initial value same asCCAP0H

CCAP0H=p_on;//

//CCAPMn1使能脉宽调制模式,EC0M必须=1

CCAPM0=0x42;//0100,0010 Setup PCA module 0in PWM mode

}

voidpulse_1(unsigned char p_on)

{

CCAP1L=p_on;//Set the initial value same asCCAP0H

CCAP1H=p_on;//25% Duty Cycle

//CCAPMn1使能脉宽调制模式,EC0M必须=1

CCAPM1=0x42;//0100,0010 Setup PCA module 0in PWM mode

}

voidpulse_2(unsigned char p_on)

{

CCAP2L=p_on;//Set the initial value same asCCAP0H

CCAP2H=p_on;//25% Duty Cycle

//CCAPMn1使能脉宽调制模式,EC0M必须=1

CCAPM2=0x42;//0100,0010 Setup PCA module 0in PWM mode

}

voidpulse_3(unsigned char p_on)

{

CCAP3L=p_on;//Set the initial value same asCCAP0H

CCAP3H=p_on;//25% Duty Cycle

//CCAPMn1使能脉宽调制模式,EC0M必须=1

CCAPM3=0x42;//0100,0010 Setup PCA module 0in PWM mode

}

voiddelay(int a)

{

int i;

for(i=0;i<a;i++);

}

voidmain(void)

{

unsigned char i=0;

init_pwm();

CR=1; //Start PCA Timer

while(1)

{

while(++i)

{

pulse_0(i+50);

pulse_1(i+100);

pulse_2(i+150);

pulse_3(i+200);

delay(1000);

}

while(--i)

{

pulse_0(i+50);

pulse_1(i+100);

pulse_2(i+150);

pulse_3(i+200);

delay(1000);

}

}

}

以上就是关于关于PWM程序全部的内容,包括:关于PWM程序、单片机pwm调光程序、怎么51单片机定时器来模拟PWM波等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

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

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

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

发表评论

登录后才能评论

评论列表(0条)

保存