定时器模拟PWM-创新互联

在51单片机中,是没有PWM这种外设的,其实PWM的原理很简单,就是将单片机的引脚按设定好的时间拉高拉低引脚。时间用定时器(T0,T1)就可以产生,高低电平只需要在定时器中断中拉高拉低就行。

创新互联总部坐落于成都市区,致力网站建设服务有网站制作、成都网站制作、网络营销策划、网页设计、网站维护、公众号搭建、微信小程序开发、软件开发等为企业提供一整套的信息化建设解决方案。创造真正意义上的网站建设,为互联网品牌在互动行销领域创造价值而不懈努力!

往往我们在写程序是都要开启定时器来作为程序定时功能,比如时间片;而为了让输出的波形更加标准,模拟PWM应该独享一个定时器,这样输出的波形才会更加的完美。

可以通过设置定时器重装载值来设置PWM的频率,那占空比如何设置?通过载中断中放置一个静态变量累加。例如:我要设置一个PWM周期为100ms的,占空比为30%的PWM波形,我需要设置定时器每次发生中断的时间为10ms,当静态变量i < 3, 相应的引脚输出0,当3<= i < 10,相应的引脚输出1.

#ifndef MID_PWM_H
#define MID_PWM_H
#include "reg52.h"
#include "c51_gpio.h"


typedef u16 PWM_Period;

typedef struct
{
	//绑定IO口,用于快速开关PWM
	unsigned char PWM_State;
	GPIO_TypeDef GPIOx;
	GPIO_PinNum_t GPIO_Pin;
 
	//设置占空比和一个周期的时间
	u16 Dievdend;//分子
	u16 Divsor;//分母
	
	u8  record_time_flag;
	PWM_Period	time;//毫秒级
	u16 old_time;
}PWM_TypeDef;

void PWM_set_and_start(PWM_TypeDef* PWM_InitStructure);
void PWM_OnOff(PWM_TypeDef* PWM_InitStructure, u8 state);
void PWM_Modify_PWM_Period(PWM_TypeDef* PWM_InitStructure, PWM_Period time);
void PWM_Modify_DutyCycle(PWM_TypeDef* PWM_InitStructure, unsigned char Dievdend, unsigned char Divsor);
void PWM_set(void);
#endif
#include "mid_pwm.h"
#include "bsp_uart.h"
#include "bsp_time0.h"

extern u16 time_count;


void PWM_set_and_start(PWM_TypeDef* PWM_InitStructure)
{
	u16 temp = 0;
	u16 DutyCycle_time = PWM_InitStructure->time / PWM_InitStructure->Divsor * PWM_InitStructure->Dievdend;
	if(PWM_InitStructure->PWM_State == 0)
	{
 
		if(PWM_InitStructure->record_time_flag == 0)
		{
			PWM_InitStructure->record_time_flag = 1;
			PWM_InitStructure->old_time = time_count;
		}
		else
		{
			if(PWM_InitStructure->old_time< time_count)
			{
				temp = time_count - PWM_InitStructure->old_time;
			}
			else
			{
				temp = 0xFFFF - PWM_InitStructure->old_time + time_count;
			}
			
			if(temp >= 0 && temp< DutyCycle_time)
			{
				GPIO_Write(PWM_InitStructure->GPIOx, PWM_InitStructure->GPIO_Pin, Bit_RESET);
//				bsp_uart_send_data(0xA1);
//				delay_us(40000);
			}
			else if(temp< PWM_InitStructure->time && temp >= DutyCycle_time)
			{
				GPIO_Write(PWM_InitStructure->GPIOx, PWM_InitStructure->GPIO_Pin, Bit_SET);
//				bsp_uart_send_data(0xB1);
//				delay_us(40000);
			}
			else if(temp >= PWM_InitStructure->time)
			{
				PWM_InitStructure->record_time_flag = 0;
//				bsp_uart_send_data(0xC1);
//				delay_us(40000);
				
			}
		}
	}
}
void PWM_OnOff(PWM_TypeDef* PWM_InitStructure, u8 state)
{
	PWM_InitStructure->PWM_State = state;
}
void PWM_Modify_PWM_Period(PWM_TypeDef* PWM_InitStructure, PWM_Period time)
{
	PWM_InitStructure->time = time;
}
void PWM_Modify_DutyCycle(PWM_TypeDef* PWM_InitStructure, unsigned char Dievdend, unsigned char Divsor)
{
	PWM_InitStructure->Dievdend = Dievdend;
	PWM_InitStructure->Divsor = Divsor;
}
通过模拟的PWM控制直流无刷电机 

本来想着说将PWM1这个变量声明成code类型,然而悲催的是,其不能用指针来访问,然后想了一下,这个变量是在flash中,而指针的概念是存在内存中的,因此访问会有问题 

#include "app_motor.h"

PWM_TypeDef PWM1 =
{
	0,
	P_0,
	GPIO_Pin_1,
	15,
	80,
	
	0,
	800,
	0
};
void app_set_motor_speed(void)
{
	GPIO_Write(P_0, GPIO_Pin_0, 1);//控制H桥一直导通
	PWM_set_and_start(&PWM1);//PWM控制另外一个通路,这样就能控制速度了
}

在写的过程中,我发现51单片机是真的慢,写个中断回调和直接用变量time_count++计数时间差别巨大.

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


网页名称:定时器模拟PWM-创新互联
标题来源:http://scyanting.com/article/djpeej.html