242 lines
6.1 KiB
C
242 lines
6.1 KiB
C
#ifdef SUPPORT_MS_EXTENSIONS
|
|
#pragma bss_seg(".ntc_det.data.bss")
|
|
#pragma data_seg(".ntc_det.data")
|
|
#pragma const_seg(".ntc_det.text.const")
|
|
#pragma code_seg(".ntc_det.text")
|
|
#endif
|
|
//*********************************************************************************//
|
|
// NTC det //
|
|
//*********************************************************************************//
|
|
//
|
|
//
|
|
#include "gpadc.h"
|
|
#include "ntc_det_api.h"
|
|
#include "system/includes.h"
|
|
#include "asm/charge.h"
|
|
#include "app_msg.h"
|
|
#include "asm/efuse.h"
|
|
|
|
#define NTC_USED_INPUT_100K 1//使用内部上拉
|
|
|
|
#if NTC_USED_INPUT_100K
|
|
static u32 efuse_pb00_100k;
|
|
#endif
|
|
|
|
|
|
#if NTC_DET_EN
|
|
|
|
#define NTC_DET_BAD_RES 0 //分压电阻损坏关闭检测
|
|
|
|
#ifndef NTC_DET_DUTY1
|
|
#define NTC_DET_DUTY1 5000 //检测周期
|
|
#endif
|
|
|
|
#ifndef NTC_DET_DUTY2
|
|
#define NTC_DET_DUTY2 10 //检测小周期
|
|
#endif
|
|
|
|
#ifndef NTC_DET_CNT
|
|
#define NTC_DET_CNT 3 //检测次数
|
|
#endif
|
|
|
|
#ifndef NTC_DET_UPPER
|
|
#define NTC_DET_UPPER 322*1000 //正常范围AD值上限,0度时电阻值
|
|
#endif
|
|
|
|
#ifndef NTC_DET_LOWER
|
|
#define NTC_DET_LOWER 44*1000 //正常范围AD值下限,45度时电阻值
|
|
#endif
|
|
|
|
#define NTC_REDCOEFF 10*1000 //温度恢复一定范围后才算正常,防止临界状态,默认设置10k的安全范围,参考100k的电阻
|
|
|
|
|
|
#define NTC_IS_NORMAL(value, offset) (value >= NTC_DET_LOWER+(offset) && value <= NTC_DET_UPPER-(offset))
|
|
#define NTC_IS_BAD_RES(value) (value >= 3273*1000 || value <= 2197) //大于142度或者低于-40
|
|
|
|
|
|
|
|
|
|
enum {
|
|
NTC_STATE_NORMAL = 0,
|
|
NTC_STATE_ABNORMAL,
|
|
};
|
|
|
|
struct ntc_det_t {
|
|
u16 normal_cnt : 4; //温度正常的次数
|
|
u16 cnt : 4; //温度检测的次数
|
|
u16 res_cnt : 4; //分压电阻脱落或损坏
|
|
u16 state : 1; //是否超出范围
|
|
u16 timer;
|
|
};
|
|
static struct ntc_det_t ntc_det = {0};
|
|
extern u8 get_charge_full_flag(void);
|
|
|
|
u16 ntc_det_working()
|
|
{
|
|
return ntc_det.timer;
|
|
}
|
|
|
|
#define NTC_AD_MAX 4096
|
|
|
|
static u32 ntc_ad_ohm(u32 adc)
|
|
{
|
|
return (u32)((adc * efuse_pb00_100k) / ((float)(NTC_AD_MAX - adc)));
|
|
}
|
|
|
|
|
|
static void ntc_det_timer_deal(void *priv)
|
|
{
|
|
u32 value;
|
|
|
|
#if NTC_DET_CNT
|
|
if (ntc_det.cnt == 0) {
|
|
sys_timer_modify(ntc_det.timer, NTC_DET_DUTY2);
|
|
}
|
|
#endif
|
|
|
|
value = adc_get_value(NTC_DET_AD_CH);
|
|
|
|
value = ntc_ad_ohm(value);
|
|
printf("adc %d ohm \n", value);
|
|
|
|
|
|
ntc_det.cnt++;
|
|
|
|
if (NTC_IS_NORMAL(value, (ntc_det.state * NTC_REDCOEFF))) { //温度恢复一定范围后才算正常,防止临界状态,默认设置10k的安全范围
|
|
ntc_det.normal_cnt++;
|
|
} else if (NTC_IS_BAD_RES(value)) {
|
|
ntc_det.res_cnt++;
|
|
}
|
|
if (ntc_det.cnt >= NTC_DET_CNT) {
|
|
if (ntc_det.normal_cnt > NTC_DET_CNT / 2) {
|
|
if (ntc_det.state == NTC_STATE_ABNORMAL) {
|
|
printf("temperature recover, start charge");
|
|
ntc_det.state = NTC_STATE_NORMAL;
|
|
charge_start();
|
|
}
|
|
}
|
|
#if NTC_DET_BAD_RES
|
|
else if (ntc_det.res_cnt > NTC_DET_CNT / 2) {
|
|
printf("bad res, stop det");
|
|
ntc_det_stop();
|
|
}
|
|
#endif
|
|
else {
|
|
if (ntc_det.state == NTC_STATE_NORMAL) {
|
|
printf("temperature is abnormall, stop charge");
|
|
ntc_det.state = NTC_STATE_ABNORMAL;
|
|
charge_close();
|
|
CHARGE_EN(0);
|
|
}
|
|
/* power_set_soft_poweroff(); */
|
|
}
|
|
ntc_det.cnt = 0;
|
|
ntc_det.res_cnt = 0;
|
|
ntc_det.normal_cnt = 0;
|
|
sys_timer_modify(ntc_det.timer, NTC_DET_DUTY1);
|
|
}
|
|
}
|
|
|
|
|
|
void ntc_det_start(void)
|
|
{
|
|
if (ntc_det.timer == 0) {
|
|
printf("ntc det start");
|
|
memset(&ntc_det, 0, sizeof(ntc_det));
|
|
gpio_write(NTC_POWER_IO, 1);
|
|
#if NTC_USED_INPUT_100K
|
|
if (!efuse_pb00_100k) {
|
|
u8 efuse_100k = efuse_get_io_pu_100k();
|
|
if (efuse_100k != 0xff) {
|
|
s8 offset = (efuse_100k & 0x80) ? -(efuse_100k & 0x7F) : efuse_100k;
|
|
efuse_pb00_100k = (u32)((3072 - (524 + offset) * 3) / 0.015f);
|
|
} else {
|
|
printf("PB0_100k not trim\n");
|
|
efuse_pb00_100k = 10 * 1000;
|
|
}
|
|
}
|
|
ASSERT(efuse_pb00_100k > 50 * 1000 && efuse_pb00_100k < 150 * 1000);
|
|
ASSERT(NTC_DETECT_IO == IO_PORTB_00);
|
|
gpio_set_mode(IO_PORT_SPILT(NTC_DETECT_IO), PORT_HIGHZ);
|
|
gpio_hw_set_pull_up(IO_PORT_SPILT(NTC_DETECT_IO), GPIO_PULLUP_100K);
|
|
#else
|
|
gpio_set_mode(IO_PORT_SPILT(NTC_DETECT_IO), PORT_HIGHZ);
|
|
#endif
|
|
|
|
adc_add_sample_ch(NTC_DET_AD_CH);
|
|
adc_delay_set(NTC_DET_AD_CH, 0, 9);//采用不准可以延长采样时间0~15
|
|
ntc_det.timer = sys_timer_add(NULL, ntc_det_timer_deal, NTC_DET_DUTY1);
|
|
}
|
|
}
|
|
|
|
void ntc_det_stop(void)
|
|
{
|
|
if (!get_charge_full_flag() && get_charge_online_flag() && ntc_det.state == NTC_STATE_ABNORMAL) {
|
|
printf("charge protecting, wait recover");
|
|
return;
|
|
}
|
|
if (ntc_det.timer) {
|
|
printf("ntc det stop");
|
|
sys_timer_del(ntc_det.timer);
|
|
ntc_det.timer = 0;
|
|
adc_delete_ch(NTC_DET_AD_CH);
|
|
gpio_set_mode(IO_PORT_SPILT(NTC_POWER_IO), PORT_HIGHZ);
|
|
}
|
|
}
|
|
|
|
#if TCFG_CHARGE_ENABLE
|
|
|
|
static int ntc_msg_entry(int *msg)
|
|
{
|
|
switch (msg[0]) {
|
|
case CHARGE_EVENT_CHARGE_START:
|
|
ntc_det_start();
|
|
break;
|
|
case CHARGE_EVENT_CHARGE_CLOSE:
|
|
ntc_det_stop();
|
|
break;
|
|
case CHARGE_EVENT_LDO5V_KEEP:
|
|
ntc_det_stop();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
APP_MSG_PROB_HANDLER(ntc_msg_entry) = {
|
|
.owner = 0xff,
|
|
.from = MSG_FROM_BATTERY,
|
|
.handler = ntc_event_handler,
|
|
};
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
/* --------------------------------------------------------------------------*/
|
|
/**
|
|
* @brief ntc否可进低功耗查询函数
|
|
*
|
|
* @return 0:不可进
|
|
* 1:可进
|
|
*/
|
|
/* ----------------------------------------------------------------------------*/
|
|
static u8 ntc_idle_query(void)
|
|
{
|
|
if (ntc_det.timer) {
|
|
return 0;
|
|
} else {
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
/* REGISTER_LP_TARGET(ntc_driver_target) = { */
|
|
/* .name = "ntc", */
|
|
/* .is_idle = ntc_idle_query, */
|
|
/* }; */
|
|
|
|
|
|
|
|
#endif
|
|
|