51单片机基于定时器实现呼吸灯(C8051F020单片机)

一、实现思路

原理:利用PWM信号控制LED灯的亮暗程度,实现LED灯由暗到亮又由亮到暗的渐变过程。

51单片机基于定时器实现呼吸灯(C8051F020单片机)_第1张图片

方法:通过定时器设置LED所接引脚的高低电平持续时间,模拟出PWM波。

二、关键问题——PWM的频率和占空比

1.设定PWM的频率:

由于人眼的视觉暂留效果,为避免视觉上灯的闪烁,PWM方波的频率至少大于30Hz。可以取PWM的周期为10ms,即频率为100Hz。

实现方式:使用定时器0的实现10ms定时。并使用定时器2控制PWM高低电平的持续时间。

2.设定占空比的步进间隔

步进时间间隔应小于人眼的视觉暂留效果,即小于30Hz,保证LED亮暗的变化能够被人眼捕捉到,我们设定步进时间的间隔为100ms(10Hz)。

实现方式:

(1)每隔100ms修改一次占空比,可通过进入10次定时器0(上文提到的)的溢出中断实现。

(2)定时器中断ISR中修改占空比:占空比从0开始,每次步进10%,递增到100%;再从100%每次递减10%到0%。

3.总结:利用两个定时器互相配合来模拟PWM波的生成,PWM波的频率和占空比均可控。

三、实现代码

注:C8051F020是增强型51单片机,与传统51相比增加了看门狗(watchdog)、交叉开关(crossbar)等外设,编程时应额外注意它们的使用。

步骤:各外设的初始化——打开定时器中断——在中断服务函数中写逻辑

#include 

#define Duty_Max 10         //10代表占空比最大为100%
#define STEP 1              //1代表每次步进10%
#define SYSCLK 2000000      //2MHz system clock

sfr16 RCAP2 = 0xCA;        	// Timer2 Reload Register
sfr16 TMR2 = 0xCC;         	// Timer2 Register

unsigned char duty = 0;     //占空比的范围0~10, 代表0%~100%
sbit LED = P2^4;            //开发板上P2.4连接LED
bit direction = 1;          //占空比增加/减少的方向: 1代表增加; 0代表减少

void Timer0_Init(void);
void Port_Init (void);
void Wait_MS(unsigned char ms);    //定时器2轮询方式实现ms级延时

void main()
{
	WDTCN = 0xDE;		// Disable watchdog timer
	WDTCN = 0xAD;
	OSCICN = 0x04;      //2MHz system clock
	
	Port_Init();
	Timer0_Init();
	LED = 0;
	EA = 1;
	while(1);
}

void Timer0_ISR(void) interrupt 1
{	
	static unsigned char n = 0;
	TH0 = 0xB1;
	TL0 = 0xE0;

	n++;
	LED = 1;		
	Wait_MS(duty);	
	LED = 0;	
	Wait_MS(10-duty);

	if(n==10)
	{	
		n = 0;
		if(direction == 1)
		{
			duty += STEP;
			if(duty == Duty_Max)
			{
				direction = 0;
			}
		}
		if(direction == 0)
		{
			duty -= STEP;
			if(duty == 0)
			{
				direction = 1;
			}
		}
			
	}
	
}

void Port_Init (void)
{
	XBR2 = 0x40;                    //enable crossbar
	P2MDOUT = 0xFF;
}
void Wait_MS(unsigned char ms)
{
   CKCON |= 0x20;					   //use SYSCLK               
   RCAP2 = -(SYSCLK/1000);             // Timer 2 overflows at 1 kHz
   TMR2 = RCAP2;

   TR2 = 1;                            // Start Timer 2
   while(ms)
   {
      TF2 = 0;                         
      while(!TF2);                     // Wait until timer overflows
      ms--;                            // Decrement ms
   }
   TR2 = 0;                            // Stop Timer 2
}
void Timer0_Init(void)
{
	CKCON |= 0x08;                      //use SYSCLK
	TMOD = 0x01;                        // 16-bit Mode Timer0	
   	TH0 = 0xB1;      					// 10ms
   	TL0 = 0xE0;
	ET0 = 1;                            // Timer0 interrupt enabled
   	TR0 = 1;
}

 

 

 

你可能感兴趣的:(51单片机,单片机,c语言)