80C51定时/计数器的应用之实现PWM(脉冲宽度调制)

知识来源于链接:https://www.bilibili.com/video/BV1eT4y1J7wB/?spm_id_from=333.880.my_history.page.click&vd_source=b91967c499b23106586d7aa35af46413

这种模拟实现 PWM 波的应用只能应用于对波形精度和频率要求不高的情况下。

一、程序思路分析

这里想要产生一个 100 Hz 的正弦波,对应周期就是 1/100 = 0.01s = 10 ms = 10 000 us
80C51定时/计数器的应用之实现PWM(脉冲宽度调制)_第1张图片
把这段时间分为100份,其中,若前 20 份为高电平,后80份为低电平,就是占空比为 20%,若100份全为高电平,则占空比就为 100% 。因此,使用定时器定时为100 us ,每经过100us,就让 I/O 输出高电平或低电平,由此,可实现模拟 PWM 的输出。

80C51定时/计数器的应用之实现PWM(脉冲宽度调制)_第2张图片

二、程序源码

time.h

#ifndef _TIME_H_
#define _TIME_H_

#include <reg52.h>

sbit PWM = P1^0;
#define PWM_DUTY 50  // 50%

// 函数的声明
void Timer0_Init(void);		//1毫秒@11.0592MHz

#endif

time.c

#include "time.h"

unsigned char PWM_Cnt = 0;

void Timer0_Init(void)		//100微秒@12.000MHz
{
	TMOD &= 0xF0;			//设置定时器模式
	TMOD |= 0x01;			//设置定时器模式
	
	TL0 = 0x9C;				//设置定时初始值
	TH0 = 0xFF;				//设置定时初始值
	
	TF0 = 0;				//清除TF0标志
	ET0 = 1;
	EA = 1;
	TR0 = 1;				//定时器0开始计时
}

void timer_isr() interrupt 1
{
		TR0 = 0;				//定时器0开始计时
	
		PWM_Cnt++;
		if(PWM_Cnt >= 100)
		{
				PWM_Cnt = 0;
		}
		if(PWM_Cnt < PWM_DUTY)
		{
				PWM = 1;
		}
		else
		{
				PWM = 0;
		}
		
		TL0 = 0x9C;				//设置定时初始值
		TH0 = 0xFF;				//设置定时初始值

		TR0 = 1;				//定时器0开始计时
}	

main.c

#include <reg52.h>
#include "time.h"

void main()
{
		Timer0_Init();
		
		while(1);
}

通过修改 PWM_DUTY 的值,可改变占空比大小。

通过示波器观察波形,如下图所示

该占空比为 20%

该占空比为 0%

可以发现,程序中设定的频率为100,结果输出的频率只有 77 Hz,占空比也有1%左右的误差。

三、扩展程序源码(加入按键调节)

将宏定义修改为变量

unsigned char PWM_DUTY = 0;

80C51定时/计数器的应用之实现PWM(脉冲宽度调制)_第3张图片

你可能感兴趣的:(pwm,51单片机)