This repository has been archived on 2025-02-28. You can view files and clone it, but cannot push or open issues or pull requests.
controller-hd/User/system/bsp/adcs.c

296 lines
8.4 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @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_COLL 30 /* 通道单采集次数*/
#define ADC_CH_NUM INMAX
#define ADC_SUM ADC_CH_NUM *ADC_COLL /* 总采集次数 */
#if defined(SRAM2_BASE)
// 将 adc_value分配到SRAM2中因为SRAM2的速度更快可以提高ADC采集的速度
volatile static uint16_t adc_value[ADC_COLL][INMAX] __attribute__((section(".sram2")));
#else
volatile static uint16_t adc_value[ADC_COLL][INMAX]; /* 存储ADC原始值 */
#endif
volatile static BOOL _flag = FALSE; /* DMA传输完成标志 */
static BOOL init_flag = FALSE; /* ADC初始化标志 */
volatile uint32_t adcs_ovr_count = 0;
/**
* @brief 这是一个用于处理ADC转换完成回调的函数
* @param {adc_t} handle - 包含ADC句柄的信息
* @return {*} 无
*/
void adc_dma_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);
}
// ...
}
void adc_callback(adc_t handle)
{
if (LL_ADC_IsActiveFlag_OVR(handle.adc) != 0)
{
adcs_ovr_count++;
LL_ADC_REG_StopConversion(handle.adc);
LL_DMA_DisableChannel(handle.dma, handle.dma_channel);
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);
LL_ADC_ClearFlag_OVR(handle.adc);
LL_ADC_ClearFlag_EOC(handle.adc);
LL_ADC_REG_StartConversion(handle.adc); // 开始转换
}
}
/**
* @brief 初始化ADC
* @param {adc_t} handle
* @return {*}
* @note TCONV(转换时间) = (采样时间 + 12.5 个周期)/(主频/ADC分频系数)
*/
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, LL_ADC_SINGLE_ENDED);
// 等待校准完成
while (LL_ADC_IsCalibrationOnGoing(handle.adc))
;
LL_ADC_REG_SetDMATransfer(handle.adc, backup_setting_adc_dma_transfer);
LL_mDelay(10);
LL_ADC_EnableIT_OVR(handle.adc);
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); // 开始转换
}
osel_memset((uint8_t *)adc_value, 0, sizeof(uint16_t) * ADC_COLL * INMAX);
}
/**
* @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;
}