[求助]Arduino控制可控硅的程序(含过零检测)各位大神现身吧
本帖最后由 wasdpkj 于 2012-11-1 20:46 编辑我自己搞定了!
这次主要是来求助程序的,可控硅是通过高低电平来控制其导通角达到目的,可过零检测这里我就纠结了,涉及到中断,c语言太烂是在无从下手。
上网搜了很久,没有arduino控制可控硅的例子,各位能否帮我看看程序如何写好。
最终目的是arduino控制220v市电电器的功率,用可控硅可以实现电压的无极调整,光耦则是安全考虑。
电路图:
电路图经测试是有效的,P1是控制端,P2是过零检测端
这里有个例子:
http://wenku.baidu.com/view/dc37c4eb998fcc22bcd10d13.html
以下是搜得的51单片机代码(c语言太烂,实在看不太懂)
#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 CELL10000//10000us,实际是9216
#define KEYPRESSTIME7//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表示没按键按下,更表示误按了快速弹起了。
}
好资料,你使用了吗? 太行摄狼 发表于 2012-10-25 23:22 static/image/common/back.gif
好资料,你使用了吗?
没使用,刚试了试,没加过零检测的话,风扇只能勉强转,无法很好地控制,我现在就是不会编程。。所以来求助,您能否帮忙看看程序怎么写
页:
[1]