21ic问答首页 - G032实现双通道ADC+DMA出现采集错误
G032实现双通道ADC+DMA出现采集错误
本帖最后由 阿斯顿发大水 于 2025-11-20 15:27 编辑
N32G032实现双通道ADC+DMA实现数据采集
void RCC_Configuration(void)
{
ErrorStatus HSIStartUpStatus; // HSI启动状态
// 1. 使能ADC、DMA、GPIOA时钟(确保时钟已使能)
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA , ENABLE);
RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_DMA, ENABLE);
RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_ADC, ENABLE);
/* 使能HSI时钟 */
RCC_EnableHsi(ENABLE);
/* 等待HSI稳定(最多等待10ms,超时则启动失败) */
HSIStartUpStatus = RCC_WaitHsiStable();
if (HSIStartUpStatus != SUCCESS)
{
/* HSI启动失败,进入死循环(需硬件复位) */
while (1);
}
/* 配置ADC时钟(ADC工作频率需≤18MHz) ADC_1MCLK用于内部计时功能,在RCC中配置,频率大小必须配置成1M */
RCC_ConfigAdc1mClk(RCC_ADC1MCLK_SRC_HSI, RCC_ADC1MCLK_DIV8); // ADC1M时钟=HSI/8=1MHz
// RCC_ConfigAdcHclk(RCC_ADCHCLK_DIV16); // ADC核时钟=AHB/16=3MHz
ADC_ConfigClk(ADC_CTRL3_CKMOD_AHB, RCC_ADCHCLK_DIV16);
}
void ADC_DMA_Configuration(void)
{
ADC_InitType ADC_InitStructure;
DMA_InitType DMA_InitStructure;
GPIO_InitType GPIO_InitStructure;
ADC_InitTypeEx ADC_InitStructureEx;
RCC_Configuration();
// 1. 配置PA0、PA1为模拟输入
GPIO_InitStruct(&GPIO_InitStructure);
GPIO_InitStructure.Pin = PA0_MAINS_ZERO_PIN | PA1_INV_VOLT_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_ANALOG;
GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
// 2. 配置DMA通道(单通道传输多个ADC数据)
DMA_DeInit(DMA_CH1); // 使用通道1
DMA_StructInit(&DMA_InitStructure);
DMA_InitStructure.PeriphAddr = (uint32_t)&ADC->DAT; // ADC数据寄存器
DMA_InitStructure.MemAddr = (uint32_t)&adc_values[0]; // 起始地址
DMA_InitStructure.Direction = DMA_DIR_PERIPH_SRC; // 外设→内存
DMA_InitStructure.BufSize = 2; // 传输2个通道数据
DMA_InitStructure.PeriphInc = DMA_PERIPH_INC_DISABLE; // 外设地址固定
DMA_InitStructure.DMA_MemoryInc = DMA_MEM_INC_ENABLE; // 内存地址递增
DMA_InitStructure.PeriphDataSize = DMA_PERIPH_DATA_SIZE_HALFWORD; // 16位
DMA_InitStructure.MemDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.CircularMode = DMA_MODE_CIRCULAR; // 循环模式
DMA_InitStructure.Priority = DMA_PRIORITY_HIGH;
DMA_InitStructure.Mem2Mem = DMA_M2M_DISABLE;
DMA_Init(DMA_CH1, &DMA_InitStructure);
DMA_RequestRemap(DMA_REMAP_ADC, DMA, DMA_CH1, ENABLE);
DMA_EnableChannel(DMA_CH1, ENABLE);
// 3. 配置ADC多通道扫描
ADC_InitStruct(&ADC_InitStructure);
ADC_InitStructure.MultiChEn = ENABLE; // 多通道使能
ADC_InitStructure.ContinueConvEn = ENABLE; // 连续转换
ADC_InitStructure.ExtTrigSelect = ADC_EXT_TRIGCONV_NONE; // 软件触发
ADC_InitStructure.DatAlign = ADC_DAT_ALIGN_R; // 右对齐
ADC_InitStructure.ChsNumber = 2; // 2个转换通道
ADC_Init(ADC, &ADC_InitStructure);
// 4. 配置通道转换顺序
// PA0(ADC_CH0):第1个转换
ADC_ConfigRegularChannel(ADC, ADC_CH_0_PA0, 1, ADC_SAMP_TIME_56CYCLES5);
// PA1(ADC_CH1):第2个转换
ADC_ConfigRegularChannel(ADC, ADC_CH_1_PA1, 2, ADC_SAMP_TIME_56CYCLES5);
// 5. 使能ADC并等待就绪
ADC_Enable(ADC, ENABLE);
while (!ADC_GetFlagStatusNew(ADC, ADC_FLAG_RDY));
while (ADC_GetFlagStatusNew(ADC, ADC_FLAG_PD_RDY));
// 6. 使能ADC-DMA,启动转换
ADC_EnableDMA(ADC, ENABLE);
ADC_EnableSoftwareStartConv(ADC, ENABLE);
}
不管有没有输入,采集的数据都是接近12位的最大值
N32G032实现双通道ADC+DMA实现数据采集
void RCC_Configuration(void)
{
ErrorStatus HSIStartUpStatus; // HSI启动状态
// 1. 使能ADC、DMA、GPIOA时钟(确保时钟已使能)
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA , ENABLE);
RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_DMA, ENABLE);
RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_ADC, ENABLE);
/* 使能HSI时钟 */
RCC_EnableHsi(ENABLE);
/* 等待HSI稳定(最多等待10ms,超时则启动失败) */
HSIStartUpStatus = RCC_WaitHsiStable();
if (HSIStartUpStatus != SUCCESS)
{
/* HSI启动失败,进入死循环(需硬件复位) */
while (1);
}
/* 配置ADC时钟(ADC工作频率需≤18MHz) ADC_1MCLK用于内部计时功能,在RCC中配置,频率大小必须配置成1M */
RCC_ConfigAdc1mClk(RCC_ADC1MCLK_SRC_HSI, RCC_ADC1MCLK_DIV8); // ADC1M时钟=HSI/8=1MHz
// RCC_ConfigAdcHclk(RCC_ADCHCLK_DIV16); // ADC核时钟=AHB/16=3MHz
ADC_ConfigClk(ADC_CTRL3_CKMOD_AHB, RCC_ADCHCLK_DIV16);
}
void ADC_DMA_Configuration(void)
{
ADC_InitType ADC_InitStructure;
DMA_InitType DMA_InitStructure;
GPIO_InitType GPIO_InitStructure;
ADC_InitTypeEx ADC_InitStructureEx;
RCC_Configuration();
// 1. 配置PA0、PA1为模拟输入
GPIO_InitStruct(&GPIO_InitStructure);
GPIO_InitStructure.Pin = PA0_MAINS_ZERO_PIN | PA1_INV_VOLT_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_ANALOG;
GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
// 2. 配置DMA通道(单通道传输多个ADC数据)
DMA_DeInit(DMA_CH1); // 使用通道1
DMA_StructInit(&DMA_InitStructure);
DMA_InitStructure.PeriphAddr = (uint32_t)&ADC->DAT; // ADC数据寄存器
DMA_InitStructure.MemAddr = (uint32_t)&adc_values[0]; // 起始地址
DMA_InitStructure.Direction = DMA_DIR_PERIPH_SRC; // 外设→内存
DMA_InitStructure.BufSize = 2; // 传输2个通道数据
DMA_InitStructure.PeriphInc = DMA_PERIPH_INC_DISABLE; // 外设地址固定
DMA_InitStructure.DMA_MemoryInc = DMA_MEM_INC_ENABLE; // 内存地址递增
DMA_InitStructure.PeriphDataSize = DMA_PERIPH_DATA_SIZE_HALFWORD; // 16位
DMA_InitStructure.MemDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.CircularMode = DMA_MODE_CIRCULAR; // 循环模式
DMA_InitStructure.Priority = DMA_PRIORITY_HIGH;
DMA_InitStructure.Mem2Mem = DMA_M2M_DISABLE;
DMA_Init(DMA_CH1, &DMA_InitStructure);
DMA_RequestRemap(DMA_REMAP_ADC, DMA, DMA_CH1, ENABLE);
DMA_EnableChannel(DMA_CH1, ENABLE);
// 3. 配置ADC多通道扫描
ADC_InitStruct(&ADC_InitStructure);
ADC_InitStructure.MultiChEn = ENABLE; // 多通道使能
ADC_InitStructure.ContinueConvEn = ENABLE; // 连续转换
ADC_InitStructure.ExtTrigSelect = ADC_EXT_TRIGCONV_NONE; // 软件触发
ADC_InitStructure.DatAlign = ADC_DAT_ALIGN_R; // 右对齐
ADC_InitStructure.ChsNumber = 2; // 2个转换通道
ADC_Init(ADC, &ADC_InitStructure);
// 4. 配置通道转换顺序
// PA0(ADC_CH0):第1个转换
ADC_ConfigRegularChannel(ADC, ADC_CH_0_PA0, 1, ADC_SAMP_TIME_56CYCLES5);
// PA1(ADC_CH1):第2个转换
ADC_ConfigRegularChannel(ADC, ADC_CH_1_PA1, 2, ADC_SAMP_TIME_56CYCLES5);
// 5. 使能ADC并等待就绪
ADC_Enable(ADC, ENABLE);
while (!ADC_GetFlagStatusNew(ADC, ADC_FLAG_RDY));
while (ADC_GetFlagStatusNew(ADC, ADC_FLAG_PD_RDY));
// 6. 使能ADC-DMA,启动转换
ADC_EnableDMA(ADC, ENABLE);
ADC_EnableSoftwareStartConv(ADC, ENABLE);
}
不管有没有输入,采集的数据都是接近12位的最大值

问答
您需要登录后才可以回复 登录 | 注册