NO8 蓝桥杯单片机实践之定时器实现PWM

本文详细介绍了PWM的调节原理,通过占空比控制灯的亮度,涉及单片机的定时器结构、HC138通道选择、按键处理和消抖。作者给出了一个实际应用的示例,展示了如何通过定时器控制不同占空比以实现灯的10%、50%和90%亮度,以及使用独立按键切换模式。
摘要由CSDN通过智能技术生成

1 回顾

PWM的调节原理是通过控制占空比来实现调节功能的。

占空比为一个周期高电平占总电平的比例。

2实践

2.1任务

2.2 思路

任务中涉及到的模块有:

点亮L1 :  故涉及到HC138通道选择, L1可用sbit来表示

独立按键S7: 需要一个按键操作函数,为了消抖,故还要一个延时函数。S7可用sbit表示,

PWM信号实现调节灯的亮度: 需要用到定时器的结构。

这里的核心主要是如何通过定时器来实现PWM调制。

PWM信号频率为100HZ,故周期等于1 / 100 = 0.1s = 10ms

即PWM脉冲一个周期为10ms,根据题目,有四种不同的模式(熄灭,亮10%,亮50%,亮90%),则可以用占空比的不同来表示。

由于在单片机中低电平为亮,占空比是高电平占总电平的比。则亮10%可以表示为占空比为90%,即低电平占一个周期的10%。

同理,亮50%表示为占空比为50%,  亮90%表示占空比为10%。

那么如何用定时器表示呢?

一个PWM周期为10ms,定时器执行一次最多为65535 us = 65.535ms。

 我们之前说占空比是一个周期内高电平占总电平的比。那么如果我们把10ms分成10份,取一份为低电平,9份为高电平,那么占空比就为90%,同理,取5份为高,5份为低,占空比为50%,取9份为低,1份为高,占空比为10%。(也可以分为100份,取10份为低电平,90份为高电平,占空比也是90%)。

把10ms分成10份为例,那么我们就可以将定时器执行一次为(10ms/10 = 1ms = 1000us)

对应公式为:

  TH0 = (65535 - 1000) / 256;
  TL0 = (65535 - 1000) % 256;

然后在中断服务函数中,利用一个count进行计算,判断当定时器执行(1次/ 5次 /9次),故这里可以用一个PWM_Duty来表示,即PWM_Duty= 1次/ 5次 /9次,

在Key独立按键函数中,就要设置一个state来记录S7是第几次按下,对应是什么状态。

2.3 完整代码

这里解释以下:

中断服务函数这里:10ms一个周期分为10份,题目提到一开始L1是关闭的,这里用一个if函数判断,当if=PWM_duty时,L1=0才开始点亮。比如PWM_duty=9时,表示占空比为90%,高电平占了9份,因此在第0~8份时,都不满足if条件,故L1一直等于1,熄灭状态,当达到第9份时,满足了if条件,L1=1,开始亮灯。故实现了亮10%(占空比为90%)

最后这里还有一个if函数判断count是否等于10,表示如果等于10则一个周期过去了,故count要清零重新开始。

易错:不能把if(count==1),if(count==5),if(count==9)写入中断服务函数中,那么就表示它是自动更换亮度,不是靠按键来实现,因此要用一个变量PWM_duty,并在Key独立按键函数中给它赋值。

值得注意的是,本来常写在中断初始函数中的TR0写在了独立按键上,TR0是表示定时器是否正常工作的。

易错:

当90%亮再按一次就回到熄灭,即以下代码的case3,除了L1 = 1外,还要TR0 = 0,让计时器停止工作,否则定时器会继续工作,就会又执行到中断服务函数让L1点亮了。

完整代码如下:

#include "stc15f2k60s2.h"

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

void Delay(unsigned char t)
{
  while(t--);
}

void selectHC138(unsigned int n)
{
  switch(n)
  {
    case 0:
      P2 = (P2 & 0x1f) | 0x00;  break;
		case 1:
			P2 = (P2 & 0x1f) | 0x20;  break; 
		case 2:
			P2 = (P2 & 0x1f) | 0x40;  break; 
		case 3: 
			P2 = (P2 & 0x1f) | 0x60;  break; 
		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;   
  }
}

//================timer to PWM===========
void Init_Tmier0()
{
  TMOD = 0x00;
  TH0 = (65535 - 1000) / 256;
  TL0 = (65535 - 1000) % 256;
  EA = 1;
  ET0 = 1;
}

unsigned int count = 0;
unsigned int PWM_duty;
void Timer0() interrupt 1
{
  count++;
  if(count == PWM_duty)
  {
    L1 = 0;
  }

  if(count == 10)
  {
    L1 = 1;
    count = 0;
  }  
}


//===============================================
unsigned int state = 0;
void Key()
{
  if(S7 == 0)
  {
    Delay(50);
    if(S7 == 0)
    {
      switch(state)
      {
        case 0:
          PWM_duty =9; TR0 = 1; state = 1; break;
        case 1:
          PWM_duty =5; TR0 = 1; state = 2; break;        
        case 2:
          PWM_duty =1; TR0 = 1; state = 3; break; 
        case 3:
          L1 = 1; TR0 = 0; state = 0; break;
        
      }
      while(S7 == 0);
    }
  }
}

void close()
{
  selectHC138(5);
  P0 = 0x00;
  selectHC138(4);
  P0 = 0xff;
}

void main()
{
  close();
  Init_Tmier0();
  while(1)
  {
    Key();
  }
}

欢迎指正。

  • 22
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值