小蜜蜂51单片机之PWM脉宽调制信号的发生与控制

关键词:PWM脉宽调制;占空比;用PWM和一个按键控制LED亮度;小蜜蜂

一、知识点

1.占空比;高电平在一个周期中占的比例

2.PWM占空比的应用:直流电机调速;LED亮度调节;舵机角度调节等

二、实验

实验目的:

实验思路:

1.用定时器实现脉宽信号的输出

2.按键实现4种状态的循环,状态的2个改变量:工作模式、PWM占空比

所需部件:

1.L1位声明+HC573锁存器打开LED的Y4信道

2.定时器0初始化函数,计算初值(频率100HZ,周期为10ms,即10000us将1个周期分为100us*100次,100us决定计数初值,100次决定中断服务函数中的计数次数,以PWM_duty为分界,以count==100为清零节点,区分L1亮灭以实现占空比,从而让LED有不同亮度)

3.定时器中断服务函数,调节PWM占空比

4.扫描S7按键+状态位stat+Delay消抖

实验现象:

L1最初灭,按下S7,L1有10%的亮度;再按一次,L1有50%的亮度;再按一次,L1有90%的亮度;再按一次,L1熄灭,如此循环往复

完整代码:

#include <REGX52.H>
sbit L1=P0^0;
sbit S7=P3^0;
//如果是独立按键,J5跳帽接到2,3引脚
//如果是矩阵键盘,J5跳帽接到1,2引脚

void SelectHC573()
{
	P2=(P2&0x1f)|0x80;
}

//*****************定时器相关
void Init_Timer0()
{
	TMOD=0x01;
	TH0=(65535-100)/256;
	TL0=(65535-100)%256;
	ET0=1;
	EA=1;
	TR0=0;//默认也是0,让定时器暂时不工作
}

unsigned char count=0;
unsigned char PWM_duty=0;
void ServiceTimer0() interrupt 1
{
	TH0=(65535-100)/256;
	TL0=(65535-100)%256;
	count++;
	if(count==PWM_duty)
	{
		L1=1;
	}
	else if(count==100)
	{
		L1=0;
		count=0;
	}
}

//****************************

//*****************独立按键相关
void DelayK(unsigned int t)
{
	while(t--);
}

unsigned char stat=0;
void ScanKeys()
{
	if(S7==0)
	{
		DelayK(100);
		if(S7==0)
		{
			switch(stat)
			{
				case 0:PWM_duty=10;L1=0;TR0=1;stat=1;break;
				case 1:PWM_duty=50;stat=2;break;
				case 2:PWM_duty=90;stat=3;break;
				case 3:L1=1;TR0=1;stat=0;break;
			}
			while(S7==0);
		}
	}
}
//********************************

void main()
{
	Init_Timer0();
	SelectHC573();
	L1=1;
	while(1)
	{
		ScanKeys();
	}
}

三、总结收获

1.J5跳帽随着独立键盘和矩阵键盘的不同而不同

//如果是独立按键,J5跳帽接到2,3引脚
//如果是矩阵键盘,J5跳帽接到1,2引脚

2.定时器0初始化函数,计算初值不同

①定时器处理脉冲占空比,将一个周期进行划分

②定时/计数器用作中断,是因为延时时间超出65.5ms,而进行分小凑大,eg.需延时500ms,将其分为50ms*10

3.占空比调节

思路:

因为题设L1亮度从0->...->90->0->...,所以不妨设一个周期里低电平在前,高电平在后。最初main函数里初始化L1=1;按下按键后,L1点亮,定时器开始计时,进行PWM脉宽调制(当count一到PWM_duty,L1灭,count一到100L1又亮,并清零count)

①简洁版:

unsigned char count=0;
unsigned char PWM_duty=0;
void ServiceTimer0() interrupt 1
{
	TH0=(65535-100)/256;
	TL0=(65535-100)%256;
	count++;
	if(count==PWM_duty)
	{
		L1=1;
	}
	else if(count==100)
	{
		L1=0;
		count=0;
	}
}

②清晰版:

unsigned char count=0;
unsigned char PWM_duty=0;
void ServiceTimer0() interrupt 1
{
	TH0=(65535-100)/256;
	TL0=(65535-100)%256;
	count++;
	if(count<=PWM_duty)
	{
		L1=0;
	}
	else if(count<100)
	{
		L1=1;
	}
    else
    {
        L1=0;
        count=0;
    {
}

 ③新思路(另一个实验)

清零和占空比分离,其中compare等效PWM_duty

void Timer0_Routine() interrupt 1
{
	
	TL0 = 0x9C;				
	TH0 = 0xFF;	
	Counter++;
	Counter%=100;//if(Counter>=100) Counter=0;同样的功能
	if(Counter<Compare) LED=0;
	else LED=1;
}

4.与PWM相关的按键控制中,需要调节:PWM_duty占空比设置、L1亮灭以及TR0(开始和结束时)、状态位

5.当只有一个按键调节多种状态时,可使用状态位进行切换(循环)

6.当出现按键不灵敏时,可在第二个if(S7==0)内加while(S7==0);空循环

unsigned char stat=0;
void ScanKeys()
{
	if(S7==0)
	{
		DelayK(100);
		if(S7==0)
		{
			switch(stat)
			{
				case 0:PWM_duty=10;L1=0;TR0=1;stat=1;break;
				case 1:PWM_duty=50;stat=2;break;
				case 2:PWM_duty=90;stat=3;break;
				case 3:L1=1;TR0=1;stat=0;break;
			}
			while(S7==0);
		}
	}
}

7.main函数中while内和外的语句设置

void main()
{
	Init_Timer0();
	SelectHC573();
	L1=1;
	while(1)
	{
		ScanKeys();
	}
}

四、联想拓展

1. 用4个键对应控制LED亮灭和直流电机转速

2.还可加上数码管显示

3.呼吸灯

详细参考:51单片机之LED呼吸灯&直流电机调速http://t.csdnimg.cn/3mGaZ

感谢B站小蜜蜂老师的教程,本笔记资料及代码均来自教程,仅作为个人复习、整理和学习交流用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值