蓝桥杯基础学习记录——PWM脉宽调制控制灯闪

jsi

依然是先列框架。

  1. 看题要用到的东西,定义头文件,HC138相关代码,定义S7L1端口,以及main函数。
    #include <REGX52.H>
    
    sbit L1 = P0^0;
    sbit S7 = P3^0;
    
    void SELECT_HC138(unsigned char n)
    	{
    	
      switch(n)
    {
    		case 4:
      P2=(P2&0x1f)|0x80;
        break;
    		case 5:
      P2=(P2&0x1f)|0xa0;
        break;
    		case 6:
      P2=(P2&0x1f)|0xc0;
        break;
    		case 7:
      P2=(P2&0x1f)|0xe0;
    	  break;
    
    }
    	}
    
    void main()
    {
    	SELECT_HC138(4);
    	L1=1;
    	InitTimer0();
    	while(1)
    	{
    	ScanKey();
    	}
    
    }
  2. 要用到S7按键,所以需要一个按键扫描ScanKey函数以及用于消抖的延时函数。在ScanKey函数中,由于整个题有四个不同的状态,我们设置一个变量state记录。当state为0时,开始计时,且亮度即占空比为10%,执行完后,state变为1;当state为1时,占空比改为20%,执行完后同样改变state值,使其进行下一个循环;当state为2时,占空比为90%,同样改变state值;当state为3时,此时灯光完全熄灭,这里有两种方法,一是将占空比定义为0,同样会进行系统定时器的计数,count会计数到100后自动清零,然后改变state值为0,从而再进入到下一个循环。另一种方法是在state为3时,关闭定时器的计数,改变state值为0,这个时候就不会进行定时器计数,只需要等到下一次按下S7进入下一个循环即可。两种方法在实践中都可以完成任务,都没有问题。
    
    void ScanKey()
    {
    	if(S7 == 0)
    	{
    		Delay(100);
    		if(S7==0)
    		{
    		switch(state)
    			{
    			case 0:
    				L1 = 0;
    			    TR0=1;
    				pwm_duty = 10;
    			    state=1;
    			break;
    			
    			case 1:
    				pwm_duty=50;
    			    state=2;
    			break;
    			
    			case 2:
    				pwm_duty =90;
    				state=3;
    			break;
    			
    			case 3:
    				L1=1;
    			    TR0=0;
    				state=0;
    			break;
    			}
    			while(S7 == 0);
    		}
    	
    	}
    
    
    }

  3. 利用脉宽信号实现对灯光的控制,这个地方需要用到中断函数InitTimer0,一般分为初始化函数和中断服务函数ServiceTimer0()。题目上说pwm脉宽信号的频率为100Hz,即周期为10ms,以第一种情况为例,10%的亮度,即低电平在整个周期中占比为10%。假如将这个周期分为一百份,其中十份为低电平,剩下的九十份为高电平,这样完成一个周期就完成了第一种情况,等到下个周期的时候,改变低电平的占比为50%就可以完成第二种情况,依次改变占空比就可以完成所有情况。
  4. 我们将系统定时器的周期设置成一百份中的其中一份,每完成一次周期记一次数,这个数在小于占空比值时,设置为低电平使灯亮,大于占空比时,设置为高电平使灯灭,等到这个数为100时,就可以清空,然后开启下一个占空比值不同的周期。这里定义两个变量pwm_duty以及count分别用于改变占空比值和记录周期。
    
    void InitTimer0()
    {
    	TMOD=0x01;
    	TH0=(65535-100)/256;
    	TL0=(65535-100)%256;
      ET0=1;
    	EA=1;
    	
    }
    void ServiceTimer0() interrupt 1
    {
    	TH0=(65535-100)/256;
    	TL0=(65535-100)%256;
    	count++;
    	if(count <= pwm_duty)
    	{
    		L1=0;
    	}
    	else if(count > pwm_duty)
    	{
    		L1=1;
    		if(count == 100)
    	{ 
    		count = 0;
    	}
    	}
    	
    		
    }

  • 46
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值