PWM脉冲宽度调制—呼吸灯以及蜂鸣器奏乐应用

目录

序言

PWM

PWM函数

代码

代码细节部分解读

应用

呼吸灯

蜂鸣器奏乐

总结


序言

本文主要讲解pwm的具体(基础)使用,并未诠释pwm的核心概念,并使用更快的定时器初始值计算方法,讲解了常见计算精度上的一些小处理。


PWM

pwm脉冲示例图

PWM函数

代码

要输入两个变量分别为:周期占控比给pwm函数

void pwm_config( unsigned int T, unsigned char Ratio)
{
	unsigned int HighVoltTime,LowVoltTime; 
	long int temp;

    //计算定时器初始值
	temp=(long int)T*Ratio;
    HighVoltTime=temp/100;
	LowVoltTime=T-HighVoltTime;

    TH0_LowVolt=(65536-LowVoltTime)>>8;
	TL0_LowVolt=65536-LowVoltTime;
	TH0_HighVolt=(65536-HighVoltTime)>>8;
	TL0_HighVolt=65536-HighVoltTime;
}

代码细节部分解读

首先是进行定时器初始值的计算,周期×占控比得到高八位的定时器的值,再用周期减去高八位持续的时间即可得到低八位的定时器的数值。

小细节操作

  • 高八位的配置:

        原始

TH0=(65535-LowVoltTime)/256

        升级

TH0_LowVolt=(65536-LowVoltTime)>>8

在计算机的加减乘除运算之中,除法运算最慢,使用位操作符来替换除法,加快运算效率,减少计算时间

  • 低八位的配置:

        原始

TL0=(65535-HighVoltTime)%256

        升级

TL0_LowVolt=65536-LowVoltTime

这是因为c语言在运算超出数据类型的范围时,默认保留低八位,利用这个特性可以省去一步取余计算。基于数据存储形式优化计算速度

  • 初始值计算

周期还是使用的微秒作为单位,在计算过程之中会面临数值过大的问题

倘若使用以下操作进行计算,会出现精度损失的问题

HighVoltTime=T/100*Ratio

所以选择调换计算顺序,并使用更大的数据类型来解决精度损失的问题(要注意数据类型转换)

	long int temp;
	temp=(long int)T*Ratio;
    HighVoltTime=temp/100;
  • PWM函数内完成初始值的计算

目的是不在中断之中运算,加快运算速度,减少cpu损耗,中断之中仅进行赋值操作

应用

呼吸灯调的是占控比,体现灯亮度的变换

蜂鸣器调的是周期,通过调整周期使得频率不一样,发出的声音也不一样(这里用的是无源蜂鸣器,此蜂鸣器一般配合按键一起食用)

呼吸灯

小细节操作

  • 占控比为10%和90%的灯都是亮的,按原理上来说,占控比低的更亮(在我的程序之中,占控比越高,高电平占比越高),但实际上人眼可能感受不出来,因为分辨率不够

代码

#include<reg51.h>
sbit led=P2^0;
unsigned int code beattime[7]={261,293,329,349,393,440,493};//音律的频率
unsigned int code SongCode[7]={3822,3406,3034,2864,2551,2272,2025}; //音律的周期
unsigned char code R[8]={10,30,50,70,90,70,50,30};//呼吸灯占控比
unsigned char TH0_LowVolt;
unsigned char TL0_LowVolt;
unsigned char TH0_HighVolt;
unsigned char TL0_HighVolt;
void pwm_config( unsigned int T, unsigned char Ratio)
{
	unsigned int HighVoltTime,LowVoltTime; 
	long int temp;
	
	//计算定时器的初始值
	temp=(long int)T*Ratio;
  HighVoltTime=temp/100;
	LowVoltTime=T-HighVoltTime;
	
	//完成赋值操作
  TH0_LowVolt=(65536-LowVoltTime)>>8;
	TL0_LowVolt=65536-LowVoltTime;
	TH0_HighVolt=(65536-HighVoltTime)>>8;
	TL0_HighVolt=65536-HighVoltTime;
}
void timer_config()
{
  EA=1;
	ET0=1;
	TR0=1;
	TMOD=0x01;
	TH0=(65536-8000)>>8;
	TL0=65536-8000;
}
void main()
{
	timer_config();
	pwm_config(10000,R[]);
  while(1)
	{
	
	}
}
void timer_5ms() interrupt 1
{
	static unsigned int count=0,j=0;
	count++;
	if(count==200) //1 sec
	{
		count=0;
		j++;
		j=j%7;
	  pwm_config(10000,R[]);
	}
	//通过前一个状态决定不同的定时器初始值的配置
	if(led)
	{
		TH0=TH0_LowVolt;
		TL0=TL0_LowVolt;
	}
	else
	{
	  TH0=TH0_HighVolt;
		TL0=TL0_HighVolt;
	}
	P2=~P2;
}

蜂鸣器奏乐

小细节操作

  • 倘若要蜂鸣器响1s,大概只要设置0.8秒就可以了,考虑到声音的传播,并且使得两个节拍之间的衔接更加柔和,也不容易出现两个节拍重叠发声的情况(具体时间得根据不同场景进行调整)
  • 蜂鸣器的音质差,因为输入给蜂鸣器的是方波信号,一般声音是很复杂的波形,单单使用一个I/O口无法实现复杂波形的输入(有点复杂)
  • 蜂鸣器是否好听取决于各音调“比例”恰不恰当,只要比例合适,不管是“哪个人唱”,别人都会觉得好听,和谐
  • 通过不同的声音频率,来计算出对应声音要持续的周期长度,进而发出不同的声音

代码

#include<reg51.h>
sbit led=P2^0;
unsigned int code beattime[7]={261,293,329,349,393,440,493};//音律的频率
unsigned int code SongCode[7]={3822,3406,3034,2864,2551,2272,2025}; //音律的周期
unsigned char code R[8]={10,30,50,70,90,70,50,30};//呼吸灯占控比
unsigned char TH0_LowVolt;
unsigned char TL0_LowVolt;
unsigned char TH0_HighVolt;
unsigned char TL0_HighVolt;
void pwm_config( unsigned int T, unsigned char Ratio)
{
	unsigned int HighVoltTime,LowVoltTime; 
	long int temp;
	
	//计算定时器的初始值
	temp=(long int)T*Ratio;
    HighVoltTime=temp/100;
	LowVoltTime=T-HighVoltTime;
	
	//完成赋值操作
    TH0_LowVolt=(65536-LowVoltTime)>>8;
	TL0_LowVolt=65536-LowVoltTime;
	TH0_HighVolt=(65536-HighVoltTime)>>8;
	TL0_HighVolt=65536-HighVoltTime;
}
void timer_config()
{
 EA=1;
	ET0=1;
	TR0=1;
	TMOD=0x01;
	TH0=(65536-8000)>>8;
	TL0=65536-8000;
}
void main()
{
	timer_config();
	pwm_config(SongCode[0],50);
  while(1)
	{
	
	}
}
void timer_5ms() interrupt 1
{
	static unsigned int count=0,j=0;
	count++;
	if(count==beattime[j]) //0.5 sec
	{
		count=0;
		j++;
		j=j%7;
	    pwm_config(SongCode[j],50);
	}
	//通过前一个状态决定不同的定时器初始值的配置
	if(led)
	{
		TH0=TH0_LowVolt;
		TL0=TL0_LowVolt;
	}
	else
	{
	    TH0=TH0_HighVolt;
		TL0=TL0_HighVolt;
	}
	P2=~P2;
}

总结

pwm的应用有很多,更多的应用是在于电机和舵机的控制

pwm的理解:

PWM就是在合适的信号频率下,通过一个周期里改变占空比的方式来改变输出的有效电压

  • 19
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值