/* * uer_adc.c * * Created on: 2025年7月13日 * Author: 罗成 */ #include #include "user_adc.h" #include "user_charge.h" #include "my_math.h" #include "tools.h" static uint8_t tmpIdx = 0; static uint16_t tmpValue[ADC_COUNT * ADC_BUFFER_SIZE] = {0}; //温度 static int16_t Calibrattion_Val = 0; static adc_data_s adc_data = { .left_ntc = 0, .right_ntc = 0, #if TEMPE_OWNER == 1 .tmp_chip = 0.0f, #endif }; static adc_upload_func adc_upload = NULL; //static bool set_rand_seek = false; static void upload_adc_value(bool tmp_stat); /******************************************************************************* * @函数名称 ADC_Function_Init * @函数说明 ADC初始化 * @输入参数 无 * @输出参数 无 * @返回参数 无 *******************************************************************************/ static void ADC_Function_Init(void) { ADC_InitTypeDef ADC_InitStructure={0}; GPIO_InitTypeDef GPIO_InitStructure={0}; NVIC_InitTypeDef NVIC_InitStructure; ADC_GPIO_RCC_ENABLE; ADC_RCC_ENABLE; RCC_ADCCLKConfig(RCC_PCLK2_Div8); GPIO_InitStructure.GPIO_Pin = LEFT_NTC_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_Init(LEFT_NTC_GPIO, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = RIGHT_NTC_PIN; GPIO_Init(RIGHT_NTC_GPIO, &GPIO_InitStructure); ADC_DeInit(ADC_CHANNEL); ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; ADC_InitStructure.ADC_ScanConvMode = ENABLE; ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; #if TEMPE_OWNER == 1 ADC_InitStructure.ADC_NbrOfChannel = 3; #else ADC_InitStructure.ADC_NbrOfChannel = 2; #endif ADC_Init(ADC_CHANNEL, &ADC_InitStructure); // Configure channel sequence ADC_RegularChannelConfig(ADC_CHANNEL, LEFT_NTC_CHANNEL, 1, ADC_SampleTime_239Cycles5); ADC_RegularChannelConfig(ADC_CHANNEL, RIGHT_NTC_CHANNEL, 2, ADC_SampleTime_239Cycles5); // Enable DMA for ADC ADC_DMACmd(ADC_CHANNEL, ENABLE); // Enable ADC ADC_Cmd(ADC_CHANNEL, ENABLE); ADC_ResetCalibration(ADC_CHANNEL); while(ADC_GetResetCalibrationStatus(ADC_CHANNEL)); ADC_StartCalibration(ADC_CHANNEL); while(ADC_GetCalibrationStatus(ADC_CHANNEL)); Calibrattion_Val = Get_CalibrationValue(ADC_CHANNEL); PRINT("Calibrattion_Val=%d\n", Calibrattion_Val); #if TEMPE_OWNER == 1 ADC_TempSensorVrefintCmd(ENABLE); #endif } /********************************************************************* * @fn DMA_Tx_Init * * @brief Initializes the DMAy Channelx configuration. * * @param DMA_CHx - x can be 1 to 7. * ppadr - Peripheral base address. * memadr - Memory base address. * bufsize - DMA channel buffer size. * * @return none */ static void ADC_DMA_Init(void) { DMA_InitTypeDef DMA_InitStructure = {0}; NVIC_InitTypeDef NVIC_InitStructure; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); // Configure DMA interrupt NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); DMA_DeInit(DMA1_Channel1); DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->RDATAR; DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)tmpValue; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = ADC_COUNT * ADC_BUFFER_SIZE; // For two channels DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; // Continuous mode DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel1, &DMA_InitStructure); DMA_Cmd(DMA1_Channel1, ENABLE); // Enable DMA interrupt DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE); } /********************************************************************* * @fn Get_ConversionVal * * @brief Get Conversion Value. * * @param val - Sampling value * * @return val+Calibrattion_Val - Conversion Value. */ uint16_t Get_ConversionVal(int16_t val) { if((val + Calibrattion_Val) < 0) { return 0; } else if((Calibrattion_Val + val) > 4095 || val == 4095) { return 4095; } return (val + Calibrattion_Val); } const float Rp = 100000.0; //10K const float T2 = (273.15 + 25.0);;//T2 const float Bx = 3950.0;//B const float Ka = 273.15; float Get_Temp(float Rt) { float temp; //like this R=5000, T2=273.15+25,B=3470, RT=5000*EXP(3470*(1/T1-1/(273.15+25)), temp = Rt/Rp; temp = log(temp);//ln(Rt/Rp) temp/=Bx;//ln(Rt/Rp)/B temp+=(1/T2); temp = 1/(temp); temp-=Ka; return temp; } /******************************************************************************* * @函数名称 temperature_task * @函数说明 温度任务 * @输入参数 无 * @输出参数 无 * @返回参数 无 *******************************************************************************/ static void temperature_task(void) { #if TEMPE_OWNER == 1 uint32_t tempe_temp = 0; #endif uint32_t leftadcvalue = tmpValue[0]; uint32_t rightadcvalue = tmpValue[1]; for(int i = 2; i < ADC_COUNT * ADC_BUFFER_SIZE; i+=2) { leftadcvalue += tmpValue[i]; rightadcvalue += tmpValue[i+1]; leftadcvalue /= 2; rightadcvalue /= 2; } float lefttemp = (float)(Get_ConversionVal(leftadcvalue) * ADC_VDDA / 4096); float righttemp = (float)(Get_ConversionVal(rightadcvalue) * ADC_VDDA / 4096); float left_r = (lefttemp * 100000.0f) / (5000.0f - lefttemp); float right_r = (righttemp * 100000.0f) / (5000.0f - righttemp); // PRINT("left=%d,%.02f,%.02f,right=%d,%.02f,%.02f\n", leftadcvalue, lefttemp, left_r / 1000, rightadcvalue ,righttemp, right_r / 1000); adc_data.left_ntc = Get_Temp(left_r) * 100; adc_data.right_ntc = Get_Temp(right_r) * 100; #if TEMPE_OWNER == 1 tempe_temp = Get_ConversionVal(tmpValue[2]) * ADC_VDDA / 4096; adc_data.tmp_chip =((float)tempe_temp - TEMPE_V_25) / TEMPE_AVG_SLOPE +25.0; #endif upload_adc_value(true); } /******************************************************************************* * @函数名称 upload_adc_value * @函数说明 上报温度值 * @输入参数 无 * @输出参数 无 * @返回参数 无 *******************************************************************************/ static void upload_adc_value(bool tmp_stat) { // PRINT("temperature left=%d.%d, right=%d.%d\n", adc_data.left_ntc / 100 , adc_data.left_ntc % 100, // adc_data.right_ntc / 100, adc_data.right_ntc % 100); if(adc_upload != NULL) { adc_upload(adc_data, tmp_stat); } } /******************************************************************************* * @函数名称 adc_task_start * @函数说明 ADC任务启动 * @输入参数 无 * @输出参数 无 * @返回参数 无 *******************************************************************************/ void adc_task_start(void) { bStatus_t stat = tmos_start_reload_task(user_charge_task_id, (1 << ADC_QUEUE_TIME), MS1_TO_SYSTEM_TIME(TEMP_INTERVAL)); ADC_SoftwareStartConvCmd(ADC_CHANNEL, ENABLE); } /******************************************************************************* * @函数名称 adc_task_process_event * @函数说明 task的event处理回调函数,需要在注册task时候,传进去 * @输入参数 task_id:任务ID events:事件 * @输出参数 无 * @返回参数 无 *******************************************************************************/ uint16_t adc_task_process_event(uint8_t task_id, uint16_t events) { //event 处理 if(events & (1 << ADC_QUEUE_TIME)) { // PRINT("ADC_QUEUE_JEOC execute\r\n"); DMA_SetCurrDataCounter(DMA1_Channel1, ADC_COUNT * ADC_BUFFER_SIZE); DMA_Cmd(DMA1_Channel1, ENABLE); ADC_SoftwareStartConvCmd(ADC_CHANNEL, ENABLE); return (events ^ (1 << ADC_QUEUE_TIME)); //异或的方式清除该事件运行标志,并返回未运行的事件标志 } if(events & (1 << ADC_QUEUE_DMA)) { // PRINT("ADC_QUEUE_JEOC execute\r\n"); temperature_task(); return (events ^ (1 << ADC_QUEUE_DMA)); //异或的方式清除该事件运行标志,并返回未运行的事件标志 } return 0; } /******************************************************************************* * @函数名称 adc_init * @函数说明 ADC初始化 * @输入参数 无 * @输出参数 无 * @返回参数 无 *******************************************************************************/ void adc_init(void) { ADC_Function_Init(); ADC_DMA_Init(); } /******************************************************************************* * @函数名称 set_adc_upload_func * @函数说明 设置adc结果上报回调函数指针 * @输入参数 func:函数直针 * @输出参数 无 * @返回参数 无 *******************************************************************************/ void set_adc_upload_func(adc_upload_func func) { adc_upload = func; } /******************************************************************************* * @函数名称 vUser_adc_dma_finish * @函数说明 ADC DMA中断 * @输入参数 无 * @输出参数 无 * @返回参数 无 *******************************************************************************/ void vUser_adc_dma_finish(void) { DMA_Cmd(DMA1_Channel1, DISABLE); ADC_SoftwareStartConvCmd(ADC_CHANNEL, DISABLE); bStatus_t stat = tmos_start_task(user_charge_task_id, (1 << ADC_QUEUE_DMA), MS1_TO_SYSTEM_TIME(1)); }