驱动调试记录-可控硅的使用
此笔记记录了可控硅的控制原理、以及相位控制和零点控制的控制方法以及代码实现。
一、可控硅的控制原理
参考网址:https://zhuanlan.zhihu.com/p/434566109
1. 相位控制
微控制器通过检测零检测电路的信号后,通过延时一定的时间然后打开可控硅,从而控制可控硅的导通角,通过导通角来实现控制功率输出的大小。如下图所示,在过零检测电路输出的矩形波期间用微控制器产生脉冲控制可控硅的导通时间从而能有效地控制功率的输出。
2. 零点控制
零点控制是对交流电压的周波进行控制,通过控制负载电压的周波通断比来控制负载功率,多用于大惯性的加热器负载。采用这种控制,既实现了温度控制,又消除了相位控制带来的高次谐波污染电网,不过控制精度有所降低。
二、驱动代码的实现
1. 相位控制代码实现
注:对定时器精度有要求,精度不够则选择零点控制为佳
__hdle hdl1 = NULL;
typedef struct
{
__u8 enable;
__u8 SetRPow ; //功率值
__u8 R_Dly ; //过零后延时开可控硅时间
__u8 T_Dirv ; //可控硅打开的驱动时间
}__tTriDrive_t;
static __krnl_stmr_t *tridevice_timer_hdl = NULL;
__tTriDrive_t tTriDriv = {
.enable = 0,
.SetRPow = 0, //功率值
.R_Dly = 0, //过零后延时开可控硅时间
.T_Dirv = 0 //可控硅打开的驱动时间
};
//定义标志位
__u8 F_TRI1 ;
__u8 F_HT1 ; //开启负载标志 1为开启
//定时器中断处理函数
static void tridevice_timmer_proc(void *arg)
{
if(F_TRI1)
{
if(tTriDriv.R_Dly != 0)
{
tTriDriv.R_Dly -- ;
}
else
{
app_gpio_set_heating(1);//开可控硅
F_TRI1 = 0;
}
}
else
{
if(tTriDriv.T_Dirv != 0)
{
tTriDriv.T_Dirv -- ;
}
else
{
app_gpio_set_heating(0);//关可控硅
esKRNL_TmrStop(tridevice_timer_hdl, OS_TMR_OPT_NONE, NULL); //关定时器中断
//使能指定引脚的中断
esPINS_EnbaleInt(hdl1);
}
}
}
static __s32 tridevice_isr_task_pio(void *arg)
{
__s32 ret;
if (NULL == hdl1)
{
__err("tridevice int pin hdl is null...\n");
return EPDK_FAIL;
}
//清除中断引脚的挂起状态
ret = esPINS_ClearPending(hdl1);
if (ret == EPDK_FAIL)
{
__err("pending clear failed!\n");
}
//禁用中断
ret = esPINS_DisbaleInt(hdl1);
if (EPDK_FAIL == ret)
{
}
if(!tTriDriv.enable)
return 0;
F_TRI1 = 1;
//更新等待时间
tTriDriv.R_Dly = (__u8)tTriDriv.SetRPow/100.0*20; //等待打开可控硅的时间
tTriDriv.T_Dirv = 2; //可控硅打开的持续时间
//让定时器开始跑
if((esKRNL_TmrStateGet(tridevice_timer_hdl) == OS_TMR_STATE_STOPPED) && tTriDriv.SetRPow != 0)
{
esKRNL_TmrStart(tridevice_timer_hdl);
}
return 1;
}
__s32 tridevice_init(void)
{
__s32 ret;
user_gpio_set_t gpio_set[2]={0};
//过零检测 PF0 (6 0)
gpio_set[0].port = 6;
gpio_set[0].port_num = 0;
gpio_set[0].mul_sel = 6;
gpio_set[0].pull = 1;
gpio_set[0].drv_level = 3;
gpio_set[0].data = 1;
hdl1 = esPINS_PinGrpReq(&gpio_set[0], 1);
if (hdl1)
{
//注册io中断处理函数
__log("install pio isr\n");
ret = esPINS_RegIntHdler(hdl1, tridevice_isr_task_pio, NULL);
if (EPDK_FAIL == ret)
{
__wrn("install pio isr fail...\n");
}
//设置指定引脚的中断模式(0为上升沿触发,1为下降沿触发,2为高电平触发,4为边沿触发,包括上升沿和下降沿)
ret = esPINS_SetIntMode(hdl1, 4);
if (EPDK_FAIL == ret)
{
__wrn("set irq mode fail...\n");
}
//使能指定引脚的中断
__wrn("enable one pio int\n");
ret = esPINS_EnbaleInt(hdl1);
if (EPDK_FAIL == ret)
{
__wrn("enable one pio int fail...\n");
}
//创建定时器,若精度不够则不适合这种方式
tridevice_timer_hdl = esKRNL_TmrCreate(
1,
OS_TMR_OPT_PRIO_HIGH | OS_TMR_OPT_PERIODIC,
(OS_TMR_CALLBACK)tridevice_timmer_proc,
NULL);
if (!tridevice_timer_hdl)
{
__log("create timer failed");
return EPDK_FAIL;
}
}
return ret;
}
2. 零点控制代码实现
__hdle hdl1 = NULL;
typedef struct
{
__u8 enable;
__u8 SetRPow ; //功率值
__u8 ctr_cycle_num ; //控制周期数
}__tTriDrive_t;
__tTriDrive_t tTriDriv={
.enable = 0,
.SetRPow = 0,
.ctr_cycle_num = 4
};
//io中断处理函数
static __s32 tridevice_isr_task_pio(void *arg)
{
__s32 ret;
if (NULL == hdl1)
{
__err("tridevice int pin hdl is null...\n");
return EPDK_FAIL;
}
//清除中断引脚的挂起状态
ret = esPINS_ClearPending(hdl1);
if (ret == EPDK_FAIL)
{
__err("pending clear failed!\n");
}
//禁用中断
ret = esPINS_DisbaleInt(hdl1);
if (EPDK_FAIL == ret)
{
}
static __u8 cycle_cnt = 0;
if(tTriDriv.enable == 0)
{
return 0;
}
if(cycle_cnt <= 0)
{
cycle_cnt = tTriDriv.ctr_cycle_num;
}
switch(tTriDriv.SetRPow)
{
case 0:
app_gpio_set_heating(0);
break;
case 25:
if(cycle_cnt > 3)
app_gpio_set_heating(1);
else
app_gpio_set_heating(0);
break;
case 50:
if(cycle_cnt > 2)
app_gpio_set_heating(1);
else
app_gpio_set_heating(0);
break;
case 75:
if(cycle_cnt > 1)
app_gpio_set_heating(1);
else
app_gpio_set_heating(0);
break;
case 100:
app_gpio_set_heating(1);
break;
default:break;
}
cycle_cnt--;
//使能指定引脚的中断
esPINS_EnbaleInt(hdl1);
return 1;
}
__s32 tridevice_init(void)
{
__s32 ret;
user_gpio_set_t gpio_set[2]={0};
//过零检测 PF0 (6 0)
gpio_set[0].port = 6;
gpio_set[0].port_num = 0;
gpio_set[0].mul_sel = 6;
gpio_set[0].pull = 1;
gpio_set[0].drv_level = 3;
gpio_set[0].data = 1;
hdl1 = esPINS_PinGrpReq(&gpio_set[0], 1);
if (hdl1)
{
//注册io中断处理函数
__log("install pio isr\n");
ret = esPINS_RegIntHdler(hdl1, tridevice_isr_task_pio, NULL);
if (EPDK_FAIL == ret)
{
__wrn("install pio isr fail...\n");
}
//设置指定引脚的中断模式(0为上升沿触发,1为下降沿触发,2为高电平触发,4为边沿触发,包括上升沿和下降沿)
ret = esPINS_SetIntMode(hdl1, 4);
if (EPDK_FAIL == ret)
{
__wrn("set irq mode fail...\n");
}
//使能指定引脚的中断
__wrn("enable one pio int\n");
ret = esPINS_EnbaleInt(hdl1);
if (EPDK_FAIL == ret)
{
__wrn("enable one pio int fail...\n");
}
}
return ret;
}
其他控制接口如下:
//设置功率
void tridevice_set_power(__u8 value)
{
tTriDriv.SetRPow = value;
if(tTriDriv.SetRPow >= 100)
{
tTriDriv.SetRPow = 100;
}
else if(tTriDriv.SetRPow >= 75)
{
tTriDriv.SetRPow = 75;
}
else if(tTriDriv.SetRPow >= 50)
{
tTriDriv.SetRPow = 50;
}
else if(tTriDriv.SetRPow >= 25)
{
tTriDriv.SetRPow = 25;
}
else if(tTriDriv.SetRPow < 25)
{
tTriDriv.SetRPow = 0;
}
__log("set power = [%d]%%",tTriDriv.SetRPow);
}
void tridevice_enable(void)
{
tTriDriv.enable = 1;
}
void tridevice_disenable(void)
{
tTriDriv.enable = 0;
}
- 零点控制模式下功率为25%的波形如下: