/** * @file adcs.c * @author xxx * @date 2023-09-04 15:59:16 * @brief LL库ADC驱动 * @copyright Copyright (c) 2023 by xxx, All Rights Reserved. */ #include "adcs.h" #define ADC_CH_NUM INMAX #define ADC_COLL 20 /* 通道单采集次数*/ #define ADC_SUM ADC_CH_NUM *ADC_COLL /* 总采集次数 */ __IO static uint16_t adc_value[ADC_COLL][INMAX]; /* 存储ADC原始值 */ __IO static BOOL _flag = FALSE; /* DMA传输完成标志 */ static BOOL init_flag = FALSE; /* ADC初始化标志 */ /** * @brief 这是一个用于处理ADC转换完成回调的函数 * @param {adc_t} handle - 包含ADC句柄的信息 * @return {*} 无 */ void adc_convert_callback(adc_t handle) { // 检查DMA1的传输完成标志是否为1,如果是,则清除该标志 if (LL_DMA_IsActiveFlag_TC1(handle.dma) != 0) { LL_DMA_ClearFlag_TC1(handle.dma); // 停止ADC转换 LL_ADC_REG_StopConversion(handle.adc); // 关闭ADC,可以不关闭但是校准无法清除 // LL_ADC_Disable(handle.adc); adc_completed_state_change(TRUE); } // 检查DMA1的传输错误标志是否为1,如果是,则清除该标志 if (LL_DMA_IsActiveFlag_TE1(handle.dma) != 0) { LL_DMA_ClearFlag_TE1(handle.dma); } // ... } /** * @brief 初始化ADC * @param {adc_t} handle * @return {*} * @note TCONV(转换时间) = 采样时间+ 12.5 个周期 */ void adc_init(adc_t handle) { init_flag = TRUE; uint32_t backup_setting_adc_dma_transfer = 0U; backup_setting_adc_dma_transfer = LL_ADC_REG_GetDMATransfer(handle.adc); LL_ADC_REG_SetDMATransfer(handle.adc, LL_ADC_REG_DMA_TRANSFER_NONE); // ADC开始校准 LL_ADC_StartCalibration(handle.adc); // 等待校准完成 while (LL_ADC_IsCalibrationOnGoing(handle.adc)) ; LL_ADC_REG_SetDMATransfer(handle.adc, backup_setting_adc_dma_transfer); LL_mDelay(10); LL_ADC_Enable(handle.adc); LL_mDelay(10); LL_DMA_SetDataLength(handle.dma, handle.dma_channel, ADC_SUM); LL_DMA_SetPeriphAddress(handle.dma, handle.dma_channel, LL_ADC_DMA_GetRegAddr(handle.adc, LL_ADC_DMA_REG_REGULAR_DATA)); LL_DMA_SetMemoryAddress(handle.dma, handle.dma_channel, (uint32_t)&adc_value); LL_DMA_EnableChannel(handle.dma, handle.dma_channel); if (backup_setting_adc_dma_transfer == LL_ADC_REG_DMA_TRANSFER_UNLIMITED) { LL_ADC_REG_StartConversion(handle.adc); // 开始转换 } } /** * @brief 开始转换ADC * @param {adc_t} handle * @return {*} * @note 单次采集需要每次调用 */ void adc_start(adc_t handle) { if (TRUE == init_flag) { LL_ADC_REG_StartConversion(handle.adc); // 开始转换 } } /** * @brief 设置ADC转换完成状态变化回调函数 * @param {BOOL} state * @return {*} */ void adc_completed_state_change(BOOL state) { _flag = state; } /** * @brief 获取ADC转换完成状态 * @return {BOOL} ADC转换完成标志 */ BOOL adc_completed(void) { return _flag; } /** * @brief 获取ADC第0个通道的读取结果 * @param {uint8_t} in_num * @return {uint16_t} 返回当前值 */ uint16_t adc_get_result0(uint8_t in_num) { return adc_value[0][in_num]; } /** * @brief 获取ADC所有通道的读取结果平均值 * @param {uint8_t} adc_num * @return {uint16_t} 返回平均值 */ uint16_t adc_get_result_average(uint8_t adc_num) { uint32_t adc_sum = 0; // 用于存储所有ADC通道数据的和 uint16_t adc_average = 0; // 用于存储平均值 uint16_t i = 0; // 用于循环的变量 for (i = 0; i < ADC_COLL; i++) // 遍历所有ADC通道 { adc_sum += adc_value[i][adc_num]; // 将每个ADC通道的数据累加到adc_sum中 } adc_average = adc_sum / ADC_COLL; // 计算平均值并存储在adc_average中 return adc_average; // 返回平均值 } /** * @brief 获取ADC所有通道的读取结果平均值,按照从小到大排序,取中间N个数据 * @param {uint8_t} adc_num * @return {uint16_t} 返回平均值 */ uint16_t adc_get_n_result_average(uint8_t adc_num) { uint32_t adc_sum = 0; uint16_t adc_average = 0; uint16_t array[ADC_COLL]; uint8_t n = ADC_COLL / 4; uint8_t count = ADC_COLL > (2 * n) ? n : 0; for (uint16_t i = 0; i < ADC_COLL; i++) { array[i] = adc_value[i][adc_num]; } osel_quick_sort(array, 0, ADC_COLL - 1); for (uint16_t i = count; i < ADC_COLL - count; i++) { adc_sum += array[i]; } adc_average = adc_sum / (ADC_COLL - 2 * count); return adc_average; } /** * @brief 中位值滤波 * @param {uint8_t} adc_num * @return {uint16_t} 返回中位数 */ uint16_t adc_get_result_median(uint8_t adc_num) { uint16_t adc_temp[ADC_COLL]; uint16_t i = 0, j = 0; uint16_t temp = 0; for (i = 0; i < ADC_COLL; i++) { adc_temp[i] = adc_value[i][adc_num]; } for (i = 0; i < ADC_COLL - 1; i++) { for (j = 0; j < ADC_COLL - 1 - i; j++) { if (adc_temp[j] > adc_temp[j + 1]) { temp = adc_temp[j]; adc_temp[j] = adc_temp[j + 1]; adc_temp[j + 1] = temp; } } } return adc_temp[ADC_COLL / 2]; } /** * @brief 中位值平均滤波 * @param {uint8_t} adc_num * @return {uint16_t} 返回中位数 */ uint16_t adc_get_result_median_average(uint8_t adc_num) { uint16_t adc_temp[ADC_COLL]; uint16_t i = 0, j = 0; uint16_t temp = 0; uint32_t adc_sum = 0; // 用于存储所有ADC通道数据的和 uint16_t adc_average = 0; // 用于存储平均值 for (i = 0; i < ADC_COLL; i++) { adc_temp[i] = adc_value[i][adc_num]; } for (i = 0; i < ADC_COLL - 1; i++) { for (j = 0; j < ADC_COLL - 1 - i; j++) { if (adc_temp[j] > adc_temp[j + 1]) { temp = adc_temp[j]; adc_temp[j] = adc_temp[j + 1]; adc_temp[j + 1] = temp; } } } for (i = 0; i < ADC_COLL; i++) // 遍历所有ADC通道 { adc_sum += adc_temp[i]; // 将每个ADC通道的数据累加到adc_sum中 } adc_average = adc_sum / ADC_COLL; // 计算平均值并存储在adc_average中 return adc_average; // 返回平均值 } /** * @brief 计算温度值 * @param {uint16_t} measure - ADC读取到的温度值 * @return {int32_t} 返回温度值 * @note: 计算公式为:(measure * VDD_APPLI / VDD_CALIB) - (int32_t)*TEMP30_CAL_ADDR) * (int32_t)(130 - 30) / (int32_t)(*TEMP130_CAL_ADDR - *TEMP30_CAL_ADDR)) + 30 */ int32_t compute_temperature(uint16_t measure) { #define TEMP130_CAL_ADDR ((uint16_t *)((uint32_t)0x1FF8007E)) #define TEMP30_CAL_ADDR ((uint16_t *)((uint32_t)0x1FF8007A)) #define VDD_CALIB ((uint16_t)(300)) #define VDD_APPLI ((uint16_t)(330)) int32_t tmp; tmp = ((measure * VDD_APPLI / VDD_CALIB) - (int32_t)*TEMP30_CAL_ADDR); tmp = tmp * (int32_t)(130 - 30); tmp = tmp / (int32_t)(*TEMP130_CAL_ADDR - *TEMP30_CAL_ADDR); tmp = tmp + 30; return (tmp); } /** * @brief 计算本地值 * @param {uint16_t} measure - ADC读取到的电压值 * @return {int32_t} 返回本地值 * @note: 计算公式为:(1224.0 / measure) * 4096 */ int32_t compute_value_local(uint16_t measure) { return (1224.0 / measure) * 4096; }