关于ADC的差分输入模式
在配置ADC时,将ADC1 Channel1, ADC1 Channel2配置为单端模式
将ADC1 Channel6,和Channel7配置为差分模式的正负极输入。
单端模式读入的数据正确,但是差分模式读入的数据看不懂。。。
差分输入为0V时,读到的数据是十进制2050左右;
差分输入0.75V时,读到的数据是2513左右;
差分输入1.88V时,读到的数据是3213左右;
差分输入2.27V时,读到数据是3456左右。
AD的参考电压是3.3V。目前从上面的数据中,获得了这样的规律,以输入为0V是,获取的数据2050为基准,假设差分输入电压为Uin,读取到的数据为Data则:
Uin-0=((Data-2050)/4095)*3.3*2
现在的疑惑是,为什么会是这样?
4 个回复
牙子男男
赞同来自:
找到原因了!!!
当ADC配置为单端模式时,GPIO的输入电压范围是0-Vref+,一般就是0-3.3V。分辨率为12位的话,转化结果为0-4095。
当ADC配置为单端模式时,两个差分电压输入引脚的电压差范围可以是-Vref+ 到Vref+。 也就是说,可以检测-3.3到3.3v的差分电压。
我目前的猜测是,将4096/2=2048这个值,作为基准点,也就是电压0点。大于这个值得,就是正电压;小于这个值的,就是负电压。这种情况下,其实0-3.3V的分辨率只有2^11,也就是2048了。于是,输入的差分电压Uin与转换结果Data计算如下:
Uin = 3.3*(Data-2047)/2047;
Data = (2047*Uin/3.3)+2047; 这里具体是用2048还是2047,我没仔细去想。问题应该不大。
测试差分输入为-0.65V时,理论计算的结果应是1643.8:转换结果为1644。
tmooc
赞同来自:
大佬,差分和单端计算方式一样啊,不都是测量的AD值*3.3除以65535么?你看我的测量值和代码
#include "main.h"
#include "stm32f3xx_hal.h"
uint32_t uhADCxConvertedValue = 0;
SDADC_HandleTypeDef hsdadc1;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_SDADC1_Init(void);
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_SDADC1_Init();
HAL_SDADC_AssociateChannelConfig(&hsdadc1, SDADC_CHANNEL_6, SDADC_CONF_INDEX_0);
HAL_SDADC_ConfigChannel(&hsdadc1, SDADC_CHANNEL_6, SDADC_CONTINUOUS_CONV_OFF);
HAL_SDADC_SelectRegularTrigger(&hsdadc1, SDADC_SOFTWARE_TRIGGER);
HAL_SDADC_CalibrationStart(&hsdadc1, SDADC_CALIBRATION_SEQ_1);
HAL_SDADC_PollForCalibEvent(&hsdadc1, HAL_MAX_DELAY);
while (1)
{
HAL_SDADC_Start(&hsdadc1); //此功能允许在轮询模式下开始常规转换。
HAL_SDADC_PollForConversion(&hsdadc1,HAL_MAX_DELAY); //此功能允许轮询常规转换的结束
uhADCxConvertedValue=HAL_SDADC_GetValue(&hsdadc1);
HAL_Delay(1000);
}
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_PeriphCLKInitTypeDef PeriphClkInit;
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSE;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_SDADC;
PeriphClkInit.SdadcClockSelection = RCC_SDADCSYSCLK_DIV2;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
HAL_PWREx_EnableSDADC(PWR_SDADC_ANALOG1);
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}
static void MX_SDADC1_Init(void)
{
SDADC_ConfParamTypeDef ConfParamStruct;
hsdadc1.Instance = SDADC1;
hsdadc1.Init.IdleLowPowerMode = SDADC_LOWPOWER_NONE;
hsdadc1.Init.FastConversionMode = SDADC_FAST_CONV_DISABLE;
hsdadc1.Init.SlowClockMode = SDADC_SLOW_CLOCK_DISABLE;
hsdadc1.Init.ReferenceVoltage = SDADC_VREF_EXT;
if (HAL_SDADC_Init(&hsdadc1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
ConfParamStruct.InputMode = SDADC_INPUT_MODE_DIFF;
ConfParamStruct.Gain = SDADC_GAIN_1;
ConfParamStruct.CommonMode = SDADC_COMMON_MODE_VSSA;
ConfParamStruct.Offset = 0;
if (HAL_SDADC_PrepareChannelConfig(&hsdadc1, SDADC_CONF_INDEX_0, &ConfParamStruct) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}
static void MX_GPIO_Init(void)
{
__HAL_RCC_GPIOF_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
}
void _Error_Handler(char *file, int line)
{
while(1)
{
}
}
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t* file, uint32_t line)
{
}
#endif /* USE_FULL_ASSERT */
牙子男男
赞同来自:
仔细看一下SDADC的采样电压范围这里的介绍。
文档里提到采样范围和增益有关系。
你程序里面配置增益是1,那么采样范围是-1.65V~1.65V(如果参考电压是3.3V)。
根据我的理解,差分模式的时候,增益是1/2的时候,采样后的转化范围是0-65535(2^16-1); 增益是1的时候,采样后的转化范围是0-32767(2^15-1)。
根据上面两点,你现在的配置,-1.65~1.65V转化后范围是0-32767。 0V的转化值是2^14-1=16383。
所以转化后的值A和输入差分电压B之间关系应该是:A-16383 = (B-0)*16384/1.65,也就是说A= (B*16384/1.65)+16383
但我发现,通过我这个公式计算出来的值和你转化后的值还是有出入,具体什么问题我也不清楚了,只能帮你到这儿了。
龚向东
赞同来自:
我感到很迷茫,我将STM32L4XX配置成差分模式,结果它的值在正值时,为2048~4096之间,为负值时,为0~2048之间。围绕这个2048为中心值,这和我想象中可不一样。我原先想正电压的时候,输出为0~2047之间,负的时候,输出的是补码,而且扩展到16位。 我用ADS1120就是这样子的。可为什么STM32怎么会这样呢?也没有例子,只好自已试了。要是这样的话,我用单端来转换,结果也一样。何必用差分呢?