本帖最后由 聪聪哥哥 于 2025-5-23 20:24 编辑
使用ADC实现位移传感器的采集功能
内置的12位模数转换器嵌入到STM32C091xB/xC和STM32C092xB/xC设备中。该ADC最多有19个外部通道和2个内部通道。通道(温度传感器、电压参考)。LT在单次测量或扫描模式下执行转换。在扫描模式下,对选定的一组模拟输入执行自动转换。
ADC的频率独立于CPU的频率,即使在CPU速度较低的情况下,也可以达到2.5MSps的最大采样率。自动关机功能可确保除在活动转换阶段外ADC处于关机状态。
ADC可以由DMA控制器提供服务。它可以在整个VDD供电范围内运行。
模拟看门狗功能允许对一个、某些或所有扫描通道的转换电压进行非常精确的监控。当转换电压超出预定义的阈值时,将生成中断。
通用定时器(TIMx)产生的事件可以在内部连接到ADC开始触发器,使应用程序能够将A/D转换与定时器同步。
一:温度传感器
温度传感器
温度传感器(TS)产生一个随温度线性变化的电压VTS。
温度传感器与ADC输入端内部连接,将传感器输出电压转换为数字值。
该传感器具有良好的线性度,但必须进行校准才能获得良好的温度测量整体准确性。由于工艺变化,温度传感器的偏移可能会因部件而异,因此未校准的内部温度传感器仅适用于相对温度测量。
为了提高温度传感器的准确性,每个部分都单独由ST进行工厂校准,校准数据被存储在部分的工程字节中,在只读模式下可访问。
二:内部电压参考(VREFINT)
内部电压参考(VREFINT)为ADC提供稳定的(带隙)电压输出。VREFINT内部连接到ADC输入。VREFINT电压在生产测试期间由ST为每个部件单独精确测量,并存储在部件的工程字节中。它可以在只读模式下访问。三:STM32cube MX 软件配置
四:软件代码如下:
static void MX_ADC1_Init(void)
{
/* USER CODE BEGIN ADC1_Init 0 */
/* USER CODE END ADC1_Init 0 */
ADC_ChannelConfTypeDef sConfig = {0};
/* USER CODE BEGIN ADC1_Init 1 */
/* USER CODE END ADC1_Init 1 */
/** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc1.Init.LowPowerAutoWait = DISABLE;
hadc1.Init.LowPowerAutoPowerOff = DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.NbrOfConversion = 3;
hadc1.Init.DiscontinuousConvMode = ENABLE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.DMAContinuousRequests = ENABLE;
hadc1.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
hadc1.Init.SamplingTimeCommon1 = ADC_SAMPLETIME_79CYCLES_5;
hadc1.Init.SamplingTimeCommon2 = ADC_SAMPLETIME_160CYCLES_5;
hadc1.Init.OversamplingMode = DISABLE;
hadc1.Init.TriggerFrequencyMode = ADC_TRIGGER_FREQ_HIGH;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_4;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLINGTIME_COMMON_1;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_VREFINT;
sConfig.Rank = ADC_REGULAR_RANK_2;
sConfig.SamplingTime = ADC_SAMPLINGTIME_COMMON_2;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
sConfig.Rank = ADC_REGULAR_RANK_3;
sConfig.SamplingTime = ADC_SAMPLINGTIME_COMMON_1;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN ADC1_Init 2 */
/* USER CODE END ADC1_Init 2 */
}
在主程序下添加如下代码:
/* Start ADC group regular conversion */
if (HAL_ADC_Start(&hadc1) != HAL_OK)
{
/* Error: ADC conversion start could not be performed */
Error_Handler();
}
if(ubDmaTransferStatus == 1)
{
/* For this example purpose, calculate analog reference voltage (Vref+) */
/* from ADC conversion of internal voltage reference VrefInt. */
/* This voltage should correspond to value of literal "VDDA_APPLI". */
/* Note: This calculation can be performed when value of voltage Vref+ */
/* is unknown in the application */
/* (This is not the case in this example due to target board */
/* supplied by a LDO regulator providing a known constant voltage */
/* of value "VDDA_APPLI"). */
/* In typical case of Vref+ connected to Vdd, it allows to */
/* deduce Vdd value. */
uhADCxConvertedData_VrefAnalog_mVolt = __LL_ADC_CALC_VREFANALOG_VOLTAGE(uhADCxConvertedData[1], LL_ADC_RESOLUTION_12B);
/* Computation of ADC conversions raw data to physical values */
/* using LL ADC driver helper macro. */
uhADCxConvertedData_VoltageGPIO_mVolt = __LL_ADC_CALC_DATA_TO_VOLTAGE(uhADCxConvertedData_VrefAnalog_mVolt, uhADCxConvertedData[0], LL_ADC_RESOLUTION_12B);
uhADCxConvertedData_VrefInt_mVolt = __LL_ADC_CALC_DATA_TO_VOLTAGE(uhADCxConvertedData_VrefAnalog_mVolt, uhADCxConvertedData[1], LL_ADC_RESOLUTION_12B);
hADCxConvertedData_Temperature_DegreeCelsius = __LL_ADC_CALC_TEMPERATURE_TYP_PARAMS(INTERNAL_TEMPSENSOR_AVGSLOPE,INTERNAL_TEMPSENSOR_V30,INTERNAL_TEMPSENSOR_V30_TEMP,VDDA_APPLI,uhADCxConvertedData[2],LL_ADC_RESOLUTION_12B);
/* Update status variable of DMA transfer */
ubDmaTransferStatus = 0;
/* Toggle LED 4 times */
tmp_index = 4*2;
while(tmp_index != 0)
{
BSP_LED_Toggle(LED1);
HAL_Delay(LED_BLINK_FAST);
tmp_index--;
}
HAL_Delay(500); /* Delay to highlight toggle sequence */
}
实测图如下:
|