STM32G4 ADC模块注入模式使用方法
目录
概述
1 注入模式介绍
1.1 触发注入模式
1.2 自注入模式
1.3 转换时序图
1.4 注入源列表
2 STM32 Cube 配置项目
2.1 ADC模块参数配置
2.2 触发源参数配置
3 功能实现
3.1 软件架构
3.2 ADC相关代码
3.2.1 ADC模块初始化
3.2.2 读取ADC数据
3.3 源代码文件
4 测试
4.1 测试程序定义
4.2 功能测试
4.2.1 采样频率测试
4.2.2 DAC输出波形
4.2.3 ADC采样波形
4.2.4 波形比较
概述
本文主要介绍使用STM32G4 ADC模块注入模式实现ADC转换功能,文中介绍ADC注入模式转换的实现原理,波形特征,还介绍使用STM32 Cube配置项目,并编写代码验证该功能。
1 注入模式介绍
1.1 触发注入模式
要使用触发注入,必须清除ADC_CFGR寄存器中的JAUTO位。
–
1. 通过外部触发器或通过设置ADC_CR寄存器中的ADSTART位启动一组常规通道的转换。–
2. 如果外部注入触发器发生,或者如果ADC_CR寄存器中的JADSTART位是设置在转换一组常规通道时,当前转换复位并启动注入通道序列开关(所有注入通道转换一次)。
–
3. 从上次中断的正则转换中恢复正则组信道的正则转换。
–
4. 如果在注入转换期间发生常规事件,则不会中断注入转换,而是在注入序列的末尾执行常规序列。下图显示了相应的时序图。
注意点:
当使用触发注入时,必须确保触发事件之间的间隔长于注入序列。例如,如果序列长度为30个ADC时钟周期(即两次转换,采样时间为2.5个时钟周期),则触发器之间的最小间隔必须为31个ADC时钟周期。
1.2 自注入模式
如果设置了ADC_CFGR寄存器中的JAUTO位,则注入组中的通道在常规通道组之后自动转换。这可以用来转换在ADC_SQRy和ADC_JSQR寄存器中编程的最多20个转换序列。
在这种模式下,必须将ADC_CR寄存器中的ADSTART位设置为启动常规转换,然后是注入转换(JADSTART必须保持清除)。设置ADSTP位会终止常规转换和注入转换(不能使用JADSTP位)。在此模式下,必须禁用注入通道上的外部触发
注意点:
1)不可能同时使用自动注入和不连续模式。
2)当DMA在JAUTO模式下用于导出常规音序器的数据时,需要将其编程为循环模式(在DMA_CCRx寄存器中设置CIRC位)。如果CIRC位复位(单发模式),则在DMA传输时停止JAUTO序列完整的事件。
1.3 转换时序图
1.4 注入源列表
2 STM32 Cube 配置项目
2.1 ADC模块参数配置
1) MCU配置模拟量端口
2)ADC模块上的配置
3)常规参数配置
4) 注入模式参数配置
2.2 触发源参数配置
本文选择TIME0作为触发定时器,其具体配置如下:
1)定时器通道选择
2)基本参数配置
4) 参数定义
3 功能实现
3.1 软件架构
完成以上参数配置后,就可以生成代码,其程序框架结构如下:
3.2 ADC相关代码
3.2.1 ADC模块初始化
代码32行:启动定时器
代码33行:启动ADC注入中断
代码35行:指针指向ADC数据buff
3.2.2 读取ADC数据
代码46行:读取通道1数据
代码47行:读取通道2数据
3.3 源代码文件
/* USER CODE BEGIN Header */
/**
******************************************************************************
* File Name : adc_drv.c
* Description : adc driver
******************************************************************************
* @attention
*
* COPYRIGHT: Copyright (c) 2024 tangmingfei2013@126.com
* CREATED BY: mingfei.tang
* DATE: JUL 05th, 2024
******************************************************************************
*/
/* USER CODE END Header */
#include "adc_drv.h"
#include "adc.h"
#include "tim.h"
#include "userDebug.h"
#include "mainTask.h"
#include "waveLib.h"
#include "stTemper.h"
float adc1_value_list[ADC_TOTAL_CH];
static float *pADC_ValList;
static bool bl_ready = false;
void adc_drv_init( void )
{
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_4);
HAL_ADCEx_InjectedStart_IT(&hadc1);
pADC_ValList = adc1_value_list;
}
__attribute__((section("ccmram")))
void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef *hadc)
{
static uint32_t count,last_val;
if(hadc==&hadc1)
{
adc1_value_list[0] = HAL_ADCEx_InjectedGetValue(&hadc1,ADC_INJECTED_RANK_1);
adc1_value_list[1] = HAL_ADCEx_InjectedGetValue(&hadc1,ADC_INJECTED_RANK_2);
//adc1_value_list[2] = HAL_ADCEx_InjectedGetValue(&hadc1,ADC_INJECTED_RANK_3);
count++;
if( get_1ms_status() )
{
clear_1ms_status();
last_val = count;
count = 0;
}
adc1_value_list[POS_FREQ] = last_val*1000;
bl_ready = true;
}
}
void Debug_adcLog( void )
{
float value;
value = 200+ sin_wave();
// dac_triangle_wave();
DAC_SetConvert(value);
if( bl_ready )
{
bl_ready = false;
adc1_value_list[2] = value;
// asin wave
adc1_value_list[3] = asin_wave();
Debug_PrintfJustFloat( pADC_ValList, ADC_TOTAL_CH );
}
}
/* End of this file */
4 测试
4.1 测试程序定义
1)使用STM32G4的DAC产生一路正弦波
2)使用STM32G4的ADC模块采样该正弦波
源代码实现:
1)正弦波函数:
2)log输出函数
源代码函数:
/* USER CODE BEGIN Header */
/**
******************************************************************************
* File Name : waveLib.c
* Description : main task
******************************************************************************
* @attention
*
* COPYRIGHT: Copyright (c) 2024 tangmingfei2013@126.com
* CREATED BY: mingfei.tang
* DATE: JUL 05th, 2024
******************************************************************************
*/
/* USER CODE END Header */
#include "waveLib.h"
#include "dac.h"
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <math.h>
#define PI 3.14159
void DAC_SetConvert( uint32_t value)
{
HAL_DAC_SetValue( &hdac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R,value );
}
void dac_triangle_wave( void )
{
static uint32_t count = 0;
DAC_SetConvert(count);
count++;
if( count > 4095 )
{
count = 0;
}
}
float asin_wave( void )
{
static double t = -1;
float value, angle;
if( t >= 1 )
{
t = -1;
}
value = asin( t );
angle = (180*value)/3.1415926;
t += 0.001;
return angle;
}
float sin_wave( void )
{
float value, angle;
static double t = -1;
angle = 2*PI*t;
value = 100*sin( angle );
t += 0.001;
if( t >= 1 )
{
t = -1;
}
return value;
}
/* End of this file */
4.2 功能测试
4.2.1 采样频率测试
配置的采样频率
测试到采样频率
4.2.2 DAC输出波形
4.2.3 ADC采样波形
4.2.4 波形比较
作者:mftang