蓝桥杯单片机快速开发笔记——PWM

一、原理分析

        使用定时器输出PWM(脉宽调制)信号是通过微控制器的定时器模块来生成一种周期性的脉冲信号,通过控制脉冲的高电平时间(占空比)来控制输出信号的平均功率。以下是生成PWM信号的基本原理概述:

  1. 定时器工作原理

    • 定时器是微控制器中的一个功能模块,用于产生精确的时间延时或周期性的计时功能。
    • 定时器通常由一个计数器和一个时钟源组成,计数器根据时钟源的脉冲信号进行计数,当计数器的值达到设定的初值时,产生中断或者触发特定的事件。
  2. PWM信号生成原理

    • 在生成PWM信号时,定时器被配置为工作在定时器/计数器模式,计数器从一个初始值开始计数,当计数器的值达到设定的比较值时,产生一个输出比较中断。
    • 通过调整比较值和定时器的初值,可以控制PWM信号的周期和占空比。PWM信号的周期由定时器的溢出周期决定,而占空比则由比较值和初值的关系决定。
  3. 控制占空比

    • 要控制PWM信号的占空比,可以通过调整比较值来实现。占空比定义为高电平时间与周期的比值,通过改变比较值的大小,可以改变高电平的持续时间,从而改变占空比。
    • 通过定时器中断服务函数中的逻辑,根据计数器的值和比较值的关系来控制输出信号的高低电平状态,实现PWM信号的输出。
  4. 应用领域

    • PWM信号广泛应用于电机控制、LED亮度调节、音频处理等领域,通过调节占空比可以实现对输出信号的精确控制。

二、思维导图

三、示例代码

    基于定时器0的PWM控制功能,通过按键S7来调节LED L1的亮度。

sbit s7 = P3^0;
sbit L1 = P0^0;

unsigned char count = 0;
unsigned char pwm = 0;
unsigned char stat = 0;


//初始化定时器0
void Init_timer0()
{
	TH0 = (65536 - 100) / 256;
	TL0 = (65536 - 100) % 256;
	TMOD = 0x01;
	ET0 = 1;
	EA = 1;
}

void service_timer0() interrupt 1
{
	TH0 = (65536 - 100) / 256;
	TL0 = (65536 - 100) % 256;
	
	count++;
	if(count == pwm)
	{
		L1 = 1;
	}
	else if (count >= 100)
	{
		L1 = 0;
		count = 0;
	}
}

void scan_key()
{
	
	if(s7 == 0)
	{
		delay_key(100);
		if(s7 == 0)
		{
				switch(stat)
			 {
				case 0:
					L1 = 0;
				  TR0 = 1;
					pwm = 10;
					stat = 1;
				break;
				
				case 1:
					pwm = 50;
					stat = 2;
				break;
				
				case 2:
					pwm = 90;
					stat = 3;
				break;
				
				case 3:
					L1 = 1;
					TR0 = 0;
					stat = 0;
				break;
			}
			while(s7 == 0);
		}
	}
}


void main()
{
    P2 = (P2 & 0x1f) | 0x80;
    L1 = 1;
    Init_timer0()
    while(1)
    {
        scan_key();
    }
}

        实现基于定时器0的PWM(脉宽调制)控制功能,通过按键S7来控制PWM的占空比。解释一下代码的主要功能和实现思路:

  1. 定义了一个位控制变量sbit,用于表示P3口的第0位引脚,对应按键S7;另外定义了一个位控制变量sbit,用于表示P0口的第0位引脚,对应LED L1。同时定义了三个全局变量countpwmstat,分别用于计数、存储PWM值和状态控制。

  2. Init_timer0()函数用于初始化定时器0,设置定时器初值为65536 - 100,工作模式为方式1(16位定时器),开启定时器0中断,并开启总中断。

  3. service_timer0()函数是定时器0的中断服务函数,每次定时器0溢出时会执行该函数。在函数中,重新设置定时器0的初值,然后根据计数值count和PWM值pwm控制LED L1的亮灭状态,实现PWM控制。

  4. scan_key()函数用于扫描按键S7的状态,并根据按键的按下情况和当前状态进行PWM占空比的调节。具体实现包括延时检测按键稳定按下、根据状态控制PWM值和LED L1的状态,并在按键释放后更新状态。

  5. main()函数中首先配置P2口的引脚,然后初始化定时器0,将LED L1初始设为亮,进入主循环中不断扫描按键状态并进行PWM控制。

四、特别注意!!!

        如果把上述代码中所有的 TH0 = (65536 - 100) / 256; TL0 = (65536 - 100) % 256; 换成 TH0 = (0 - 100) / 256; TL0 = (0 - 100) % 256; 后LED L1就会闪烁。

        

        当将定时器0的初值设置为(0 - 100)时,会导致LED L1闪烁的原因在于定时器0的初值为负数,这可能会导致定时器计数出现异常情况,从而影响了PWM控制的稳定性。可能的原因:

  1. 负数初值问题:在定时器0的工作中,初值的设定是为了控制定时器的计数范围和溢出周期。当初值为负数时,由于定时器寄存器是无符号的,负数会被解释为一个很大的正数,这可能导致定时器计数溢出的情况出现异常。

  2. 定时器计数异常:当定时器0的初值为负数时,定时器的计数范围可能会受到影响,导致计数溢出的时机不再稳定。这可能会导致PWM控制的频率和占空比出现异常变化,从而导致LED L1的闪烁现象。

建议保持定时器0的初值为正数,以确保定时器的正常计数和稳定工作。

  • 20
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

木木不迷茫(˵¯͒¯͒˵)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值