#include "adc.h" #include "usart.h" #include "stm32f10x_adc.h" #include "stm32f10x_rcc.h" #include "stm32f10x_dma.h" #include "GUNDiscriminate.h" #define SIZE 10 #define debug 1 // 定义一个名为MovingAverage的结构体,用于存储队列的信息,未使用 typedef struct { float queue[SIZE]; // 存储队列元素的数组 int front; // 队列的前端索引 int rear; // 队列的后端索引 int itemCount; // 队列中的元素数量 float sum; // 队列中所有元素的总和 float min; // 队列中的最小元素 float max; // 队列中的最大元素 } MovingAverage; // 初始化队列 MovingAverage ma = {.front = 0, .rear = -1, .itemCount = 0, .sum = 0, .min = 3.4e+38f, .max = 1.2e-38f}; static uint32_t GetR_ValueNew(float AD_Value); typedef struct { int count; int count_DC; int count_AC; int filter_adc; float container; int mode; double Res; }ADCMode; ADCMode Sadcmode={0,0,0,0,0,0,0}; __IO uint16_t AD_Value[AD_NUM]; static void enqueue(float data); static double findAverage() ; static double calculateMovingAverage(float new_value) ; work_mode ADCtoMode(void); work_mode GUNCheck = Normal_operation; void Adc_Init() { GPIO_InitTypeDef GPIO_InitStructure; ADC_InitTypeDef ADC_InitStruct; DMA_InitTypeDef DMA_InitStructure; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //使能MDA1时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_ADC1|RCC_APB2Periph_AFIO,ENABLE); //使能ADC1通道时钟 RCC_ADCCLKConfig(RCC_PCLK2_Div6); //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //GPIO设置为模拟输入 GPIO_Init(GPIOC, &GPIO_InitStructure); ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;//独立模式 ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;//右对齐 ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //转换由软件而不是外部触发启动 ADC_InitStruct.ADC_ContinuousConvMode = ENABLE;//连续转换 ADC_InitStruct.ADC_NbrOfChannel = AD_NUM; ADC_InitStruct.ADC_ScanConvMode = ENABLE;//多通道 ADC_Init(ADC1,&ADC_InitStruct); ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_55Cycles5); //通道1采样周期55.5个时钟周期 ADC_RegularChannelConfig(ADC1, ADC_Channel_13, 2, ADC_SampleTime_55Cycles5); //通道1采样周期55.5个时钟周期 ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 3, ADC_SampleTime_55Cycles5); //通道1采样周期55.5个时钟周期 ADC_RegularChannelConfig(ADC1, ADC_Channel_15, 4, ADC_SampleTime_55Cycles5); //通道1采样周期55.5个时钟周期 DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;//外设存储器地址 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//半字 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//地址不自增 DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)AD_Value;//转移地址 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//半字 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//地址自增 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//传输方向外设-SRAM DMA_InitStructure.DMA_BufferSize = AD_NUM; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;//自动重装载值 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//硬件触发 DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;//优先级 DMA_Init(DMA1_Channel1, &DMA_InitStructure); DMA_Cmd(DMA1_Channel1, ENABLE);//使能通道一 ADC_DMACmd(ADC1, ENABLE);//使能ADC的DMA ADC_Cmd(ADC1, ENABLE); //使能指定的ADC1 ADC_ResetCalibration(ADC1); //使能复位校准 while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位校准结束 ADC_StartCalibration(ADC1); //开启AD校准 while(ADC_GetCalibrationStatus(ADC1)); //等待校准结束 ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能 } const TempRes_TypeDef Temp_R_List[] = { {-40,318.406},{-39,298.823},{-38,280.326},{-37,262.967}, {-36,246.740},{-35,231.604},{-34,217.500},{-33,204.359}, {-32,192.109},{-31,180.684},{-30,170.017},{-29,160.049}, {-28,150.727},{-27,142.001},{-26,133.827},{-25,126.165}, {-24,118.980},{-23,112.237},{-22,105.909},{-21,99.9666}, {-20,94.3861},{-19,89.1441},{-18,84.2191},{-17,79.5912}, {-16,75.2417},{-15,71.1534},{-14,67.3099},{-13,63.6959}, {-12,60.2969},{-11,57.0996},{-10,54.0912},{-9 ,51.2599}, {-8 ,48.5945},{-7, 46.0844},{-6 ,43.7200},{-5 ,41.4919}, {-4 ,39.3916},{-3 ,37.4110},{-2 ,35.5426},{-1, 33.7793}, {0 ,32.1146},{1 ,30.5423},{2 ,29.0568},{3 ,27.6525}, {4 ,26.3247},{5 ,25.0685},{6 ,23.8798},{7 ,22.7543}, {8 ,21.6884},{9 ,20.6785},{10 ,19.7213},{11 ,18.8137}, {12 ,17.9529},{13 ,17.1362},{14 ,16.3611},{15 ,15.6251}, {16 ,14.9262},{17 ,14.2623},{18 ,13.6313},{19 ,13.0316}, {20 ,12.4613},{21 ,11.9190},{22 ,11.4031},{23 ,10.9121}, {24 ,10.4449},{25 ,10.0000},{26 ,9.57638},{27 ,9.17289}, {28 ,8.78847},{29 ,8.42215},{30 ,8.07300},{31 ,7.74013}, {32 ,7.42271},{33 ,7.11995},{34 ,6.83113},{35 ,6.55553}, {36 ,6.29249},{37 ,6.04139},{38 ,5.80162},{39 ,5.57263}, {40 ,5.35389},{41 ,5.14488},{42 ,4.94514},{43 ,4.75421}, {44 ,4.57166},{45 ,4.39708},{46 ,4.23009},{47 ,4.07032}, {48 ,3.91743},{49 ,3.77108},{50 ,3.63097},{51 ,3.49680}, {52 ,3.36829},{53 ,3.24517},{54 ,3.12719},{55 ,3.01411}, {56 ,2.90571},{57 ,2.80175},{58 ,2.70205},{59 ,2.60641}, {60 ,2.51463},{61 ,2.42655},{62 ,2.34200},{63 ,2.26081}, {64 ,2.18285},{65 ,2.10795},{66 ,2.03600},{67 ,1.96685}, {68 ,1.90039},{69 ,1.83649},{70 ,1.77506},{71 ,1.71597}, {72 ,1.65913},{73 ,1.60444},{74 ,1.55181},{75 ,1.50116}, {76 ,1.45240},{77 ,1.40544},{78 ,1.36023},{79 ,1.31667}, {80 ,1.27472},{81 ,1.23429},{82 ,1.19533},{83 ,1.15778}, {84 ,1.12158},{85 ,1.08667},{86 ,1.05301},{87 ,1.02055}, {88 ,0.98923},{89 ,0.95901},{90 ,0.92986},{91 ,0.90172}, {92 ,0.87456},{93 ,0.84834},{94 ,0.82303},{95 ,0.79859}, {96 ,0.77498},{97 ,0.75218},{98 ,0.73015},{99 ,0.70886}, {100,0.68830},{101,0.66842},{102,0.64921},{103,0.63064}, {104,0.61269},{105,0.59533},{106,0.57854},{107,0.56230}, {108,0.54659},{109,0.53139},{110,0.51669},{111,0.50246}, {112,0.48869},{113,0.47536},{114,0.46246},{115,0.44997}, {116,0.43787},{117,0.42616},{118,0.41481},{119,0.40382}, {120,0.39317},{121,0.38286},{122,0.37286},{123,0.36317}, {124,0.35377},{125,0.34467}, } ; static uint16_t Temp_R_Num = sizeof(Temp_R_List) / sizeof(TempRes_TypeDef); int16_t FindTemperature(float r_value) { uint16_t high = Temp_R_Num-1; uint16_t low = 0,mid =0; if( (r_value < Temp_R_List[high].R_Value) || (r_value > Temp_R_List[low].R_Value) ) return 0xFFF; // while (low <= high) { mid = (low + high)/2; if (r_value > Temp_R_List[mid].R_Value) { high = mid - 1; //降序 //low = mid+1; //升序 } else if (r_value < Temp_R_List[mid].R_Value) { low = mid+1; //high = mid - 1; } else { return Temp_R_List[mid].TemperatureValue; } } return Temp_R_List[low].TemperatureValue; } Volt_sampldata Volt_SamplData; Filter_variable Filter_Variable[AD_NUM]; void CC_Voltage_Sampl(void); void TEMP1_Voltage_Sampl(void); void GUN_TEMP_Sampl(void); void KL30_Voltage_Sampl(void); int16_t Get_TEMP1(void); int16_t Get_GUN_TEMP(void); float Get_KL30_Volt(void); work_mode Get_WorkMode(void); get_sampl_data Get_Sampl_Data = { .Resistance_Value=0, .TEMP1=Get_TEMP1, .GUN_TEMP=Get_GUN_TEMP, .KL30_Volt=Get_KL30_Volt, .WorkMode=Get_WorkMode, }; sampl_funtion Sampl_Funtion = { .CC_Voltag=CC_Voltage_Sampl, .TEMP1_Voltage=TEMP1_Voltage_Sampl, .GUN_TEMP=GUN_TEMP_Sampl, .KL30_Voltage=KL30_Voltage_Sampl, }; void Voltage_Filter(uint16_t AD_Value,uint8_t sub,float *data) { if(Filter_Variable[sub].Flag) { if(Filter_Variable[sub].Sum!=0) { Filter_Variable[sub].Sum/=20; Filter_Variable[sub].volt_data=Filter_Variable[sub].Sum*3.3/4096; *data=Filter_Variable[sub].volt_data; } Filter_Variable[sub].Sum=0; Filter_Variable[sub].Flag=0; } else { Filter_Variable[sub].Count++; Filter_Variable[sub].Sum+=AD_Value; if(Filter_Variable[sub].Count==20) { Filter_Variable[sub].Flag=1; Filter_Variable[sub].Count=0; } } } void TEMP1_Voltage_Sampl() { static float data; uint16_t value=AD_Value[ADC_TEMP1]; Voltage_Filter(value,ADC_TEMP1,&data); Volt_SamplData.TEMP1_Data=FindTemperature(4.9/data-1); } void KL30_Voltage_Sampl() { static float data; uint16_t value=AD_Value[VIN_AD]; Voltage_Filter(value,CC_AD,&data); Volt_SamplData.KL30_Volt = data*11+0.25f; } void GUN_TEMP_Sampl() { static float data; uint16_t value=AD_Value[TEMPL_AD]; Voltage_Filter(value,TEMPL_AD,&data); Volt_SamplData.GUN_TempData=FindTemperature(4.9/data-1); } static uint32_t value1_z; static uint32_t value1_v; static uint32_t value1_flg; static uint32_t value1_sum; static float r; static int mode = 0; static int flag = 0; void CC_Voltage_Sampl() { static float data; uint16_t value=AD_Value[CC_AD]; uint16_t value1,sum; value1 = AD_Value[CC_AD]; // printf("value1=%d\r\n",value1); if(value1_flg) { value1_z = value1_z /60; value1_v = 33000 / 4096 * value1_z; Volt_SamplData.CC_Volt = (float)value1_v / 10000; // printf("R %f\r\n",Volt_SamplData.CC_Volt); // r = (7.0f*Volt_SamplData.CC_Volt*1.022/(20.0f-7.0f*Volt_SamplData.CC_Volt*1.022))*0.9414226; // GUNCheck = ADCtoMode(); // printf("value=%.5f r=%.5f mode=%d\r\n",Volt_SamplData.CC_Volt,r,mode); value1_flg = 0; value1_z = 0; value1_v = 0; } else { if(value1_sum < 60) { value1_z += value1; value1_sum++; } else { value1_sum = 0; value1_flg = 1; } } } int16_t Get_TEMP1() { return Volt_SamplData.TEMP1_Data; } int16_t Get_GUN_TEMP() { return Volt_SamplData.GUN_TempData; } float Get_KL30_Volt() { return Volt_SamplData.KL30_Volt;//ADS1015采样 } work_mode last_Stat_work = Normal_operation; work_mode This_State_work = Normal_operation; enum GUNState SUMStateLast = NO_GUN; work_mode Get_WorkMode() { return This_State_work; } void Scan_work(void) { static uint32_t GUNFLAGCount = 0; enum GUNState GUNState= Get_R_GUNState(Get_R_Value()); work_mode SUMState = Normal_operation; if( GUNState == AC_GUN) { SUMState = AC_Charging; } else if( (GUNState == DC_adapter)|| (GUNState == DC_GUN)) { SUMState = DC_Charging; } else { SUMState = Normal_operation; } if(SUMState != last_Stat_work) { GUNFLAGCount = 0; last_Stat_work = SUMState; } else if(SUMState == This_State_work) { GUNFLAGCount = 0; } else { GUNFLAGCount++; if(GUNFLAGCount >= 2) { This_State_work = last_Stat_work; SUMStateLast = GUNState; GUNFLAGCount = 0; } } } /*函数名:ADCtoMode 返回值:枚举类型 work_mode(0:交流 1:直流 3:其他) 函数流程:过滤前40个adc采样,2.335V(下拉5Ω电压)以上为一个区间,2.3080~2.335(4.5~5Ω)为一个区间 其他为一个区间进行分区计算阻值来减小电源影响,然后将计算出的阻值进行判断; 判断区间有3个:0-2.1为交流,4.5(4.3)-5.1(5.2)为直流,<0或者2.1-4.5(4.3)或者>5.1(5.2)为未插枪 判定交直流模式*/ work_mode ADCtoMode(void) { if(Volt_SamplData.CC_Volt>2.335) { // r = (7.0f*Volt_SamplData.CC_Volt*1.0256/(20.0f-7.0f*Volt_SamplData.CC_Volt*1.0256))*0.9523809; r = (7.0f*Volt_SamplData.CC_Volt/(20.0f-7.0f*Volt_SamplData.CC_Volt))*0.9523809; } else if(Volt_SamplData.CC_Volt>2.3080 &&Volt_SamplData.CC_Volt<2.335) { // r = (7.0f*Volt_SamplData.CC_Volt*1.022/(20.0f-7.0f*Volt_SamplData.CC_Volt*1.022))*0.9414226; r = (7.0f*Volt_SamplData.CC_Volt/(20.0f-7.0f*Volt_SamplData.CC_Volt))*0.9414226; } else { r = (7.0f*Volt_SamplData.CC_Volt/(20.0f-7.0f*Volt_SamplData.CC_Volt)); } Get_Sampl_Data.Resistance_Value = r; // Sadcmode.Res = calculateMovingAverage(r); if(r>4.3&&r<=5.5) { Sadcmode.count_DC++; Sadcmode.count_AC = 0; } else if(r<=2.1&&r>=0.05) { Sadcmode.count_AC++; Sadcmode.count_DC = 0; } if((r>2.1&&r<4.0)||r>5.2||r<0.05) { mode = 0; return Normal_operation ; } if(Sadcmode.count_DC > 20 || Sadcmode.count_AC > 20) { if(Sadcmode.count_DC > 20) { Sadcmode.count_DC = 0; mode = 2; return DC_Charging ; } if(Sadcmode.count_AC > 20) { Sadcmode.count_AC = 0; mode = 1; return AC_Charging ; } } return Normal_operation ; } float Get_R_Value(void) { float CC_CC2Vol = Volt_SamplData.CC_Volt; CC_CC2Vol = (Volt_SamplData.CC_Volt*5.1f)/(5.0f-Volt_SamplData.CC_Volt); CC_CC2Vol = (10.0*CC_CC2Vol)/(10.0-CC_CC2Vol); Get_Sampl_Data.Resistance_Value = CC_CC2Vol; return CC_CC2Vol; } /*取平均滤值算法,未使用*/ // 将新元素添加到队列中的函数 void enqueue(float data) { // 如果队列已满 if(ma.itemCount == SIZE){ // 从总和中减去队列前端的元素 ma.sum -= ma.queue[ma.front]; // 如果队列前端的元素是最小值或最大值,则重置最小值和最大值 if(ma.queue[ma.front] == ma.min) { ma.min = 3.4e+38f; } if(ma.queue[ma.front] == ma.max) { ma.max = 1.2e-38f; } // 前端索引向前移动一位 ma.front++; // 如果前端索引到达队列的末尾,则将其重置为0 if(ma.front == SIZE) { ma.front = 0; } // 元素数量减1 ma.itemCount--; } // 将新元素添加到队列的后端 ma.queue[ma.rear] = data; // 将新元素添加到总和中 ma.sum += data; // 如果新元素小于最小值,则更新最小值 if(data < ma.min) { ma.min = data; } // 如果新元素大于最大值,则更新最大值 if(data > ma.max) { ma.max = data; } // 后端索引向后移动一位 ma.rear++; // 如果后端索引到达队列的末尾,则将其重置为0 if(ma.rear == SIZE) { ma.rear = 0; } // 元素数量加1 ma.itemCount++; } // 计算队列中元素的平均值的函数 double findAverage() { // 如果队列中的元素数量小于等于2,则返回-1,因为我们需要去除最大值和最小值后再计算平均值 if(ma.itemCount <= 2) { return -1; } // 返回去除最大值和最小值后的平均值 return (double)((ma.sum - ma.min - ma.max) / (ma.itemCount - 3)); } // 添加新元素并计算平均值的函数 double calculateMovingAverage(float new_value) { enqueue(new_value); // 只有当队列满时,才计算平均值 if(ma.itemCount == SIZE) { return findAverage(); } // 如果队列未满,返回-1 return -1; } static uint32_t GetR_ValueNew(float AD_Value) { float R = (5.1f*AD_Value)/(5.0f-AD_Value); return (uint32_t)R; }