专注电子技术学习与研究
当前位置:单片机教程网 >> MCU设计实例 >> 浏览文章

基于51单片机的可控硅调压调光程序-带过零检测

作者:佚名   来源:本站原创   点击数:  更新时间:2012年02月02日   【字体:

   这是一个用51单片机通过过零检测来调整可控硅的导通角从而实现调光调压,其中过零电路用一个p620光耦,220v这端的电阻是40k,这是一个已经有成熟应用的例子,现在公开给51hei单片机论坛的网友.

视频演示:

全部代码下载:http://www.51hei.com/f/kkggl.rar

以下是c51源代码部分:
#include <reg52.H>	  
#include "intrins.h" 

#define	_50msL_	50000*0.9216
#define	_50msH_	50000*0.9216
#define	_1ms_	922
#define	_10ms_	9216
#define	_50us	46    //50*0.9216

#define uchar unsigned char  
#define uint unsigned int 
void delaySTD_ms(uchar ms); // 延时毫秒@12M,ms最大值255
unsigned char scankey();


sbit PWM_PIN= P1^0;
sbit PWM_TESTLED= P1^2;
/*在
 /INT0为过零检测,36v,注意安全!! 外接了两个按键,用来调整占空比;

  注意由于P1.1口也控制继电器,因此杜绝字节赋值,不要出现如P1=1;
 如果把 PWM 波形的频率提高,也可以用 LED 观察到渐亮渐暗的效果,目前看,只是闪烁的时间发生变化。
  220v调光设定为1kHz@12M,每周期1000us,分为10次比较合理,每CELL为1000us!
*/
sbit    key1pressed= P1^5;
sbit    key2pressed= P1^6;
sbit    key3pressed= P1^7;


#define LEVEL0 0
#define LEVEL1 1
#define LEVEL2 2
#define LEVEL3 3
#define LEVEL4 4

#define GRADE 10  //单位次,调光多少级?推荐10级,比较合理(实际只能显示7级,请加MAP映射处理!);20级的话到13级就会出现误判读!
//GRADE固定为10,以便完成9级调光!!!sw除开灭是8级调光,号称10级!
#define CELL  (9216/GRADE)     //10为半个市电周期,一个波
//#define CELL  10000  //10000us,实际是9216
#define KEYPRESSTIME  7  //10ms,key bound delay time

int iShiftPoint;
int b; //b一定要有符号整型!
uint timemultiplex;
uint timemultiplex_maxvalue;
//------------------------------------------
void main()
{
	PWM_PIN = 0; //先关了PWM,免得一开始就给5V导通220V了!!安全考虑!!
timemultiplex_maxvalue=3;
timemultiplex=1;	
	//外部过零中断
	IT0 = 1; //1为边沿触发
	EX0 = 1;
	//开启定时中断
	TMOD = 0x01;                 //T0定时方式1
    b =8;//初亮度调整
	iShiftPoint=b;
	TH0 = (65536-CELL*iShiftPoint) / 256;   //历史:50ms@12MHz,这里定时没意义,通过外中断过零定时
	TL0 = (65536-CELL*iShiftPoint) % 256;
	ET0 = 1;
	TR0 = 1;//TR0 = 1;定时只是为了计算延时时长!10ms即10000us,分成10种时长,由t1产生这10种时长
//定时器1初始化:
	TMOD |= 0x10;                 //T1定时方式1
	TH1 = (65536-_50us) / 256;   
	TL1 = (65536-_50us) % 256;
	ET1 = 1;
	TR1 = 1;//TR0 = 1;定时只是为了计算延时时长!10ms即10000us,分成10种时长,由t1产生这10种时长

	EA = 1;


//调光级别从0到4共5级别 能调光级别811~910
#define MAXAA 998
#define MINAA 11
         while(1)
		{
			unsigned char buf;

//以下为自动化按键测试
			b =MINAA;
			if (b>MAXAA) 
			{
		//	delaySTD_ms(500);
		//	delaySTD_ms(500);			
		//	delaySTD_ms(500);
		//	delaySTD_ms(500);
		//		b=MINAA;
			PWM_PIN=0;
			EA=0;
			}
			if (b<MINAA)
				 b=MINAA;
			b+=30;
			delaySTD_ms(500);
			continue;
//以上为自动化按键测试			

       //  while(1)
	//	{
	//		unsigned char buf;
			buf=scankey();
		 	if(buf==1)  //调灭
				{
					b++;
				}
		 	if(buf==2)
				{//二键调亮。b--是亮,765,从灭到月牙到亮
					b--;
				}
		 	if(buf==3)
				{//3键盘关闭继电器,同时也得关PWM灯才得灭;再按一次3键,则全亮
					PWM_PIN=!PWM_PIN;
				}
			if (b>(GRADE-1)) b=LEVEL4;//仍然最亮   //历史:在这里调整周期.不能无限增加
			if (b<0)  	 b=LEVEL0;//必须设置为>20,<1,不能设置为>19,<0,否则最后亮了就熄灭一下
			iShiftPoint=b;
			//other while
/*
			delaySTD_ms(500);
			delaySTD_ms(500);			
			delaySTD_ms(500);
			delaySTD_ms(500);
			timemultiplex_maxvalue++;
			if (timemultiplex_maxvalue>40) timemultiplex_maxvalue=40;
*/
		}
}

//------------------------------------------

void X0_INT(void) interrupt 0 
{
//过零检测,来个中断就表过零了,过零时才能重新基准一次10ms。

     //   EA = 0;
	TR0=0;
	//	PWM_PIN = 0;	
		TH0 = (65536-CELL*iShiftPoint) / 256;   //1000ms@12MHz,这里定时没意义,只是个时间流逝。通过外中断过零定时
		TL0 = (65536-CELL*iShiftPoint) % 256;   
	TR0=1;
  	//	EA = 1;
}

void time0(void) interrupt 1 
{

/*
	TR0 = 0;
	TH0 = (65536-CELL*iShiftPoint) / 256;   //历史:50ms@12MHz,这里定时没意义,通过外中断过零定时
	TL0 = (65536-CELL*iShiftPoint) % 256;
	TR0 = 1;
*/
	int i;
	// 1次外部中断产生,其灭会等待CELL*iShiftPoint us之后就开pwm,直至下次过零点关掉 ;CELL*iShiftPoint us由定时器来计算
	PWM_PIN = 1;       

/*
//随便两语句延时
for (i=0;i<100;i++)
{
   			_nop_();
			_nop_();
			_nop_();
}
*/

	TR1 = 0;
	TH1 = (65536-_50us) / 256;   //历史:50ms@12MHz,这里定时没意义,通过外中断过零定时
	TL1 = (65536-_50us) % 256;
	TR1 = 1;
		//关要!
//		PWM_PIN = 0;//亮个4us关,效果比一直亮好

}
//------------------------------------------ 

void time1(void) interrupt 3 
{
    timemultiplex++;
	if (timemultiplex==timemultiplex_maxvalue)
	{
		timemultiplex=0;
		//关要!
		PWM_PIN = 0;
	}
}


/*********************************************************/ 
// 延时子程序 
/*********************************************************/ 
void delaySTD_ms(uchar ms)  // 标准延时毫秒@12M,ms最大值255    
{    
    uchar i;    
    while(ms--)    
        for(i = 0; i < 124; i++);    
} 

//那个键按下返回几
unsigned char scankey()
{
	if (key1pressed==0)
	{
		delaySTD_ms(KEYPRESSTIME);
		if (key1pressed==0)
		{
			while(!key1pressed);
			delaySTD_ms(KEYPRESSTIME);
			return 1;
		}
	}
	if (key2pressed==0)
	{
		delaySTD_ms(KEYPRESSTIME);
		if (key2pressed==0)
		{
			while(!key2pressed);
			delaySTD_ms(KEYPRESSTIME);
			return 2;
		}
	}
	if (key3pressed==0)
	{
		delaySTD_ms(KEYPRESSTIME);
		if (key3pressed==0)
		{
			while(!key3pressed);
			delaySTD_ms(KEYPRESSTIME);
			return 3;
		}
	}

	return 0;  //0表示没按键按下,更表示误按了快速弹起了。
}
关闭窗口

相关文章