单片机型号为STC/AI 8G1K08A
工程前半部分做了市电的过零检测,P33引脚通过限流电阻、RC滤波结构直连市交流电(火线),并开启外部中断INT1,检测到下降沿后,在INT1中断内开启定时器进行延时补偿(考虑到继电器响应到吸合需要一定时间)
为了验证延时的效果,使用单片机P32端口监控用电器端的电压情况(反馈脚),继电器吸合后用电器与火线相连接入市电,那么,只要测量P32端口初次通电的脉冲宽度,即可确认火线进入用电器端的初始相位
测量脉冲宽度的方法是,当P32端口(ADC2)采集到高电平时,立即开启PCA计数,记录初始PCA数值,并配置为下降沿中断,中断触发后记录当前计数值,两者相减,即为高电平持续时间,即脉冲宽度
理想情况下,经定时器延时补偿 T1 + 继电器响应时间 T2 后,如果在P32端口 测量初次通电的脉冲宽度为 10 ms(近似),说明继电器触头导通瞬间,恰好正是市电零点
PCA 配置:
void PCA_Init(void){
P_SW1 &= 0x00; //P_SW1 是外设功能脚切换寄存器,可以控制相关引脚启用串口、PCA、SPI等功能,本例中置位 00 ,使得CCP0功能映射到 P3.2 端口上,其实也是CCP0的默认引脚
CMOD = 0x0C; //PCA 模式寄存器,[3:1] 控制PCA 计数脉冲源选择位即单次计数的周期 末位ECF-是否允许PCA 计数器溢出中断,0-禁止 1-使能
//0000 1100 系统时钟/6 禁止计数器溢出中断
CCON = 0x00; //B7-CF:PCA计数器溢出中断标志 B6-CR:PCA计数器允许控制位 B[2:0]-CCFn PCA模块中断标志
//PCA 控制寄存器 0000 0000 清除所有标志位
CL=CH=0; //清零PCA 计数器
EA = 1;
}
PCA中断服务函数:
void PCA_ISP() interrupt 7{
unsigned int capture=0; //记录此时进入中断的时间节点
if(CCF0){ //PCA 模块只有一个中断向量而包含多个中断源, 需要先分辨中断源再进行中断操作
CCF0=0; //清除标志
capture=((unsigned int)CH) <<8|(unsigned int)CL;
T_end = capture;
T_state = 1;
CR=0;
}
}
PCA计数调用:
if(check_flag){
Va=ADC_Read(2); //ADC采样P32端口电压
if(Va>370){ //采样值370转换为电压值为 1.2V 只有当检测到高电平时才会启用PCA 计数功能
CR=1;
T_start = ((unsigned int)CH )<<8|(unsigned int)CL; //记录当前计数值
CCAPM0 = 0x11; //CCAPMn PCA模块模式控制寄存器 详情参见数据手册
//B5-CCAPPn 允许 PCA模块n进行上升沿捕获; B4-CCAPNn 允许 PCA模块n进行下降沿捕获; B0 ECCFn 允许 PCA模块n 的匹配/捕获中断
//0001 0001 下降沿捕获并使能中断
check_flag=0;
}
}
if(T_state){
if(T_start<=T_end)
high_time=T_end-T_start;
else
high_time=65536-T_start+T_end;
T_state=0;
}
if(timer>=(high_time/100)){ //PCA计数周期是1us,定时器变量timer 的计时基准是100ms,high_time/1000得到ms量级,将ms量级的数字,乘以1000转换为秒量级,观察灯亮时间(秒级别),即可获得脉冲宽度
state=OFF;
timer=0;
}
经测试,定时器补偿3ms时,PCA测量脉冲宽度为15.8ms;
定时器补偿1ms时,PCA测量脉冲宽度为17.8ms;
可以发现,定时器补偿部分正常运行,但PCA脉冲测量结果出现极大偏差,理论上最大值仅为10ms(市电周期20ms的一半)
求大佬帮忙看看,是哪里配置有误? |