×
单片机 > 单片机程序设计 > 详情

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

发布时间:2020-06-23 发布时间:
|
这是一个用51单片机通过过零检测来调整可控硅的导通角从而实现调光调压,其中过零电路用一个p620光耦,220v这端的电阻是40k,这是一个已经有成熟应用的例子.

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

以下是c51源代码部分:
#include 	  
#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(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表示没按键按下,更表示误按了快速弹起了。
}
关键字:51单片机  可控硅  带过零检测

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
STM32中断向量表的位置.重定向