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波等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)