STM32的ADC模式及其应用例程介绍
- 📍ST官方相关应用笔记介绍资料:
https://www.stmcu.com.cn/Designresource/detail/application_note/705947
- 📌相关例程资源包:
STSW-STM32028
:https://www.st.com/zh/embedded-software/stsw-stm32028.html
✨官方所给的例程是基于标准库下的工程。对于HAl STM32CubeMX工程此功能的代码在网上最多,而基于标准库下的介绍该功能的相关配置很少,如果想学习和研究基于标准库来使用ADC功能,这是一个不错的资源例程,几乎包含了所有ADC功能实现已经应用方式。
- 📑例程包含说明文档,涉及单路以及多路ADC通道数据获取,双ADC模式下,交替、注入转换方式等内容的介绍和使用。
- 📋相关例程列表:
- 📐本文只抽取其中的
SingleChannelContinuous
单通道连续转换模式,采用DMA传输方式,进行功能测试。
所给的例程代码,已经帮我们配置了其功能代码,我们只需要做的是,添加调试串口,将对应的数据,通过串口打印出来,查看其结果是否符合预期。
- 🚩所提供的资源案例采用的是STM32F107,个人采用的是STM32F103进行测试。
📓单通道连续转换模式
单通道连续转换模式可在常规通道转换中对单个通道进行连续不断的转换。
- 此连续模式允许 ADC 在后台工作。因此,ADC 可在没有任何 CPU 干预的情况下连续转换通道。此外,还可以在循环模式下使用 DMA,从而降低 CPU 负载。
注: 本应用笔记提供了一个固件示例:SingleChannelContinuous。该示例使用两种方法:
DMA 和中断。要选择其中一种方法,只需在 main.c 文件中注释或取消注释 #define
USE_DMA_Transfer。 - 📝配置代码如下:
int main(void)
{
/* System clocks configuration ---------------------------------------------*/
RCC_Configuration();
delay_init(); //延时函数初始化
/* GPIO configuration ------------------------------------------------------*/
GPIO_Configuration();
uart_init(115200); //串口初始化
printf("Hello World \r\n");
#ifndef USE_DMA_Transfer
/* NVIC configuration ------------------------------------------------------*/
NVIC_Configuration();
#else
/* DMA1 channel1 configuration ---------------------------------------------*/
DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADC1ConvertedValue;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = 1;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
/* Enable DMA1 channel1 */
DMA_Cmd(DMA1_Channel1, ENABLE);
#endif
/* ADC1 configuration ------------------------------------------------------*/
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//独立模式
ADC_InitStructure.ADC_ScanConvMode = DISABLE;//非扫描模式
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;//连续转换
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//禁止触发检测,使用软件触发
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//右对齐
ADC_InitStructure.ADC_NbrOfChannel = 1;//1个通道
ADC_Init(ADC1, &ADC_InitStructure);
/* ADC1 regular channels configuration */
ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 1, ADC_SampleTime_28Cycles5); //采样时间
#ifdef USE_DMA_Transfer
/* Enable ADC1 DMA */
ADC_DMACmd(ADC1, ENABLE);
#else
/* Enable ADC1 EOC interupt */
ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE);
#endif
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
/* Enable ADC1 reset calibaration register */
ADC_ResetCalibration(ADC1);
/* Check the end of ADC1 reset calibration register */
while(ADC_GetResetCalibrationStatus(ADC1));
/* Start ADC1 calibaration */
ADC_StartCalibration(ADC1);
/* Check the end of ADC1 calibration */
while(ADC_GetCalibrationStatus(ADC1));
/* Start ADC1 Software Conversion */
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
while (1)
{
printf("ADC1ConvertedValue:%d \r\n",ADC1ConvertedValue);
delay_ms(1000);
}
}
- 🌿此案例采用的是ADC1中的递14通道,对应的输入引脚为PC4:
- 📜调节定位器,测试输出结果
📗扫描方式多通道连续转换
- 🌿对应的例程:
ScanContinuous
通道配置:
/* ADC1 regular channel11, channel14, channel16 and channel17 configurations */
ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_41Cycles5);//PC1
ADC_RegularChannelConfig(ADC1, ADC_Channel_17, 2, ADC_SampleTime_239Cycles5);//内部参考电压
ADC_RegularChannelConfig(ADC1, ADC_Channel_16, 3, ADC_SampleTime_239Cycles5);//内部温度传感器
ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 4, ADC_SampleTime_1Cycles5);//PC4
int main(void)
{
/* System clocks configuration ---------------------------------------------*/
RCC_Configuration();
delay_init(); //延时函数初始化
/* GPIO configuration ------------------------------------------------------*/
GPIO_Configuration();
uart_init(115200); //串口初始化
printf("Hello World \r\n");
/* DMA1 channel1 configuration ---------------------------------------------*/
DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADC1ConvertedValue;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = BufferLenght;
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_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
/* Enable DMA1 channel1 */
DMA_Cmd(DMA1_Channel1, ENABLE);
/* ADC1 configuration ------------------------------------------------------*/
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;//右对齐
ADC_InitStructure.ADC_NbrOfChannel = BufferLenght;//4个转换在规则序列中 也就是转换规则序列4
ADC_Init(ADC1, &ADC_InitStructure);
/* ADC1 regular channel11, channel14, channel16 and channel17 configurations */
ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_41Cycles5);//PC1
ADC_RegularChannelConfig(ADC1, ADC_Channel_17, 2, ADC_SampleTime_239Cycles5);//内部参考电压
ADC_RegularChannelConfig(ADC1, ADC_Channel_16, 3, ADC_SampleTime_239Cycles5);//内部温度传感器
ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 4, ADC_SampleTime_1Cycles5);//PC4
/* Enable ADC1 DMA */
ADC_DMACmd(ADC1, ENABLE);
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
/* Enable TempSensor and Vrefint channels: channel16 and Channel17 */
ADC_TempSensorVrefintCmd(ENABLE);
/* Enable ADC1 reset calibaration register */
ADC_ResetCalibration(ADC1);
/* Check the end of ADC1 reset calibration register */
while(ADC_GetResetCalibrationStatus(ADC1));
/* Start ADC1 calibaration */
ADC_StartCalibration(ADC1);
/* Check the end of ADC1 calibration */
while(ADC_GetCalibrationStatus(ADC1));
/* Start ADC1 Software Conversion */
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
/* Test on Channel 1 DMA1_FLAG_TC flag */
while(!DMA_GetFlagStatus(DMA1_FLAG_TC1));
/* Clear Channel 1 DMA1_FLAG_TC flag */
DMA_ClearFlag(DMA1_FLAG_TC1);
while(1)
{
printf("%d - %d - %d - %d \r\n", ADC1ConvertedValue[0], ADC1ConvertedValue[1],
ADC1ConvertedValue[2], ADC1ConvertedValue[3]\
);//PC1->[0];内部参考电压;温度; PC4->[3]
delay_ms(1000);
}
}
- 📋串口打印:
👉🏻仅对资源例程中2个例程进行了有效性验证,其他例程没有做烧录测试和功能验证。
📚例程资源(包含中文说明文档)
- 🔖如需下载未修改过的原例程资源请前往官方下载。
- 🌿该资源例程修改匹配的是stm32f103芯片。
链接:https://pan.baidu.com/s/1-k9UvL2lSLI2ZlxyoT-FWg
提取码:7kot