• 回复
  • 收藏
  • 点赞
  • 分享
  • 发新帖

过温保护异常,导致电源重启。

这是我之前做的一个电源产品,使用R8C27系列的单片机来控制各路输出电压,还有控制其上电时序,并检测各路电压是否异常,异常时,电源关闭保护。另外,还有检测电源内部温度情况,当温度大于80时,电源关闭。关于温度检测这一块,主要是使用NTC热敏电阻(电路图上位号:RT601, 规格书见附件)与一个10K电阻串联。通过AD转化得到一个AD数值,再由AD数值来计算出NTC热敏电阻的阻值。由电阻值来判断当前电源温度。软件上具体的为:

定义变量:UINT  ad_valueULONG  r_value r_value=1024*10*10 - ad_value*10*10/ad_value.

这里定义的ad_value为电阻分压出来,也就是ADT点上的电压的AD值。r_value 10倍的NTC热敏电阻值(单位为: k Ω)。例如:当ad_value=883时,则r_value=16,即NTC热敏电阻值为:1.6k,通过规格书可以知道此时的温度为80。那也就是说逻辑上,r_value<16时,温度超过80,电源才保护的。

    目前的问题是产品卖到北方地区,客户反馈早上起来的时候,电源开机不良,上半年未发现此问题,而我们工厂(在南方,温度基本上在10以上)这边,也从来没有出现过这种现象。后来将产品进行低温试验(-10)。发现在常温下将产品置于低温室时,20分钟左右开机后,会自动保护。而如果继续放置两小时,温度平衡后,开机又正常,现象挺奇怪的。

   大家觉得是什么原因?是NTC热敏电阻在温度变化的过程中,存在突变点? 温度曲线没有像规格书描述的那样?温度越低,阻值越大?还是软件上有BUG

 

全部回复(13)
正序查看
倒序查看
58340153
LV.3
2
2012-12-10 10:32

电路图和规格书如下:

NTC热敏电阻规格书 

 

0
回复
58340153
LV.3
3
2012-12-11 12:57

通过仿真,已经明确是软件上有BUG,具体的改天有时间再来分析给大家看。

0
回复
sharkdo
LV.3
4
2012-12-11 14:35

楼主很专业,个人认为也可以通过专业仪器仪表的使用来保证电源的运行,现在的功率检测分析仪/功率计采用了拥有专利的高带宽架构,能够精度测量单相或三相电流和电压、谐波分析、快速傅里叶变换(FFT)分析,以及计算功率和其它计算值,作为实验室或试验台上的台式仪器,都非常方便、可靠。

0
回复
58340153
LV.3
5
2012-12-12 13:33
软件在计算过程中,逻辑和公式的推导都没有问题,变量的类型定义似乎也没问题。但是事实上,在仿真的过程中确实发现有数据溢出导致计算结果出错,从而导致了电源的误操作。那么数据是如何溢出的呢?
0
回复
58340153
LV.3
6
2012-12-12 13:55
下面具体的来看一下,当温度变化为:-40度~125度时,NTC 对应的阻值变化范围为:5~202.1K欧,r_value变化范围为:0~2021,而r_value的类型定义为无符号长整型ULONG,可以表示的范围为:0~0XFFFFFFFF, 很显然 r_value 不可能溢出。那么再来看一下,另外一个变量ad_value,  ad_value定义的类型为无符号整型UINT, 可以表示的范围为:0~0XFFFF,其值在实际的变范围只有:0~1024。看起来这两个变量也未出现溢出。所以接下只好再看一下,计算的过程。
0
回复
58340153
LV.3
7
2012-12-12 15:32

C语言代码:r_value=(1024*10*10 - ad_value*10*10)/ad_value;       // value si 10*R ;
生产汇编语言后的代码:               
                MOV.W     0438H,R0  (将存储在0438H中的值即ad_value,赋予寄存器R0)
                MUL.W     #0064H,R0  (执行ad_value*10*10 ,其中#0064H代表常量100。 以16位做乘法运算,结果以32位保存)
                MOV.W     R0,R1
                MOV.W     #9000H,R0 (#9000H即为:1024*10*10-0XFFFF=0X19000-0XFFFF=0X9000=9000H)
                SUB.W     R1,R0    
                MOV.W     #0H,R2
                DIVU.W    0438H (除法运算)
                MOV.W     R0,054CH (r_value的值存储在地址 054CH,054EH 中)
                MOV.W     #0H,054EH

从生成的汇编语言的代码中,已经可以看出问题的所在。

0
回复
58340153
LV.3
8
2012-12-12 15:58
@58340153
C语言代码:r_value=(1024*10*10-ad_value*10*10)/ad_value;      //valuesi10*R;生产汇编语言后的代码:                              MOV.W    0438H,R0 (将存储在0438H中的值即ad_value,赋予寄存器R0)               MUL.W    #0064H,R0 (执行ad_value*10*10,其中#0064H代表常量100。以16位做乘法运算,结果以32位保存)               MOV.W    R0,R1               MOV.W    #9000H,R0(#9000H即为:1024*10*10-0XFFFF=0X19000-0XFFFF=0X9000=9000H)               SUB.W    R1,R0                   MOV.W    #0H,R2               DIVU.W   0438H(除法运算)               MOV.W    R0,054CH(r_value的值存储在地址054CH,054EH中)               MOV.W    #0H,054EH从生成的汇编语言的代码中,已经可以看出问题的所在。
问题就出在,以下的两条指令:
                MOV.W     #9000H,R0 (#9000H即为:1024*10*10-0XFFFF=0X19000-0XFFFF=0X9000=9000H)
                SUB.W     R1,R0 
 
1、表达式:1024*10*10 。应生成:MOV.W     #19000H,R0 才对(实际上需要生成两条语句,这里为了好理解直接写成这样。),因为:1024*10*10=0X19000=19000H,而这里由于系统认为最大的变量为,无符号整型UINT,所以1024*10*10变成了9000H,将进位1直接去掉。
2、另外,SUB.W     R1, R0,只能做16位的减法运算。即运算结果必须小于0XFFFF。否则,数据将溢出。
0
回复
58340153
LV.3
9
2012-12-12 16:24
@58340153
问题就出在,以下的两条指令:               MOV.W    #9000H,R0(#9000H即为:1024*10*10-0XFFFF=0X19000-0XFFFF=0X9000=9000H)               SUB.W    R1,R0  1、表达式:1024*10*10。应生成:MOV.W    #19000H,R0才对(实际上需要生成两条语句,这里为了好理解直接写成这样。),因为:1024*10*10=0X19000=19000H,而这里由于系统认为最大的变量为,无符号整型UINT,所以1024*10*10变成了9000H,将进位1直接去掉。2、另外,SUB.W    R1,R0,只能做16位的减法运算。即运算结果必须小于0XFFFF。否则,数据将溢出。
那也就是说 r_value=(1024*10*10 - ad_value*10*10)/ad_value <0xFFFF=65535; 对应的ad_value必须大于(102400-65535)/100=368.65。此时r_value的计算值为0,但实际电阻值为18K,温度为9度。所以出现了电源异常保护的问题。如果温度继续降低,则ad_value会继续减小,而 r_value 又会继续增加,重新大于16。电源工作又变正常,这个点在实际中电阻值为22K左右,对应的温度为5度。
0
回复
58340153
LV.3
10
2012-12-12 16:43
大家有没有发现,理论分析与实际相吻合了。 本电源在工作过程中,由于计算过程中,数据溢出,原本只在温度大于80度以上保护时,变成了在5~9度时,出现了电源也过温保护。现在才知道为什么把电源放入低温室(-10度)时,20分钟左右开机后,会自动保护。而如果继续放置两小时,温度平衡后,开机又正常的奇怪现象了。 因为,只有在降温的过程中5-9度才会出现这中问题。
0
回复
58340153
LV.3
11
2012-12-12 17:09
说了这么多现在来看看如何解决这个问题,其实,当我们找到问题所在的同时,也同时找到了解决办法。方法有很多:可以将原先16位的变量ad_value定义为32位的比如:ULONG,float等类型。还有另外一种办法是改变产量的表达方法,只要对表达式: r_value=(1024*10*10 - ad_value*10*10)/ad_value ,改为 : rt_value=(102400-vt_average_ad_data*100)/vt_average_ad_data;  或者      
r_value=(1024*10*10.0 - ad_value*10*10.0)/ad_value;   就可以了。
0
回复
58340153
LV.3
12
2012-12-12 17:17
我把更表达式后的汇编代码给出来,有兴趣的可以自己去研究一下,这些代码最后计算的方法有什么不同。
0
回复
58340153
LV.3
13
2012-12-12 17:18
rt_value=(102400-vt_average_ad_data*100)/vt_average_ad_data;  // value si 10*R ;
编译后生成的代码:
               MOV.W     0438H,R0
               MUL.W     #0064H,R0
               MOV.W     #0H,R2
               MOV.W     #9000H,R1   //   (这就是我前面所说的,与 MOV.W     #19000H, R0 对应的两条代码)
               MOV.W     #1H,R3        //
               SUB.W     R0,R1
               SBB.W     R2,R3
               MOV.W     0438H,R0
               MOV.W     #0H,R2
               XCHG.W    R0,R1
               XCHG.W    R2,R3
               MOV.W     R1,A0
               MOV.W     R3,A1
               PUSHM     A0,A1
               JSR.W     __i4div
               ADD.B     #4H,SP
               MOV.W     R0,054CH
               MOV.W     R2,054EH
0
回复
58340153
LV.3
14
2012-12-12 17:18
@58340153
rt_value=(102400-vt_average_ad_data*100)/vt_average_ad_data; //valuesi10*R;编译后生成的代码:              MOV.W    0438H,R0              MUL.W    #0064H,R0              MOV.W    #0H,R2              MOV.W    #9000H,R1  //  (这就是我前面所说的,与MOV.W    #19000H,R0对应的两条代码)              MOV.W    #1H,R3       //              SUB.W    R0,R1              SBB.W    R2,R3              MOV.W    0438H,R0              MOV.W    #0H,R2              XCHG.W   R0,R1              XCHG.W   R2,R3              MOV.W    R1,A0              MOV.W    R3,A1              PUSHM    A0,A1              JSR.W    __i4div              ADD.B    #4H,SP              MOV.W    R0,054CH              MOV.W    R2,054EH
r_value=(1024*10*10.0 - ad_value*10*10.0)/ad_value;        // value si 10*R ;
编译后生成的代码:   
                MOV.W     0438H,R0
                MUL.W     #000AH,R0
                PUSH.W    #0000H
                PUSH.W    R0
                JSR.W     __i4Utof
                ADD.B     #4H,SP
                PUSH.W    #4024H
                PUSH.W    #0000H
                PUSH.W    #0000H
                PUSH.W    #0000H
                PUSHM     R0,R1,R2,R3
                JSR.W     __f8mul
                ADD.B     #10H,SP
                PUSHM     R0,R1,R2,R3
                PUSH.W    #40F9H
                PUSH.W    #0000H
                PUSH.W    #0000H
                PUSH.W    #0000H
                JSR.W     __f8sub
                ADD.B     #10H,SP
                MOV.W     R3,-2H[FB]
                MOV.W     R2,-4H[FB]
                MOV.W     R1,-6H[FB]
                MOV.W     R0,-8H[FB]
                PUSH.W    #0000H
                PUSH.W    0438H
                JSR.W     __i4Utof
                ADD.B     #4H,SP
                PUSHM     R0,R1,R2,R3
                PUSH.W    -2H[FB]
                PUSH.W    -4H[FB]
                PUSH.W    -6H[FB]
                PUSH.W    -8H[FB]
                JSR.W     __f8div
                ADD.B     #10H,SP
                PUSHM     R0,R1,R2,R3
                JSR.W     __f8toi4
                ADD.B     #8H,SP
                MOV.W     R2,054EH
                MOV.W     R0,054CH
0
回复