单片机PWM输出控制直流电机(89c51系列、stc12c5a60s2系列)

版权声明:版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Xiaomo_haa/article/details/84189798

目录

【pwm是如何控制电机转速】

【89C51系列单片机产生pwm波】

【STC12C5A60S2系列单片机输出PWM】


【pwm是如何控制电机转速】

在本科学习中,学生所做的小车多数为使用lm298n或者tb6612来驱动简单的直流电机,我们需要单片机输出pwm波来控制直流电机转速。

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

【89C51系列单片机产生pwm波】

89c51单片机没有自带pwm发生器,如果想要使用传统的51单片机产生pwm,只能通过软件模拟的方法来产生pwm。

软件模拟可以分为软件延时和定时器两种方法。

1、软件延时输出pwm

使用延时函数产生频率为1kHz的pwm方波(@12MHz晶振)

#include <reg52.h>

sbit pwm = P1^0;

void delay100us(unsigned int x)
{
	unsigned char i;
	while(--x)
	{
		i = 20;
		while (--i);
	}
}

int main(void)
{
	while(1)
	{
		pwm = 1;
		delay100us(6);
		pwm = 0;
		delay100us(4);
	}
}

proteus仿真结果

使用简单的延时函数即可简单地模拟出pwm波。但是这种方法缺点很明显,就是在输出pwm时占用大量机器周期,此时若进行其他操作时会影响pwm的准确度。所以这种方法我们很少使用。

2、定时器产生pwm

使用定时器的溢出中断,在中断服务程序中改变IO口的电平高低,可以在多操作情况下输出比较准确的pwm波形。

比如我们使用定时器0。

定时器工作模式:我们设置定时器0工作模式为方式1,16位自动重载模式,这样可以获得较宽的调频范围。

定时器中断:16位自动重载模式下最多可以记65536个数,一旦超出这个数值,便会进入中断。定时器初值可以使用定时器计算器计算,方便快捷。

使用定时器0产生占空比可调,频率为100Hz的pwm波。

#include <reg52.h>

sbit pwm = P1^0;

unsigned int PWM = 50;	//pwm占空比为50%,可调占空比
unsigned char time = 0;

void Time0Init(void)
{
	TMOD = 0X01;	//定时器工作在方式1(16位定时器)
	TH0 = 0XFF;		//12M晶振下定时0.01ms
	TL0 = 0X9c;
	ET0 = 1;			//开定时器1中断
	EA = 1;
	TR0 = 1;			//开启定时器
}

void Timer0(void) interrupt 1
{
	TH0 = 0XFF;		//重装初值
	TL0 = 0X9c;
	time++;
}

void main(void)
{
	Time0Init();
	while(1)
	{
		if(time >= 100)	//PWM周期为100*0.1ms
			time = 0;
		if(time < PWM)		
			pwm = 1;
		else if(time >= PWM)
			pwm = 0;
	}
}

proteus仿真结果

由仿真结果来看,所得波形还是不算很精准,实际应用过程中还会有很多误差,但是这样已经比延时函数产生pwm的结果可靠的多。

【STC12C5A60S2系列单片机输出PWM】

我在做循迹小车时使用的是stc12c5a60s2单片机。stc12c5a60s2单片机集成了两路可编程计数器阵列(PCA)模块,可用于软件定时器、外部脉冲的捕捉、高速输出以及脉宽调制(PWM)输出。

使用stc12c5a60s2单片机的PCA模块可通过程序设定,使其工作于8位PWM模式,通过P13和P14输出。

如下图所示:

PWM输出频率取决于PCA定时器的时钟源。

 由于所有模块共用仅有的PCA定时器,所以它们的输出频率相同。各个模块的输出占空比是独立变化的,与使用的捕获寄存器[EPCnL, CCAPnL]有关。当寄存器CL的值小于[EPCnL,CCAPnL]时,输出为低;当寄存器CL的值等于或大于[EPCnL, CCAPnL]时,输出为高。当CL的值由FF变为00溢出时,[EPCnH, CCAPnH]的内容装载到[EPCnL, CCAPnL]中。这样就可实现无干扰地更新PWM。要使能PWM模式,模块CCAPMn寄存器的PWMn和ECOMn位必须置位。

 PCA时钟输入源频率由于PWM是8位的,所以

PWM频率 = PCA时钟输入源频率 / 256

PCA时钟输入源可以从以下8种中选择一种: SYSclk,   SYSclk/2,  SYSclk/4,SYSclk/6,SYSclk/8,SYSclk/12, 定时器0的溢出,ECI/P3.4输入。

当某个I/O口作为PWM使用时,该口状态:

PWM之前口的状态 PWM输出时口的状态
弱上拉/准双向 强推挽输出/强上拉输出,要加输出限流电阻1K-10K
强推挽输出/强上拉输出 强推挽输出/强上拉输出,要加输出限流电阻1K-10K
仅为输入/高阻输入 PWM无效
开漏 开漏

------

#include "stc12c5a.h"

void PCA_Init(void)
{
	CCON = 0;				//PCA初始化
	CMOD = 0x00;			//空闲时不计数,不产生中断,时钟源为Sysclk/12,PWM频率大约为4KHz
	CL = 0x00;				//PCA低8位清零
	CH = 0x00;				//PCA高8位清零

	CCAPM0 = 0x42;			//8位PWM模式,无中断
	CCAP0H = 0xc0;			//PWM0占空比(调节此处值调节PWM占空比)
	CCAP0L = 0xc0;			//PWM0占空比(调节此处值调节PWM占空比)

	CCAPM1 = 0x42;			//8位PWM模式,无中断
	CCAP1H = 0x40;			//PWM1占空比(调节此处值调节PWM占空比)
	CCAP1L = 0x40;			//PWM1占空比(调节此处值调节PWM占空比)

	CR = 1;					//启动PCA计数器
}

/*PWM占空比设置*/
void PWM_Set(unsigned char x,unsigned char y)
{
  CCAP0H = y;				//设置比较值
  CCAP0L = y;	
  CCAP1H = x;				//设置比较值
  CCAP1L = x;
}

void main(void)
{
  P1M0 = 0xff;				//P1口推挽输出
  P1M1 = 0x00;
  PCA_Init();				//PCA初始化
  
  PWM_Set(0x80,0x80);       //设置占空比
}

此时产生的就是占空比为50%的PWM波。使用示波器可以在P13和P14口测得PWM输出波形。
 


 

猜你喜欢

转载自blog.csdn.net/Xiaomo_haa/article/details/84189798