STM32 ADC中断读取调整函数及实验
一、ADC规则组与注入组的区别
1. 基本概念对比
规则组
定位:常规测量通道
优先级:较低
数据寄存器:1个共享数据寄存器(DR)
通道数量:最多16个通道
转换顺序:按预设序列顺序转换
注入组
定位:紧急/高优先级测量通道
优先级:较高,可中断规则组转换
数据寄存器:4个独立数据寄存器(JDR1~JDR4)
通道数量:最多4个通道
转换顺序:可配置的独立序列
2. 详细区别分析
中断能力与优先级
规则组:
不能中断其他转换
可被注入组中断
适合常规的顺序数据采集
注入组:
可以中断规则组的转换
具有"插队"能力
适合紧急事件检测和快速响应
数据存储方式
规则组:
// 所有规则通道共享一个数据寄存器
uint32_t value = HAL_ADC_GetValue(&hadc1);
// 多通道时需要及时读取或使用DMA
注入组:
// 每个注入通道有独立的数据寄存器
uint32_t value1 = HAL_ADCEx_InjectedGetValue(&hadc1, ADC_INJECTED_RANK_1);
uint32_t value2 = HAL_ADCEx_InjectedGetValue(&hadc1, ADC_INJECTED_RANK_2);
uint32_t value3 = HAL_ADCEx_InjectedGetValue(&hadc1, ADC_INJECTED_RANK_3);
uint32_t value4 = HAL_ADCEx_InjectedGetValue(&hadc1, ADC_INJECTED_RANK_4);
触发方式
规则组触发:
软件触发
硬件触发(定时器、外部事件等)
连续转换模式
注入组触发:
软件触发
硬件触发
自动注入:在规则组转换结束后自动开始注入组转换
典型应用场景
规则组适用场景:
多路传感器数据采集(温度、压力、电压等)
周期性数据监测
顺序扫描多个检测点
注入组适用场景:
过压/过流保护
紧急停机信号检测
关键参数实时监控
需要立即响应的安全检测
二、ADC中断读取配置函数
1. HAL_ADCEx_InjectedStart_IT(&hadc1)
功能:以中断方式启动ADC注入组转换
特点:
启动注入组通道的转换
转换完成后会产生中断,调用相应的回调函数
注入组通常用于高优先级的紧急测量,可以中断正在进行的规则组转换
支持多个注入通道,按配置的序列顺序转换
2. HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef* hadc)
功能:注入组转换完成中断回调函数
特点:
当注入组转换完成时自动调用
需要用户在代码中重写这个函数
在函数内部可以安全地读取注入组转换结果
通常在此函数中处理注入组的测量数据
3. HAL_ADCEx_InjectedGetValue(ADC_HandleTypeDef* hadc, uint32_t InjectedRank)
功能:读取指定注入通道的转换结果
参数:
hadc:ADC句柄指针
InjectedRank:注入通道等级(ADC_INJECTED_RANK_1~4)
返回值:指定注入通道的ADC转换值
注意:注入组有独立的数据寄存器,可以同时保存多个通道的转换结果
4. HAL_ADC_Start_IT(&hadc1)
功能:以中断方式启动ADC规则组转换
特点:
启动规则组通道的转换
转换完成后会产生中断,调用规则组转换完成回调函数
规则组用于常规的顺序测量
适合多通道扫描转换
5. HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
功能:规则组转换完成中断回调函数
特点:
当规则组转换完成时自动调用
需要用户在代码中重写这个函数
在函数内部可以安全地读取规则组转换结果
规则组所有通道转换完成后才会调用此函数
6. HAL_ADC_GetValue(&hadc1)
功能:读取规则组转换结果
特点:
读取规则组数据寄存器中的值
在规则组多通道转换时,通常返回序列中最后一个通道的值
建议在转换完成回调函数中调用此函数
三、示例实验
1. 实验现象
每隔500毫秒同时启动ADC规则组和注入组转换,通过中断方式分别采集两个通道的模拟信号,将规则组转换结果转换为电压值显示为"输出1",注入组转换结果转换为电压值显示为"输出2",并通过串口以每行一个电压值的形式输出这两个电压值,电压范围在0.000V到3.300V之间。
2. 示例代码
ADC初始化
void MX_ADC1_Init(void)
{
ADC_ChannelConfTypeDef sConfig = {0}; // 定义规则通道配置结构体
ADC_InjectionConfTypeDef sConfigInjected = {0}; // 定义注入通道配置结构体
/** ADC通用配置 */
hadc1.Instance = ADC1; // 设置ADC实例为ADC1
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE; // 禁用扫描模式(单通道)
hadc1.Init.ContinuousConvMode = DISABLE; // 禁用连续转换模式(单次转换)
hadc1.Init.DiscontinuousConvMode = DISABLE; // 禁用间断模式
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; // 使用软件触发转换
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; // 数据右对齐
hadc1.Init.NbrOfConversion = 1; // 转换序列数为1
// 初始化ADC,如果失败则调用错误处理函数
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
/** 配置规则通道 */
sConfig.Channel = ADC_CHANNEL_4; // 设置ADC规则通道4
sConfig.Rank = ADC_REGULAR_RANK_1; // 设置通道在规则组中的排名为第1个
sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5; // 设置采样时间为1.5个ADC时钟周期
// 配置ADC规则通道,如果失败则调用错误处理函数
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
/** 配置注入通道 */
sConfigInjected.InjectedChannel = ADC_CHANNEL_5; // 设置ADC注入通道5
sConfigInjected.InjectedRank = ADC_INJECTED_RANK_1; // 设置注入通道等级为第1个
sConfigInjected.InjectedNbrOfConversion = 1; // 注入组转换序列数为1
sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_1CYCLE_5; // 设置采样时间
sConfigInjected.ExternalTrigInjecConv = ADC_INJECTED_SOFTWARE_START; // 软件触发注入转换
sConfigInjected.AutoInjectedConv = DISABLE; // 禁用自动注入模式
sConfigInjected.InjectedDiscontinuousConvMode = DISABLE; // 禁用注入间断模式
sConfigInjected.InjectedOffset = 0; // 设置注入偏移量为0
// 配置ADC注入通道,如果失败则调用错误处理函数
if (HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected) != HAL_OK)
{
Error_Handler();
}
}
主函数
uint16_t get[2] = {0}; // 存储ADC原始值的数组:[0]规则组结果,[1]注入组结果
float aaa[2] = {0.0f}; // 存储电压值的数组:[0]规则组电压,[1]注入组电压
// 系统时钟配置函数声明
void SystemClock_Config(void);
/**
* @brief 应用程序主函数
* @retval int
*/
int main(void)
{
// HAL库初始化
HAL_Init();
// 系统时钟配置
SystemClock_Config();
// 初始化所有配置的外设
MX_GPIO_Init(); // GPIO初始化
MX_ADC1_Init(); // ADC1初始化(配置规则通道4和注入通道5)
MX_USART1_UART_Init(); // USART1串口初始化
HAL_ADCEx_Calibration_Start(&hadc1); // 执行ADC校准
// 主循环
while (1)
{
// 以中断方式启动规则组转换
HAL_ADC_Start_IT(&hadc1);
// 以中断方式启动注入组转换
HAL_ADCEx_InjectedStart_IT(&hadc1);
// 将ADC原始值转换为电压值(12位分辨率,参考电压3.3V)
aaa[0] = (float)get[0] / 4095 * 3.3f; // 规则组通道4的电压值
aaa[1] = (float)get[1] / 4095 * 3.3f; // 注入组通道5的电压值
// 通过串口输出两个通道的电压值
printf("\r\n输出1:%.3f\r\n输出2:%.3f\r\n", aaa[0], aaa[1]);
// 延时500ms
HAL_Delay(500);
}
}
中断回调函数
/**
* @brief 规则组转换完成中断回调函数
* @param hadc: ADC句柄指针
*/
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
if(hadc->Instance == ADC1)
{
// 读取规则组转换结果(通道4)并存储到get[0]
get[0] = HAL_ADC_GetValue(hadc);
}
}
/**
* @brief 注入组转换完成中断回调函数
* @param hadc: ADC句柄指针
*/
void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef* hadc)
{
if(hadc->Instance == ADC1)
{
// 读取注入组转换结果(通道5)并存储到get[1]
get[1] = HAL_ADCEx_InjectedGetValue(hadc, ADC_INJECTED_RANK_1);
}
}
浙公网安备 33010602011771号