C51--Task07 PWM与呼吸灯实验

一、按键控制LED亮度

具体任务:

 采用按键控制LED1亮度。要求能在数码管上显示当前占空比,能够使用KEY1增加占空比,KEY2降低占空比。

代码:

#include <reg52.h>

//位定义
sbit LED1 = P2^4; 
sbit KEY1 = P3^2; 
sbit KEY2 = P3^3; 
sbit SegmentG1 = P2^3;  
sbit SegmentG2 = P2^2;  
sbit SegmentG3 = P2^1;  
sbit SegmentG4 = P2^0;  

//定义变量
static unsigned int a ,b ,c ,d;
static unsigned char s_arrNumber[] = {0x03 , 0x9f , 0x25 , 0x0d , 0x99 , 0x49 , 0x41 , 0x1f , 0x01 , 0x09}; //?????????0-9
static unsigned int s_iCnt1 = 0;        //s_iCnt1作为10ms计数变量,控制PWM周期
static unsigned int s_iCnt2 = 0;        //s_iCnt1作为20ms计数变量,控制呼吸快慢
static unsigned int s_iDuty = 100;      //s_iDuty作为占空比
static unsigned char s_iFlag = 0;       //s_iFlag作为占空比增减标志,0减小,1增加

//定时器0配置函数
static void InitTimer0()
{
  TMOD = 0x02;  //工作模式2
  TH0  = 0xFF;  //高八位
  TL0  = 0x9C;  //低八位,定时100μs溢出
  TR0  = 1;     //打开定时器0
}

//中断初始化函数
static void InitInterrupt()
{
  ET0 = 1;   //定时器0 中断允许
  EA  = 1;   //总中断允许
}

//延迟函数
static void DelayNms(int nms)
{
  unsigned int i,j;
  for(i = 0; i < nms; i++)
  {
    for(j = 0; j < 123; j++)
    {
      
    } 
  }
}

//主函数
void main()
{
  InitInterrupt();  //配置中断
  InitTimer0();     //配置定时器0
  while (1)
  {
	//一直在显示可以放主函数里
  a = s_iDuty / 1000;                //显示千位(定义的整型所以自动忽略小数点后面的)
  b = s_iDuty / 100;                 //显示百位
  c = s_iDuty / 10;                 //显示十位
  d = s_iDuty % 10;                 //显示个位
	
  P0 = s_arrNumber[a]; 
  SegmentG1 = 0;       
  DelayNms(1);         
  SegmentG1 = 1;       

  P0 = s_arrNumber[b]; 
  SegmentG2 = 0;       
  DelayNms(1);         
  SegmentG2 = 1;       

  P0 = s_arrNumber[c]; 
  SegmentG3 = 0;       
  DelayNms(1);         
  SegmentG3 = 1;      

  P0 = s_arrNumber[d]; 
  SegmentG4 = 0;       
  DelayNms(1);         
  SegmentG4 = 1;       
  }
}

//中断服务函数
void Timer0_Handler () interrupt 1
{
  //反复执行10ms计数(控制周期)
  s_iCnt1++;
  if(s_iCnt1 >= 100)   //100*100μs=10ms
  {
    s_iCnt1 = 0;           
  }
  
	//设置占空比调节标志
    if(s_iDuty >= 100 && 1 == s_iFlag)     //若占空比增大到100且当前标志为增加占空比
    {
      s_iFlag = 0;                         //设置标志为减小占空比
    } 
    else if(0 == s_iDuty && 0 == s_iFlag)  //若占空比减小到0且当前标志为减小占空比
    {
      s_iFlag = 1;                         //设置标志为增加占空比
    }

    //占空比调节
    if(0 == s_iFlag) 	     //若s_iFlag为0
    {
      s_iDuty--;           //减小占空比
    }
    else if(1 == s_iFlag)  //若s_iFlag为1
    {
      s_iDuty++;           //增加占空比
    }
		
	//KEY1按键调节
	if(0 == KEY1)           //KEY1按下
    {
      DelayNms(50);       //等50ms
      if(0 == KEY1)       //再次检测到KEY1按下
      {
      s_iDuty++;           //增加占空比
    }
  }
	
	//KEY2按键调节
	if(0 == KEY2)           //KEY2按下
    {
      DelayNms(50);       //等50ms
      if(0 == KEY2)       //再次检测到KEY2按下
      {
        s_iDuty--;        //减小占空比
    }
  }
	
  if(s_iCnt1 <= s_iDuty)   //控制LED开关
  {
    LED1 = 1;              //关LED1
  }
  else
  { 
    LED1 = 0;              //开LED1
  }
}

二、按键调整LED呼吸速度

具体任务:

 采用按键调整LED1呼吸速度。要求能在数码管上显示 PWM占空比调整周期(单位:ms),能够使用KEY1降低调整周期,KEY2延长调整周期。

代码:

#include <reg52.h>

//位定义
sbit LED1 = P2^4; 
sbit KEY1 = P3^2; 
sbit KEY2 = P3^3; 
sbit SegmentG1 = P2^3;  
sbit SegmentG2 = P2^2;  
sbit SegmentG3 = P2^1;  
sbit SegmentG4 = P2^0;  

//定义变量
int a ,b ,c ,d;
static unsigned char s_arrNumber[] = {0x03 , 0x9f , 0x25 , 0x0d , 0x99 , 0x49 , 0x41 , 0x1f , 0x01 , 0x09}; //?????????0-9
static unsigned int s_iCnt1 = 0;        //s_iCnt1作为10ms计数变量,控制PWM周期
static unsigned int s_iCnt2 = 0;        //s_iCnt1作为20ms计数变量,控制呼吸快慢
static unsigned int s_iDuty = 100;      //s_iDuty作为占空比
static unsigned char s_iFlag = 0;       //s_iFlag作为占空比增减标志,0减小,1增加

//定时器0配置函数
static void InitTimer0()
{
  TMOD = 0x02;  //工作模式2
  TH0  = 0x9C;  //高八位
  TL0  = 0x9C;  //低八位,定时100μs溢出
  TR0  = 1;     //打开定时器0
}

//中断初始化函数
static void InitInterrupt()
{
  ET0 = 1;   //定时器0 中断允许
  EA  = 1;   //总中断允许
}

//延迟函数
static void DelayNms(int nms)
{
  unsigned int i,j;
  for(i = 0; i < nms; i++)
  {
    for(j = 0; j < 123; j++)
    {
      
    } 
  }
}

//主函数
void main()
{
  InitInterrupt();  //配置中断
  InitTimer0();     //配置定时器0
  while (1)
  {
	//一直在显示可以放主函数里
  a = s_iCnt2 / 1000;                //显示千位
  b = s_iCnt2 / 100;                 //显示百位
  c = s_iCnt2 / 10;                  //显示十位
  d = s_iCnt2 % 10;                  //显示个位
	
  P0 = s_arrNumber[a]; 
  SegmentG1 = 0;       
  DelayNms(1);         
  SegmentG1 = 1;       

  P0 = s_arrNumber[b]; 
  SegmentG2 = 0;       
  DelayNms(1);         
  SegmentG2 = 1;       

  P0 = s_arrNumber[c]; 
  SegmentG3 = 0;       
  DelayNms(1);         
  SegmentG3 = 1;      

  P0 = s_arrNumber[d]; 
  SegmentG4 = 0;       
  DelayNms(1);         
  SegmentG4 = 1;       
  }
}

//中断服务函数
void Timer0_Handler () interrupt 1
{
  //反复执行10ms计数(控制周期)
  s_iCnt1++;
  if(s_iCnt1 >= 100)   //100*100μs=10ms
  {
    s_iCnt1 = 0;           
  }
  
	 //设置占空比调节标志
    if(s_iDuty >= 100 && 1 == s_iFlag)     //若占空比增大到100且当前标志为增加占空比
    {
      s_iFlag = 0;                         //设置标志为减小占空比
    } 
    else if(0 == s_iDuty && 0 == s_iFlag)  //若占空比减小到0且当前标志为减小占空比
    {
      s_iFlag = 1;                         //设置标志为增加占空比
    }

    //占空比调节
    if(0 == s_iFlag) 	     //若s_iFlag为0
    {
      s_iDuty--;           //减小占空比
    }
    else if(1 == s_iFlag)  //若s_iFlag为1
    {
      s_iDuty++;           //增加占空比
    }
 
	
	//KEY1按键调节
 if(0 == KEY1)           //KEY1按下
    {
      DelayNms(50);       //等50ms
      if(0 == KEY1)       //再次检测到KEY1按下
      {
      s_iCnt2++;           //增加占空比周期
    }
  }
	
	//KEY2按键调节
	if(0 == KEY2)           //KEY2按下
    {
      DelayNms(50);       //等50ms
      if(0 == KEY2)       //再次检测到KEY2按下
      {
        s_iCnt2--;        //减小占空比周期
    }
  }
	
  if(s_iCnt1 <= s_iDuty)   //控制LED开关
  {
    LED1 = 1;              //关LED1
  }
  else
  { 
    LED1 = 0;              //开LED1
  }
}
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值