一、实验现象
每次循环连续采集3个ADC样本,每个样本间隔500毫秒。每次采集时,程序会启动ADC转换,等待转换完成,然后将12位ADC原始值(0-4095)转换为对应的电压值(0.000V-3.300V),并通过串口实时输出。在串口调试工具上,会看到每1.5秒输出一组3个电压值,每组内的3个数值间隔0.5秒显示。
二、示例代码
1. ADC初始化
void MX_ADC1_Init(void)
{
ADC_ChannelConfTypeDef sConfig = {0}; // 定义ADC通道配置结构体并初始化为0
/** ADC通用配置 */
hadc1.Instance = ADC1; // 设置ADC实例为ADC1
hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE; // 启用扫描模式(多通道)
hadc1.Init.ContinuousConvMode = DISABLE; // 禁用连续转换模式(单次转换)
hadc1.Init.DiscontinuousConvMode = ENABLE; // 启用间断模式
hadc1.Init.NbrOfDiscConversion = 1; // 每个间断序列包含1个转换
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; // 使用软件触发转换
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; // 数据右对齐
hadc1.Init.NbrOfConversion = 3; // 转换序列数为3(3个通道)
// 初始化ADC,如果失败则调用错误处理函数
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
/** 配置规则通道1 */
sConfig.Channel = ADC_CHANNEL_4; // 设置ADC通道4
sConfig.Rank = ADC_REGULAR_RANK_1; // 设置通道在规则组中的排名为第1个
sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5; // 设置采样时间为1.5个ADC时钟周期
// 配置ADC通道4,如果失败则调用错误处理函数
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
/** 配置规则通道2 */
sConfig.Channel = ADC_CHANNEL_5; // 设置ADC通道5
sConfig.Rank = ADC_REGULAR_RANK_2; // 设置通道在规则组中的排名为第2个
// 采样时间保持与通道4相同(1.5个ADC时钟周期)
// 配置ADC通道5,如果失败则调用错误处理函数
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
/** 配置规则通道3 */
sConfig.Channel = ADC_CHANNEL_6; // 设置ADC通道6
sConfig.Rank = ADC_REGULAR_RANK_3; // 设置通道在规则组中的排名为第3个
// 采样时间保持与前面通道相同
// 配置ADC通道6,如果失败则调用错误处理函数
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
}
2. 主函数
uint16_t adc_get[3] = {0}; // 定义ADC原始值数组,用于存储3个通道的转换结果
float vol[3] = {0.0f}; // 定义电压值数组,用于存储3个通道计算得到的电压值
// 系统时钟配置函数声明
void SystemClock_Config(void);
/**
* @brief 应用程序主函数
* @retval int
*/
int main(void)
{
// HAL库初始化
HAL_Init();
// 系统时钟配置
SystemClock_Config();
// 初始化所有配置的外设
MX_GPIO_Init(); // GPIO初始化
MX_ADC1_Init(); // ADC1初始化(配置为3通道扫描模式)
MX_USART1_UART_Init(); // USART1串口初始化
HAL_ADCEx_Calibration_Start(&hadc1); // 执行ADC校准
// 主循环
while (1)
{
// 循环采集3个通道的数据
for(int i = 0; i < 3; i++)
{
// 启动ADC转换(每次触发转换一个通道)
HAL_ADC_Start(&hadc1);
// 等待转换完成,超时时间50ms
if(HAL_ADC_PollForConversion(&hadc1, 50) == HAL_OK)
{
// 获取当前通道的ADC转换结果
adc_get[i] = HAL_ADC_GetValue(&hadc1);
// 将ADC值转换为电压值(假设参考电压3.3V,12位分辨率)
vol[i] = (float)adc_get[i] / 4095 * 3.3f;
// 通过串口打印当前通道的电压值,保留3位小数
printf("%.3f\r\n", vol[i]);
}
// 延时500ms后采集下一个通道
HAL_Delay(500);
}
}
}