当前位置: 首页 > article >正文

05:定时器生成频率不同的波形

定时器生成频率不同的波形

  • 1、蜂鸣器的使用
  • 2、PWM波形
    • 2.1、占空比
    • 2.2、平均电压
    • 2.3、实验

1、蜂鸣器的使用

实验:通过定时器生成不同的波形,让蜂鸣器发出叮咚的声音

在700Hz的电平信号下,蜂鸣器发出叮的声响,在500Hz的电平信号下,蜂鸣器发出咚的声响
700Hz的电平信号的周期T ≈ 1.42ms,500Hz的电平信号周期T = 2ms

在这里插入图片描述
综上:需要产生700Hz的电平信号,即每隔0.71ms电平翻转一次即可。需要产生500Hz的电平信号,即每隔1ms电平翻转一次即可。

将定时器T0的定时为100us,则定时到了10次后让电平翻转,则就产生了周期为2ms的电平
①Time.c文件的代码如下:

#include "Time.h"

sbit GPIO1_0 = P1^0;

/**
 * 定时器T0的初始化,且开启中断
 */
void Time0It_Init(void)
{
	/* 设置T0的计数器为16,且时钟来源为晶振 TMOD = xxxx 0001 */
	TMOD &= 0xF0;			//将低4位置0
	TMOD |= 0x01;			//最低位置1
	
	/* 设置定时计数器的初始值 */
//	TH0 = ((65536 - 100) >> 8);
//	TL0 = (65536 - 100) & 0x00FF;	//定时100us
//	TH0 = ((65536 - 250) >> 8);
//	TL0 = (65536 - 250) & 0x00FF;	//定时250us
	TH0 = ((65536 - 500) >> 8);
	TL0 = (65536 - 500) & 0x00FF;	//定时500us
	
	/* 启动T0 */
	TF0 = 0;				//清除标志位
	TR0 = 1;
	
	/* 开启中断 */
	ET0 = 1;				//使能定时器溢出中断
	EA = 1;					//开启总开关
}

/********中断服务函数*******/
/**
 * T0的中断服务函数
 */
static unsigned int Period2ms = 0;
void Time0_Rountine(void) interrupt 1
{	
	//这里不用清除标志位,硬件会自动清除
//	TH0 = ((65536 - 100) >> 8);
//	TL0 = (65536 - 100) & 0x00FF;	//定时100us
//	TH0 = ((65536 - 250) >> 8);
//	TL0 = (65536 - 250) & 0x00FF;	//定时250us
	TH0 = ((65536 - 500) >> 8);
	TL0 = (65536 - 500) & 0x00FF;	//定时500us
	
	Period2ms++;				//定时时间到执行+1
	if(Period2ms == 2)			//定时1ms到了
	{
		GPIO1_0 = ~GPIO1_0;		//让电平翻转
		Count10 = 0;
	}
}

②main.c文件的代码如下:

#include "Time.h"

void main(void)
{
	Time0It_Init();
	while(1)
	{

	}
}

在这里插入图片描述综上:定时周期越小,误差就越大

同理:将定时器T0的定时为100us,定时到了7.1次后让电平翻转,则就产生周期为1.42ms的电平

实验:通过定时器生成不同700Hz和500Hz的电平信号,信号都分别持续5ms
①Time.c文件的代码如下:

#include "Time.h"

sbit GPIO1_0 = P1^0;

/**
 * 定时器T0的初始化,且开启中断
 */
void Time0It_Init(void)
{
	/* 设置T0的计数器为16,且时钟来源为晶振 TMOD = xxxx 0001 */
	TMOD &= 0xF0;			//将低4位置0
	TMOD |= 0x01;			//最低位置1
	
	/* 设置定时计数器的初始值,定时100us */
	TH0 = ((65536 - 100) >> 8);
	TL0 = (65536 - 100) & 0x00FF;
	
	/* 启动T0 */
	TF0 = 0;				//清除标志位
	TR0 = 1;
	
	/* 开启中断 */
	ET0 = 1;				//使能定时器溢出中断
	EA = 1;					//开启总开关
}

/********中断服务函数*******/
/**
 * T0的中断服务函数
 */
static unsigned int Period = 0;
static unsigned int Count = 0;
static unsigned int Flag = 0;
void Time0_Rountine(void) interrupt 1
{	
	//这里不用清除标志位,硬件会自动清除
	TH0 = ((65536 - 100) >> 8);
	TL0 = (65536 - 100) & 0x00FF;
	
	Count++;
	Period++;			//每隔0.1ms执行+1
	
	if(Count == 50)		//5ms到了
	{
		Count = 0;
		Flag = !Flag;	//改变状态
	}
	switch(Flag)
	{
		case 0:							//
			if(Period == 10)			//定时1ms到了
			{
				GPIO1_0 = ~GPIO1_0;		//让电平翻转
				Period = 0;
			}
			break;
		case 1:
			if(Period == 7)				//定时0.7ms到了
			{
				GPIO1_0 = ~GPIO1_0;		//让电平翻转
				Period = 0;
			}
			break;
		default:break;
	}	
}

②main.c文件的代码如下:

#include "Time.h"

void main(void)
{
	Time0It_Init();
	while(1)
	{

	}
}

在这里插入图片描述综上:使用51单片机的定时器生成不同频率的波形存在太大的误差

2、PWM波形

下图是一张典型的pwm波形图,信号从高电平>>低电平>>高电平,称为一个脉冲周期T。
在这里插入图片描述

而1s内经历的周期数称为频率 f(HZ),f=1/T。例如周期为0.02s,频率就是50HZ

2.1、占空比

    一个脉冲周期内高电平维持时间在整个周期中所占的比值

    例如:一个脉冲周期为10ms的pwm波形图,第一个周期高电平为7ms(占空比70%);第二个周期高电平为4ms(占空比40%)

在这里插入图片描述

2.2、平均电压

假设高电平为5V,根据"面积等效原理
第一个周期平均电压为5V×70%=3.5V
第二个周期平均电压为5V×40%=2V

在这里插入图片描述

2.3、实验

实验:
使用定时器T0生成一个频率为50Hz,占空比为70%的信号。

频率为50Hz,则周期T = 20ms,而占空比为70%,则信号的高电平持续时间t = 14ms,信号的低电平持续时间t = 6ms。
将定时器T0的周期时间设置为1ms即可
在这里插入图片描述

①Time.c文件的代码如下:

#include "Time.h"

sbit GPIO1_0 = P1^0;

/**
 * 定时器T0的初始化,且开启中断
 */
void Time0It_Init(void)
{
	/* 设置T0的计数器为16,且时钟来源为晶振 TMOD = xxxx 0001 */
	TMOD &= 0xF0;			//将低4位置0
	TMOD |= 0x01;			//最低位置1
	
	/* 设置定时计数器的初始值,定时1ms */
	TH0 = ((65536 - 1000) >> 8);
	TL0 = (65536 - 1000) & 0x00FF;

	/* 启动T0 */
	TF0 = 0;				//清除标志位
	TR0 = 1;
	
	/* 开启中断 */
	ET0 = 1;				//使能定时器溢出中断
	EA = 1;					//开启总开关
}

/********中断服务函数*******/
/**
 * T0的中断服务函数
 */
static unsigned int PWM_Cnt = 0;
void Time0_Rountine(void) interrupt 1
{	
	//这里不用清除标志位,硬件会自动清除
	TH0 = ((65536 - 1000) >> 8);
	TL0 = (65536 - 1000) & 0x00FF;
	
	PWM_Cnt++;			//每隔1ms执行+1
	if(PWM_Cnt == 20)	//20ms到了
	{
		PWM_Cnt = 0;
	}
	if(PWM_Cnt < 14)	//14ms还没有到
	{
		GPIO1_0 = 1;	//输出高电平
	}
	if(PWM_Cnt >= 14)	//14ms到了
	{
		GPIO1_0 = 0;	//变为低电平
	}
}

②main.c文件的代码如下:

#include "Time.h"

void main(void)
{
	Time0It_Init();
	while(1)
	{

	}
}

在这里插入图片描述

改进代码如下:
①Time.c文件的代码如下:

#include "Time.h"

sbit GPIO1_0 = P1^0;

/**
 * 定时器T0的初始化,且开启中断
 */
void Time0It_Init(void)
{
	/* 设置T0的计数器为16,且时钟来源为晶振 TMOD = xxxx 0001 */
	TMOD &= 0xF0;			//将低4位置0
	TMOD |= 0x01;			//最低位置1
	
	/* 设置定时计数器的初始值,定时1ms */
	TH0 = ((65536 - 1000) >> 8);
	TL0 = (65536 - 1000) & 0x00FF;

	/* 启动T0 */
	TF0 = 0;				//清除标志位
	TR0 = 1;
	
	/* 开启中断 */
	ET0 = 1;				//使能定时器溢出中断
	EA = 1;					//开启总开关
}


/********中断服务函数*******/
/**
 * T0的中断服务函数
 */
static unsigned int PWM_Cnt = 0;
void Time0_Rountine(void) interrupt 1
{	
	//这里不用清除标志位,硬件会自动清除
	TH0 = ((65536 - 1000) >> 8);
	TL0 = (65536 - 1000) & 0x00FF;
	
	PWM_Cnt++;			//每隔1ms执行+1
	if(PWM_Cnt == Period)//周期到了
	{
		PWM_Cnt = 0;
	}
	if(PWM_Cnt < (Period * PWM_Duty)/100)
	{
		GPIO1_0 = 1;	//输出高电平
	}
	if(PWM_Cnt >= (Period * PWM_Duty)/100)	
	{
		GPIO1_0 = 0;	//变为低电平
	}
}

②Time.h文件的代码如下:

#ifndef __Time_H
#define __Time_H
#include <reg51.h>		//包含51头文件,里面全是寄存器地址>

//使用宏定义占空比,方便修改
/* 宏定义周期T = 20ms*/
#define Period 20
/* 占空比70% */
#define PWM_Duty 70

sbit GPIO1_0 = P1^0;

void Time0It_Init(void);

#endif

③main.c文件的代码如下:

#include "Time.h"

void main(void)
{
	Time0It_Init();
	while(1)
	{

	}
}

在这里插入图片描述


http://www.kler.cn/a/542032.html

相关文章:

  • ArgoCD实战指南:GitOps驱动下的Kubernetes自动化部署与Helm/Kustomize集成
  • 采用分步式无线控制架构实现水池液位自动化管理
  • 详解SQLAlchemy的函数relationship
  • CANoe工具使用技巧 --- 如何使用 “on ethernetPacket “事件处理程序
  • 鸿蒙接入支付宝SDK后模拟器无法运行,报错error: install parse native so failed.
  • 【嵌入式 Linux 音视频+ AI 实战项目】瑞芯微 Rockchip 系列 RK3588-基于深度学习的人脸门禁+ IPC 智能安防监控系统
  • Rocketmq 和 Rabbitmq ,在多消费者的情况下,可以实现顺序消费吗
  • 使用腾讯云大模型知识引擎搭建满血deepseek
  • arcgis for js实现层叠立体效果
  • C++ 用Eigen的非线性求解LevenbergMarquardt,亲测ok
  • Python 透明数字时钟
  • 独立站赋能反向海淘:跨境代购系统的用户体验与支付解决方案
  • 2025.2.10 每日学习记录3:技术报告只差相关工作+补实验
  • 在npm上传属于自己的包
  • 【RabbitMQ的x-death头】消息死亡记录头流转示例
  • 攻防世界32 very_easy_sql【SSRF/SQL时间盲注】
  • android的第一个app项目(java版)
  • C++ Primer 简单语句
  • webpack配置之---output.publicPath
  • 【机器学习】 特征归一化的重要性及方式
  • 【Day37 LeetCode】动态规划DP Ⅹ 子序列问题
  • centos 8和centos 9 stream x64的区别
  • 寒假集训思维训练5题解
  • VSCode|IDEA|PyCharm接入DeepSeek R1
  • 【数据结构-Tire树】力扣1268. 搜索推荐系统
  • 如何在本地部署deepseek?