#include "stm32f10x_rcc.h" #include "stm32f10x_gpio.h" #include "stm32f10x_dma.h" #include "ADCSample.h" #include "pid.h" #include "GlobalDefine.h" #include "lib_of_tracker.h" #include "log.h" extern GlobalVariableDef GlobalVariable; extern unsigned char PWMRunFlag; #define NUM_OF_CHANNEL 5 //规则通道ADC采集信号量个数 #define NUM_OF_SAMPLES 10 static unsigned char curridx; static unsigned short ADC_converted_value[NUM_OF_CHANNEL * NUM_OF_SAMPLES]; static float PV_bucker_voltage = 0; static float Motor_current = 0; static float adc_out[NUM_OF_CHANNEL]; static unsigned short current[18] = {0}; void ADCInit() { ADC_InitTypeDef ADCInitStruc; DMA_InitTypeDef DMAInitStruc; RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 ,ENABLE); /*ADC - DMA1C1*/ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); DMAInitStruc.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR; DMAInitStruc.DMA_MemoryBaseAddr = (uint32_t)ADC_converted_value; DMAInitStruc.DMA_DIR = DMA_DIR_PeripheralSRC; DMAInitStruc.DMA_BufferSize = NUM_OF_CHANNEL * NUM_OF_SAMPLES; DMAInitStruc.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMAInitStruc.DMA_MemoryInc = DMA_MemoryInc_Enable; DMAInitStruc.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMAInitStruc.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMAInitStruc.DMA_Mode = DMA_Mode_Circular; DMAInitStruc.DMA_Priority = DMA_Priority_High; DMAInitStruc.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel1,&DMAInitStruc); DMA_Cmd(DMA1_Channel1, ENABLE); //使能DMA时钟 RCC_ADCCLKConfig(RCC_PCLK2_Div2); RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); ADCInitStruc.ADC_Mode = ADC_Mode_Independent; ADCInitStruc.ADC_ScanConvMode = ENABLE;//DISABLE; ADCInitStruc.ADC_ContinuousConvMode = ENABLE;//DISABLE; ADCInitStruc.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//ADC_ExternalTrigConv_T3_TRGO; ADCInitStruc.ADC_DataAlign = ADC_DataAlign_Right; ADCInitStruc.ADC_NbrOfChannel = NUM_OF_CHANNEL; ADC_Init(ADC1, &ADCInitStruc); /* ADC1 regular channel14 configuration */ ADC_RegularChannelConfig(ADC1,ADC_Channel_9, 1, ADC_SampleTime_239Cycles5); //pv 12 ADC_RegularChannelConfig(ADC1,ADC_Channel_10, 2, ADC_SampleTime_239Cycles5); //v-ntc 123 ADC_RegularChannelConfig(ADC1,ADC_Channel_14, 3, ADC_SampleTime_239Cycles5); //电池电压 ADC_RegularChannelConfig(ADC1,ADC_Channel_15, 4, ADC_SampleTime_239Cycles5); //电池电流 ADC_RegularChannelConfig(ADC1,ADC_Channel_8, 5, ADC_SampleTime_239Cycles5); //motor_current ADC_DMACmd(ADC1, ENABLE); // /* Enable ADC1 external trigger */ // ADC_SoftwareStartConvCmd(ADC1, ENABLE); // /* Set injected sequencer length */ // ADC_InjectedSequencerLengthConfig(ADC1, 1); // /* ADC1 injected channel Configuration */ // ADC_InjectedChannelConfig(ADC1, ADC_Channel_8, 1, ADC_SampleTime_71Cycles5); // /* ADC1 injected external trigger configuration */ // ADC_ExternalTrigInjectedConvConfig(ADC1, ADC_ExternalTrigInjecConv_T4_TRGO); // /* Enable automatic injected conversion start after regular one */ // ADC_ExternalTrigInjectedConvCmd(ADC1, ENABLE); /* Enable ADC1 */ ADC_Cmd(ADC1, ENABLE); /* Enable ADC1 reset calibration register */ ADC_ResetCalibration(ADC1); /* Check the end of ADC1 reset calibration register */ while(ADC_GetResetCalibrationStatus(ADC1)); /* Start ADC1 calibration */ ADC_StartCalibration(ADC1); /* Check the end of ADC1 calibration */ while(ADC_GetCalibrationStatus(ADC1)); // clear flag ADC_ClearFlag(ADC1, ADC_FLAG_JEOC); ADC_ClearFlag(ADC1, ADC_FLAG_EOC); ADC_SoftwareStartConvCmd(ADC1, ENABLE); } long _IQsub(long a, long b) { return ((a >= b) ? (a - b) : (b -a)); } long _IQmpy(long x, long y) { long ltemp = x; long temp = y; ltemp = ltemp * temp; ltemp /= 4096; return ltemp; } long RampGen (long input, long output, long step) { long out = input - output; if (out > step) { out = output + step; } else if (out > -step) { out = input; } else { out = output - step; } if (out < 0) { out = 0; } return out; } void SampleCurr (void) { static char flag = 0; static u16 count = 0; long ltemp = 0; int mincurr = 0, maxcurr = 0; int temp; while(ADC_GetFlagStatus(ADC1, ADC_FLAG_JEOC) == RESET){}; ADC_ClearFlag(ADC1, ADC_FLAG_JEOC); temp = ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_1); current[curridx] = temp; if (++curridx >= 10) { curridx = 0; flag = 10; } if( ++count == 100 ) { GlobalVariable.Log.LogWave.WriteFlag = 1; QueueIn(&MyQueue,temp); GlobalVariable.Log.LogWave.WriteFlag = 0; count = 0; } mincurr = maxcurr = current[0]; for (temp = 1; temp < 10; temp++) { ltemp += current[temp]; if (current[temp] > maxcurr) { maxcurr = current[temp]; } if (current[temp] < mincurr) { mincurr = current[temp]; } } ltemp -= (mincurr); if (ltemp >= 0 && flag>=10) { // 电流 ltemp = ltemp/8;// >> 4; // 计算显示值 ltemp = _IQsub (ltemp, 0x5B); ltemp = _IQmpy (ltemp, 392); GlobalVariable.Motor[0].Current = RampGen (ltemp, GlobalVariable.Motor[0].Current, 1); } } /************************************************* Function : GetMotorCurrent() Description : get motor current Input : null Output : GlobalVariable.Motor[0].Motorcurrent Return : null Engineer : tangtao Revision : V0.0 Modified Date : 2021.09.29 Additional Comments : *************************************************/ //void GetMotorCurrent(float *current) //{ // if(PWMRunFlag == 1) // { // *current = ((float)GlobalVariable.Motor[0].Current)/10.0f; //Motor Current // } // else // { // *current = 0; // } //} /************************************************* Function : GetPVBuckerVoltage() Description : PV voltage Input : *voltage Output : *voltage Return : null Engineer : tangtao Revision : V0.0 Modified Date : 2021.09.10 Additional Comments : *************************************************/ void GetPVBuckerVoltage(float *voltage) { char k =0; adc_out[0] = 0; for(k = 0; k < NUM_OF_SAMPLES; k++) { adc_out[0] += (float)ADC_converted_value[k*NUM_OF_CHANNEL]; } PV_bucker_voltage = adc_out[0]; *voltage = PV_bucker_voltage*3.3f*12.914f/40960.0f; } /************************************************* Function : GetTempFromRntc() Return : null Engineer : tangtao Revision : V0.0 Modified Date : 2021.09.10 *************************************************/ void GetTempFromRntc(float R_NTC, float *Temp ) { if(R_NTC <= 4.8f) { *Temp = -9.7509f * R_NTC + 90.173f; } else if(R_NTC > 4.8f && R_NTC <= 10.0f) { *Temp = -3.7804f * R_NTC + 61.663f; } else if(R_NTC > 10.0f && R_NTC <= 14.3f) { *Temp = -2.0663 * R_NTC + 45.304f; } else if(R_NTC > 14.3f && R_NTC <= 22.4f) { *Temp = -1.2697f * R_NTC + 33.619f; } else if(R_NTC > 22.4f && R_NTC <= 28.5f) { *Temp = -0.884f * R_NTC + 25.169f; } else { *Temp = -0.3557f * R_NTC + 7.3795f; } } /************************************************* Function : GetBatteryTemperature() Description : Battery Temperature Input : *temperature Output : *temperature Return : null Engineer : tangtao Revision : V0.0 Modified Date : 2021.09.10 Additional Comments : *************************************************/ void _GetBatteryTemperature(float *temperature) { char k =0; float Rntc; adc_out[1] = 0; for(k = 0; k < NUM_OF_SAMPLES; k++) { adc_out[1] += (float)ADC_converted_value[(k*NUM_OF_CHANNEL) + 1]; } Rntc = (adc_out[1]*1000/(40960 - adc_out[1]))/1000 ; //*temperature = Get_Kelvin_Temperature( (adc_out[1]*1000/(40960 - adc_out[1]))/1000 ); GetTempFromRntc(Rntc , temperature ); } /************************************************* Function : GetBatteryVoltage() Description : 获取adc检测到的电池电压 Input : 存放电池电压变量的指针 Return : 无 Engineer : Lisel Revision : V0.0 Modified Date : 2022.11.23 Additional Comments : 无 *************************************************/ void _GetBatteryVoltage(float *voltage) { char k =0; adc_out[2] = 0; for(k = 0; k < NUM_OF_SAMPLES; k++) { adc_out[2] += (float)ADC_converted_value[(k*NUM_OF_CHANNEL) + 2]; } *voltage = adc_out[2]*3.3f*12.915f/40960.0f; //12.915 : 1+Rup/Rdown = 1 + 56k/4.7k = 12.914 ;Rup,Rdowm电池电压检测电路配置电阻 } /************************************************* Function : GetBatteryCurrent() Description : 获取adc检测到的电池电压 Input : 存放电池电量变量的指针 Return : 无 Engineer : Lisel Revision : V0.0 Modified Date : 2022.11.23 Additional Comments : 无 *************************************************/ void _GetBatteryCurrent(float *current) { char k =0; adc_out[3] = 0; for(k = 0; k < NUM_OF_SAMPLES; k++) { adc_out[3] += (float)ADC_converted_value[(k*NUM_OF_CHANNEL) + 3]; } *current = (adc_out[3] * 33.0f /4096.0f - 165.0f)/5.28f; //芯进电CC6920B (25A),计算公式:Vout = Vcc/2+0.0528*Ip(A), Vcc = 3.3V if(*current < 0.0f) *current = 0; } /************************************************* Function : GetMotorCurrent() Description : get motor current Input : null Output : GlobalVariable.Motor[0].Motorcurrent Return : null Engineer : Huruihong Revision : V0.0 Modified Date : 2023.08.23 Additional Comments : *************************************************/ void GetMotorCurrent(float *current) { char k =0; static float ADC_SO_0 = 0; //drv8701e SO脚有偏置,电机不转时,会有一个初始值,需要减去误差 static unsigned short PowerOnFlag = 0; adc_out[4] = 0; for(k = 0; k < NUM_OF_SAMPLES; k++) { adc_out[4] += (float)ADC_converted_value[(k*NUM_OF_CHANNEL) + 4]; } if((PowerOnFlag == 0) && (PWMRunFlag == 0)) //初始上电时并且电机没有转动时,需要读出初始值,用于纠偏 { ADC_SO_0 = adc_out[4]; PowerOnFlag = 1; } Motor_current = (adc_out[4] - ADC_SO_0)*3.3*11/40960; //(VSO = VCURR*11/10;电路电阻上:1K,下:10K,;V_SO = I_Moter*R偏置*AV;偏置电阻为0.005欧,AV放大倍数为20) if(PWMRunFlag == 1) { *current = Motor_current ; //Motor Current } else { *current = 0; } } void ADCConvert() { ADC_ClearFlag(ADC1,ADC_FLAG_EOC); DMA_Cmd(DMA1_Channel1, DISABLE); DMA1_Channel1->CNDTR = NUM_OF_CHANNEL * NUM_OF_SAMPLES; DMA_Cmd(DMA1_Channel1, ENABLE); ADC_DMACmd(ADC1, ENABLE); ADC1->CR2 |= 0x00000002; ADC_SoftwareStartConvCmd(ADC1, ENABLE); }