#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; }