智能车制作

标题: 怎么用51 单片机产生pwm [打印本页]

作者: uestcahui    时间: 2010-10-24 11:45
标题: 怎么用51 单片机产生pwm
要做巡线小车,用51单片机通L298驱动直流电机,需要用51产生pwm?
作者: zouyf12    时间: 2010-10-24 20:55
两种方法,
第一种是查询法,用一个变量保存PWM占空比数值,然后程序不停查询定时器的计数值,与之前的变量相比,相等以后就把相应的PWM引脚值置0,等定时器溢出中断时,再把引脚置1,这样调整变量就可以改变PWM占空比了。 这种方法,原理就是一般硬件PWM发生器的原理,只不过用软件来实现了。
第二种是中断法,就是先在定时器里装入一个值,等溢出中断以后,翻转PWM引脚,再装入另一个计数值,这样就可以产生PWM波,通过调节两个值的大小就可以改变PWM波的占空比和周期。不过,改变占空比时,需要计算出两个计数值。
另外,STC的51单片机有很多都有PWM模块了,可以使用那些单片机,比较方便。
作者: uestcahui    时间: 2010-10-24 21:46
回复 2# zouyf12


    谢谢哈
作者: a371274316    时间: 2010-11-4 18:37
受教咯
作者: oooooo    时间: 2012-3-25 21:58
谢谢
作者: lllddh    时间: 2013-6-15 17:33
有用:lol
作者: Legends    时间: 2013-6-16 00:55
//数度值:go/back(0~200,0~200)
#include <at89x51.h>
#define uchar unsigned char
#define uint unsigned int
void motor_r_z(void);//右边电动机正转
void motor_l_z(void);//左边电动机正转
void motor_r_f(void);//右边电动机反转
void motor_l_f(void);//左边电动机反转
void back(uchar,uchar); //小车后退
void go(uchar,uchar);//小车前进
void stop(void);//小车停止
void left(void);//小车左转
void right(void);//小车右转


sbit PWM1=P2^0;
sbit PWM2=P2^2;
sbit PWM3=P2^3;
sbit PWM4=P2^5;
sbit EN1=P2^1;
sbit EN2=P2^4;

sbit left_k=P0^6;
sbit right_k=P0^7;
sbit start_k=P3^2;
sbit stop_k=P3^3;

sbit sound=P2^7;

uchar data t_0;
uchar data motor_r;
uchar data motor_l;
uchar data Value;
uchar data mid;

//**延时子程序**///
void delay_1ms(uint n)
{
        uint i,j;
        for(j=n;j>0;j--)
        for(i=20;i>0;i--);
}

void ini(void)
{
////T0初始化///
TMOD=0x01; //T0工作在方式1
TH0=0xff; //装入T0初值
TL0=0xf6;
TR0=1;//开T0中断
ET0=1;//T0允许中断
EA=1;
//////////////////////
t_0=0;
/////////////////////
P2=0;
sound=1;
}
void Sound(void)
{
///蜂鸣器响///
sound=0;
delay_1ms(30);
sound=1;
}
void start(void)
{
   uchar a;
   aa:
   while(start_k);
   for(a=0;a<50;a++)
   {
   delay_1ms(1);
   while(start_k)
   goto aa;
   }
   Sound();
   back(150,150);
}
void go(uchar left_motor,uchar right_motor)//直行(右,左)
{
Value=right_motor;
motor_r_z();
Value=left_motor;
motor_l_z();
}
void back(uchar left_motor,uchar right_motor)//直行(右,左)
{
Value=right_motor;
motor_r_f();
Value=left_motor;
motor_l_f();
}
void motor_r_z(void)//右边电动机正转
{
  motor_r=200-Value;
  PWM2=1;
  EN1=1;
}
void motor_l_z(void)//左边电动机正转
{
  motor_l=200-Value;
  PWM4=1;
  EN2=1;
}
void motor_r_f(void)//右边电动机反转
{
  motor_r=Value;
  PWM2=0;
  EN1=1;
}
void motor_l_f(void)//左边电动机反转
{
  motor_l=Value;
  PWM4=0;
  EN2=1;
}

void stop(void)
{
EN2=0;
EN1=0;
}
void time0(void) interrupt 1 using 2
{
TR0=0;
TH0=0xff;
TL0=0xf6;
++t_0;
ACC=t_0;
CY=0;
ACC-=motor_r;
if(CY==1)
{
PWM1=1;
goto PWM_2;
}
PWM1=0;
PWM_2:
ACC=t_0;
CY=0;
ACC-=motor_l;
if(CY==1)
{
PWM3=1;
goto HIGHT;
}
PWM3=0;
HIGHT:
ACC=t_0;
if(ACC!=0xc9)
goto EXIT;
ACC=0;
t_0=ACC;
EXIT:
TR0=1;
}  
void main(void)
{
uchar a;
ini();
start();
while(1)
{
         go(100,100);

}
}
作者: --鳞--    时间: 2013-7-21 19:00
kankan

作者: 愤怒的小丽丽    时间: 2013-8-31 17:01
第二种是中断法,就是先在定时器里装入一个值,等溢出中断以后,翻转PWM引脚,再装入另一个计数值,这样就可以产生PWM波,通过调节两个值的大小就可以改变PWM波的占空比和周期。不过,改变占空比时,需要计算出两个计数值。
另外,STC的51单片机有很多都有PWM模块了,可以使用那些单片机,比较方便。

#include<AT89X51.H>
#define Moto1 P2_0 //驱动电机信号的输出端口
#define Moto2 P2_1
#define Duoj P2_4 //舵机信号的输出端口
unsigned char D_count,D_num;
unsigned char M_count,M_num;
void main()
{
Moto1=1;
P2_2=0;
Duoj=1;
TMOD=0x11; //Timer0 和Timer1 同时配置为模式1,16 位计数模式
TH0=(65536-40)/256; //定时器初值设置
TL0=(65536-40)%256; //
TH1=(65536-2000)/256;
TL1=(65536-2000)%256;
TR0=1; //允许定时器0 计数
ET0=1; //允许定时器0 溢出中断
TR1=1;
ET1=1;
EA=1; //开启总中断
第四章 程序设计
-20-
D_num=25;
while(1)
{
}
}
void t0()interrupt 1
{
D_count++;
if(D_count==D_num)
Duoj=0;
if(D_count==250)
{
D_count=0;
Duoj=1;
}
TH0=(65536-40)/256; //重装初值
TL0=(65536-40)%256;
}
void t1()interrupt 3
{
M_count++;
if(M_count==M_num)
{
Moto2=1;
}
if(M_count==5)
{
M_count=0;
Moto2=0;
}
TH1=(65536-2000)/256;
TL1=(65536-2000)%256;
}




欢迎光临 智能车制作 (http://dns.znczz.com/) Powered by Discuz! X3.2