Files
checker_slave/source/elec_det/hardware/power.c

537 lines
13 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "power.h"
#include "base/utility.h"
#include "gpio_cfg.h"
#include "base/delay.h"
#define PowerCurr_AD_BUF_LEN 40
#define POWER_SET_COUNT 20
static volatile CurrentSample_Range_eu latest_range = Current_Max;
static volatile PowerInfo_st def_power_st;
//static uint16_t PowerCurr_AD_buf[PowerCurr_AD_BUF_LEN];
static volatile float f_cur_k;
static volatile float f_cur_b;
static volatile uint8_t uc_power_cal_flag = 0;
volatile PowerInfo_st powerinfo_arrayst[POWER_SET_COUNT] ;
/*
@brief 获取内部基准1.2V电压对应的AD
*/
uint32_t Power_GetBaseVAD()
{
// y1 = kx1+b y2=kx2+b y1-y2/x1-x2
// uint16_t adv_buf[10];
// uint32_t temp_v;
// GetADC0_Value(ADC_CHANNEL_17,adv_buf,10) ;
// Bubble_Sort_u16(adv_buf,10);
// return (adv_buf[4]+adv_buf[5]+adv_buf[6]+adv_buf[7])>>2;
return (uint32_t)(1.2f/3.3f*4096);
}
void Power_CurCalibration()
{
uint16_t adv_buf[10],adv2v5,adv1v25;
uc_power_cal_flag = 1;
GetADC1_Value(VCC_2V5_CH,adv_buf,10) ;
Bubble_Sort_u16(adv_buf,10);
adv2v5 = (adv_buf[4]+adv_buf[5]+adv_buf[6]+adv_buf[7])>>2;
GetADC1_Value(VCC_1V25_CH,adv_buf,10) ;
Bubble_Sort_u16(adv_buf,10);
adv1v25 = (adv_buf[4]+adv_buf[5]+adv_buf[6]+adv_buf[7])>>2;
f_cur_k = 1.245f/((adv2v5 - adv1v25)+1);
f_cur_b = 2.49f-f_cur_k*adv2v5;
// GetADC0_Value(VCC_1V25_CH,adv_buf,10) ;
// Bubble_Sort_u16(adv_buf,10);
// adv1v25 = (adv_buf[4]+adv_buf[5]+adv_buf[6]+adv_buf[7])>>2;
//
// f_cur_k = 1.25f/((adv2v5 - adv1v25)+1);
// f_cur_b = 2.5f-f_cur_k*adv2v5;
}
/*
@brief 将获取的ADC值转换为电压值
@param1 ul_adv 采样AD原始值
@rtv 返回AD采集到的电压值 扩大1000000倍
*/
uint32_t Power_ADVGetCalVal_106(uint16_t ul_adv)
{
if(uc_power_cal_flag == 0)
{
Power_CurCalibration();
}
return (uint32_t)((f_cur_k*ul_adv+f_cur_b)*1000000);
}
/*
@brief 采样高电平电压
*/
uint32_t Power_GetHPowerV()
{
uint32_t adv;
uint16_t adv_buf[10];
Power_CurCalibration();
GetADC1_Value(V_LA_H_CH,adv_buf,10) ;
Bubble_Sort_u16(adv_buf,10);
adv = (adv_buf[4]+adv_buf[5]+adv_buf[6]+adv_buf[7])>>2;
adv = Power_ADVGetCalVal_106(adv);
adv = adv*V_PARAM_1/100000;
return adv;
}
/*
@brief 采样总线输出电压
*/
uint32_t Power_GetBousV()
{
uint32_t abus_v,bbus_v;
uint16_t adv_buf[10];
uint32_t hbus_v=0;
Power_CurCalibration();
GetADC1_Value(AD_OUTA_CH,adv_buf,10) ;
Bubble_Sort_u16(adv_buf,10);
abus_v = (adv_buf[4]+adv_buf[5]+adv_buf[6]+adv_buf[7])>>2;
GetADC1_Value(AD_OUTB_CH,adv_buf,10) ;
Bubble_Sort_u16(adv_buf,10);
bbus_v = (adv_buf[4]+adv_buf[5]+adv_buf[6]+adv_buf[7])>>2;
if(bbus_v > abus_v)
{
abus_v = bbus_v;
}
abus_v = Power_ADVGetCalVal_106(abus_v);
abus_v = abus_v*11/100000;
// hbus_v=Power_GetHPowerV();
//? 验证电压失调
// 电压相差过大的时候输出一个离谱的值
// if((hbus_v>abus_v+10)||(abus_v>hbus_v+10)){
// abus_v=500;
// }
return abus_v;
}
/*
@brief 采样中电平电压
*/
uint32_t Power_GetMPowerV()
{
int32_t adv;
uint16_t adv_buf[10];
GetADC1_Value(V_LA_M_CH,adv_buf,10) ;
Bubble_Sort_u16(adv_buf,10);
adv = (adv_buf[4]+adv_buf[5]+adv_buf[6]+adv_buf[7])>>2;
adv = Power_ADVGetCalVal_106(adv);
adv = adv*V_PARAM_1/100000;
return adv;
}
/*
typedef enum{
R510_0uA_32uA_UC = (uint8_t)0,//x201
R510_0uA_580uA_MC = (uint8_t)1,//x11
R100_0uA_160uA_UC = (uint8_t)2,//x201
R100_0p2mA_3mA_MC = (uint8_t)3,//x11
R10_0p1mA_1p6mA_UC = (uint8_t)4,//x201
R10_2mA_30mA_MC = (uint8_t)5,//x11
Current_Max = (uint8_t)6,
Current_SampleR_OFF = (uint8_t)9,
} CurrentSample_Range_eu;
*/
/*
@brief 通过采样adc换算电流
@param adv adc 采样值
@param rang 采样电阻
@rtv uint32_t 电流值 0.1uA
*/
uint32_t Power_ConvCur(uint16_t adv,CurrentSample_Range_eu range)
{
uint32_t ul_R,ul_Mut;
uint32_t ul_adv = Power_ADVGetCalVal_106(adv);
switch(range)
{
case R510_0uA_32uA_UC: ul_R = 510; ul_Mut = 201 ; break;
case R510_0uA_580uA_MC: ul_R = 510; ul_Mut = 11; break;
case R100_0uA_160uA_UC: ul_R = 100; ul_Mut = 201; break;
case R100_0p2mA_3mA_MC: ul_R = 100; ul_Mut = 11; break;
case R10_0p1mA_1p6mA_UC: ul_R = 10; ul_Mut = 201; break;
case R10_2mA_30mA_MC: ul_R = 10; ul_Mut = 11; break;
case Current_Max: ul_R = 10; ul_Mut = 1; break;
case Current_SampleR_OFF: ul_R = 510; ul_Mut = 1;break;
default: ul_R = 510; ul_Mut = 1;break;
}
ul_adv = (ul_adv*100 / ul_R /ul_Mut+4)/10;
return ul_adv;
}
//根据电流大小的范围,设置采样电阻
CurrentSample_Range_eu Power_SetSampleCurrentRange(CurrentSample_Range_eu range)
{
switch(range)
{
case R510_0uA_32uA_UC: R510_SW_ON; R100_SW_OFF; R10_SW_OFF; break;
case R510_0uA_580uA_MC: R510_SW_ON; R100_SW_OFF; R10_SW_OFF; break;
case R100_0uA_160uA_UC: R100_SW_ON; R510_SW_OFF; R10_SW_OFF; break;
case R100_0p2mA_3mA_MC: R100_SW_ON; R510_SW_OFF; R10_SW_OFF; break;
case R10_0p1mA_1p6mA_UC: R10_SW_ON; R510_SW_OFF; R100_SW_OFF; break;
case R10_2mA_30mA_MC: R10_SW_ON; R510_SW_OFF; R100_SW_OFF; break;
case Current_Max: R510_SW_ON; R100_SW_ON; R10_SW_ON;break;
case Current_SampleR_OFF: R510_SW_OFF;R100_SW_OFF; R10_SW_OFF;break;
default: range = Current_Max; R510_SW_ON; R100_SW_ON; R10_SW_ON;break;
}
latest_range = range;
return latest_range;
}
/*
@brief 设置电阻采样通道和AD采样配置
*/
CurrentSample_Range_eu Power_SetSampleRange_Seep(CurrentSample_Range_eu range , uint32_t speed)
{
switch(range)
{
case R510_0uA_32uA_UC: ADC_CurChnnelSet(AN_UA_CH,speed); break;
case R510_0uA_580uA_MC: ADC_CurChnnelSet(AN_MAL_CH,speed); break;
case R100_0uA_160uA_UC: ADC_CurChnnelSet(AN_UA_CH,speed); break;
case R100_0p2mA_3mA_MC: ADC_CurChnnelSet(AN_MAL_CH,speed); break;
case R10_0p1mA_1p6mA_UC: ADC_CurChnnelSet(AN_UA_CH,speed); break;
case R10_2mA_30mA_MC: ADC_CurChnnelSet(AN_MAL_CH,speed); break;
case Current_Max: ADC_CurChnnelSet(AN_MAL_CH,speed); break;
case Current_SampleR_OFF: ADC_CurChnnelSet(AN_MAL_CH,speed);break;
default: ADC_CurChnnelSet(AN_MAL_CH,speed);break;
}
return Power_SetSampleCurrentRange(range);
}
//获取总线电流
uint32_t Power_GetCurrent(void)
{
uint32_t adv;
uint32_t count;
CurrentSample_Range_eu range = latest_range;//档位保存
CurrentSample_Range_eu set_range;
uint32_t adv_base = Power_GetBaseVAD();
if(adv_base < 500)
return 0;
set_range = Power_SetSampleCurrentRange(R10_2mA_30mA_MC);
StartADC2Channel(AN_MAL_CH,ADC_SPEED_SLOW);
delay_us(300);
GetADC_Fast(ADC_CURR_DE);
adv = 0;
for(count = 0; count < 4; count++)
{
adv += GetADC_Fast(ADC_CURR_DE);
}
adv >>= 2;
if(adv > 250){
adv = Power_ConvCur(adv,set_range);//0.1uA
adv = (adv+4)/10;
Power_SetSampleCurrentRange(range);
return adv;
}
set_range = Power_SetSampleCurrentRange(R100_0p2mA_3mA_MC);
StartADC2Channel(AN_MAL_CH,ADC_SPEED_SLOW);
delay_us(300);
GetADC_Fast(ADC_CURR_DE);
adv = 0;
for(count = 0; count < 4; count++)
{
adv += GetADC_Fast(ADC_CURR_DE);
}
adv >>= 2;
if(adv > 250){
adv = Power_ConvCur(adv,set_range);//0.1uA
adv = (adv+4)/10;
Power_SetSampleCurrentRange(range);
return adv;
}
set_range = Power_SetSampleCurrentRange(R10_0p1mA_1p6mA_UC);
StartADC2Channel(AN_UA_CH,ADC_SPEED_SLOW);
delay_ms(2);
GetADC_Fast(ADC_CURR_DE);
adv = 0;
for(count = 0; count < 4; count++)
{
adv += GetADC_Fast(ADC_CURR_DE);
}
adv >>= 2;
if(adv > 250){
adv = Power_ConvCur(adv,set_range);//0.1uA
adv = (adv+4)/10;
Power_SetSampleCurrentRange(range);
return adv;
}
set_range = Power_SetSampleCurrentRange(R100_0uA_160uA_UC);
StartADC2Channel(AN_UA_CH,ADC_SPEED_SLOW);
delay_ms(3);
GetADC_Fast(ADC_CURR_DE);
adv = 0;
for(count = 0; count < 8; count++)
{
adv += GetADC_Fast(ADC_CURR_DE);
}
adv >>= 3;
adv = Power_ConvCur(adv,set_range);//0.1uA
adv = (adv+4)/10;
Power_SetSampleCurrentRange(range);
return adv;
}
/*
@brief 电源调压准备,计数频率和电压的线性关系
@rtv 返回值0 成功 其他失败
*/
uint8_t PowerCalPrapare(void)
{
//YM硬件直接由公式计算
return 0;
}
//防止突然上电,导致电源崩溃
static void PowerUpFilter(uint16_t tag_dac)
{
uint16_t us_lastdac_h = DAC_GetDataOutputValue(DAC_Channel_1);
if(us_lastdac_h > (tag_dac + 200))
{
while(us_lastdac_h > tag_dac)
{
if((tag_dac + 100) < us_lastdac_h)
{
us_lastdac_h -= 50;
C_H_DAC_Set(us_lastdac_h);
}else{
us_lastdac_h = tag_dac;
C_H_DAC_Set(us_lastdac_h);
}
delay_ms(10);
}
}
}
//电压调节的关系为线性函数
void PowerCalibration(PowerInfo_st* info_st)
{
float vlp,vlm,v_adc_h,v_adc_m;
uint16_t us_basedac_h,us_basedac_m;
uint16_t us_lastdac_h,us_lastdac_m;
uint16_t us_powderv;
uint16_t us_timeout ;
uint32_t diff=0;
uint16_t ok_flg = 0;
uint8_t uc_down_up_flag = 0;
if(info_st->V_LAH < info_st->V_LAM )
{
info_st->V_LAH_DAC = 0;
info_st->V_LAM_DAC = 0;
return ;
}
PAout(LAVC_M_Pin_Nu)=0;PBout(OUTAH_Pin_Nu)=0;
PBout(OUTBL_Pin_Nu)=0;PBout(OUTAL_Pin_Nu)=0;
PCout(POWER_ON_Pin_Nu) = 1;
vlp = info_st->V_LAH;
vlp /= 10;
//(VLP-1.229V)/178K + (VDAC-1.229V)/20K = 0.1229mA
v_adc_h =( 0.1229- (vlp-1.229)/V_PARAM_2)*20+1.229;
us_timeout = 80;
info_st->V_LAH_DAC = 0;
us_basedac_h = (uint16_t)( v_adc_h/3.3 * 4096);
PowerUpFilter(us_basedac_h);
us_lastdac_h = 0;
//us_basedac_h = 250;
ok_flg = 0;
uc_down_up_flag = 0;
while(us_timeout > 0)
{
us_timeout--;
C_H_DAC_Set(us_basedac_h);
us_lastdac_h = us_basedac_h;
switch(uc_down_up_flag)
{
case 0:delay_os_ms(100);break;//首次调压
case 1:delay_os_ms(50);break;//降压
case 2:delay_os_ms(10);break;//升压
}
us_powderv = Power_GetHPowerV();
diff = us_powderv > info_st->V_LAH?us_powderv-info_st->V_LAH:info_st->V_LAH-us_powderv;
if(diff < 2)
{
ok_flg++;
if(ok_flg > 2)
{
info_st->V_LAH_DAC = us_basedac_h;
break;
}else{
continue;
}
}
diff = diff *2;
ok_flg = 0;
if( us_powderv > info_st->V_LAH)
{
us_basedac_h += diff;
uc_down_up_flag = 1;
}else{
us_basedac_h -= diff;
uc_down_up_flag = 2;
}
if(us_basedac_h < 20)
us_basedac_h = 20;
if(us_basedac_h > 4050)
us_basedac_h = 4050;
}
if(info_st->V_LAH_DAC == 0)
return;
//(VM-2.5V)/20k+(VDAC-2.5V)/4.7K = 0.25mA
us_timeout = 100;
info_st->V_LAM_DAC = 0;
vlm = info_st->V_LAM ;
vlm /= 10;
v_adc_m =( 0.25- (vlm-2.5)/20)*4.7+2.5;
us_basedac_m = (uint16_t)(v_adc_m / 3.3 * 4096);
//us_lastdac_m = 250;
ok_flg = 0;
uc_down_up_flag = 0;
while( us_timeout > 0)
{
us_timeout--;
C_M_DAC_Set(us_basedac_m);
us_lastdac_m = us_basedac_m;
switch(uc_down_up_flag)
{
case 0:delay_os_ms(50);break;//首次调压
case 1:delay_os_ms(40);break;//降压
case 2:delay_os_ms(30);break;//升压
default:delay_os_ms(50);break;
}
us_powderv = Power_GetMPowerV();
diff = us_powderv > info_st->V_LAM?us_powderv-info_st->V_LAM:info_st->V_LAM-us_powderv;
if(diff < 2)
{
ok_flg++;
if(ok_flg > 2)
{
info_st->V_LAM_DAC = us_basedac_m;
break;
}
else{
continue;
}
}
ok_flg = 0;
diff = diff *10;
if( us_powderv > info_st->V_LAM)
{
us_basedac_m += diff;
uc_down_up_flag = 1;
}else{
uc_down_up_flag = 2;
us_basedac_m -= diff;
}
if(us_basedac_m < 100)
us_basedac_m = 100;
if(us_basedac_m > 4050)
us_basedac_m = 4050;
}
}
//设置总线电压
void PowerSetVoltage(PowerInfo_st* info_st)
{
memcpy((void *)&def_power_st,info_st,sizeof(PowerInfo_st));
PowerUpFilter(info_st->V_LAH_DAC);
C_H_DAC_Set(info_st->V_LAH_DAC);
C_M_DAC_Set(info_st->V_LAM_DAC);
POWER_ON;
//? 验证电压失调
// delay_ms(5);
// C_H_DAC_Set(info_st->V_LAH_DAC);
// C_M_DAC_Set(info_st->V_LAM_DAC);
}
//获取当前电压配置值
void PowerGetSet(PowerInfo_st* info_st)
{
uint16_t h_dac = DAC_GetDataOutputValue(DAC_Channel_1);
uint16_t m_dac = DAC_GetDataOutputValue(DAC_Channel_2);
info_st->V_LAH = 0;
info_st->V_LAH_DAC = h_dac;
if(h_dac == def_power_st.V_LAH_DAC)
{
info_st->V_LAH = def_power_st.V_LAH;
}
info_st->V_LAM = 0;
info_st->V_LAM_DAC = h_dac;
if(m_dac == def_power_st.V_LAM_DAC)
{
info_st->V_LAM_DAC = m_dac;
}
}
/*
@brief 设置总线电压
@param h_v/10 设置高电平电压
@param m_v/10 设置中电平电压
@rtv 0 执行成功 1 执行失败
*/
uint8_t PowerCalibration_set(uint16_t h_v,uint16_t m_v)
{
uint32_t ul_index = 0;
PowerInfo_st powerinfo_st;
rt_memset(&powerinfo_st,0,sizeof(PowerInfo_st));
while(ul_index < POWER_SET_COUNT)
{
//if( powerinfo_arrayst[ul_index].V_LAH == h_v && powerinfo_arrayst[ul_index].V_LAM == m_v)
if( powerinfo_arrayst[ul_index].V_LAH == h_v)
{
break;
}
ul_index++;
}
//在现有电压列表中能够查询到校准后的电压
if(ul_index < POWER_SET_COUNT)
{
memcpy((void *)&powerinfo_st,(void *)&powerinfo_arrayst[ul_index],sizeof(PowerInfo_st));
PowerSetVoltage(&powerinfo_st);
return 0;
}
powerinfo_st.V_LAH = h_v;
powerinfo_st.V_LAM = m_v;
PowerCalibration(&powerinfo_st);
if(powerinfo_st.V_LAH_DAC == 0 || powerinfo_st.V_LAM_DAC == 0)
{
LED1_Out = 1;
return 1;
}
//校准完成后,设置总线电压
PowerSetVoltage(&powerinfo_st);
//查找为使用的配置缓存,将新设置的电压保存
ul_index = 0;
while(ul_index < POWER_SET_COUNT)
{
if( powerinfo_arrayst[ul_index].V_LAH_DAC == 0 || powerinfo_arrayst[ul_index].V_LAM_DAC == 0)
{
memcpy((void *)&powerinfo_arrayst[ul_index],&powerinfo_st,sizeof(PowerInfo_st));
break;
}
ul_index++;
}
return 0;
}