定时器模拟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://pwwzsj.com/article/djpeej.html