|
使用定时器触发ADC采样,DMA双缓冲区配置,信号发生器给一个1KHz的方波,采集后的波形如下:

不知道是什么问题导致的,其中采样率设置为100KHz,采样周期32.5和ADC时钟中期,ADC时钟频率为32MHz。
代码如下:
extern UART_HandleTypeDef g_uartHandle;
ALIGN_32BYTES(__attribute__((section (".RAM_D3"))) uint16_t g_adc2Buffer[128]);
__IO uint8_t s_DmaFlag = 0; /* 1表示进DMA半传输完成中断,2表示进入DMA传输完成中断 */
__IO uint8_t g_adc_dma_sta = 0;
DMA_HandleTypeDef DmaHandle = {0};
ADC_HandleTypeDef AdcHandle = {0};
#define ADC_NUM_MAX (sizeof(g_adcGpioList)/sizeof(g_adcGpioList[0]))
typedef struct
{
GPIO_TypeDef *gpio;
uint32_t pin;
}AdcGpio_t;
static AdcGpio_t g_adcGpioList[] =
{
{GPIOC, GPIO_PIN_0}, //ADC2_INP4-->CH2+
{GPIOC, GPIO_PIN_5}, //ADC2_INN4-->CH2-
};
/**
***********************************************************************
*@brief 初始化ADC GPIO
*@param
*@return
***********************************************************************
**/
static void GpioInit(void)
{
GPIO_InitTypeDef gpioInitTypeDef = {0};
__HAL_RCC_GPIOC_CLK_ENABLE();
gpioInitTypeDef.Mode = GPIO_MODE_ANALOG;
for(uint8_t i = 0; i < ADC_NUM_MAX; i++)
{
gpioInitTypeDef.Pin = g_adcGpioList.pin;
HAL_GPIO_Init(g_adcGpioList.gpio, &gpioInitTypeDef);
}
}
static void AdcPreiphClkInit()
{
RCC_PeriphCLKInitTypeDef rccPeriphClkInit = {0};
/* 配置PLL2时钟为的72MHz,方便分频产生ADC最高时钟36MHz */
rccPeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;
rccPeriphClkInit.PLL2.PLL2M = 25;
rccPeriphClkInit.PLL2.PLL2N = 504;
rccPeriphClkInit.PLL2.PLL2P = 7;
rccPeriphClkInit.PLL2.PLL2Q = 7;
rccPeriphClkInit.PLL2.PLL2R = 7;
rccPeriphClkInit.PLL2.PLL2RGE = RCC_PLL2VCIRANGE_0;
rccPeriphClkInit.PLL2.PLL2VCOSEL = RCC_PLL2VCOWIDE;
rccPeriphClkInit.PLL2.PLL2FRACN = 0;
rccPeriphClkInit.AdcClockSelection = RCC_ADCCLKSOURCE_PLL2;
HAL_RCCEx_PeriphCLKConfig(&rccPeriphClkInit);
}
/*
*********************************************************************************************************
* 函 数 名: TIM1_Config
* 功能说明: 配置TIM1,用于触发ADC,当前配置的100KHz触发频率
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
static void TIM1_Config(void)
{
TIM_HandleTypeDef htim ={0};
TIM_OC_InitTypeDef sConfig = {0};
/* 使能时钟 */
__HAL_RCC_TIM1_CLK_ENABLE();
HAL_TIM_Base_DeInit(&htim);
htim.Instance = TIM1;
htim.Init.Period = 1999;
htim.Init.Prescaler = 0;
htim.Init.ClockDivision = 0;
htim.Init.CounterMode = TIM_COUNTERMODE_UP;
htim.Init.RepetitionCounter = 0;
HAL_TIM_Base_Init(&htim);
sConfig.OCMode = TIM_OCMODE_PWM1;
sConfig.OCPolarity = TIM_OCPOLARITY_LOW;
/* 占空比50% */
sConfig.Pulse = 1000;
HAL_TIM_OC_ConfigChannel(&htim, &sConfig, TIM_CHANNEL_1);
/* 启动OC1 */
HAL_TIM_OC_Start(&htim, TIM_CHANNEL_1);
}
static void Dma1Init(void)
{
__HAL_RCC_DMA1_CLK_ENABLE();
DmaHandle.Instance = DMA1_Stream1; /* 使用的DMA1 Stream1 */
DmaHandle.Init.Request = DMA_REQUEST_ADC2; /* 请求类型采用DMA_REQUEST_ADC1 */
DmaHandle.Init.Direction = DMA_PERIPH_TO_MEMORY; /* 传输方向是从外设到存储器 */
DmaHandle.Init.PeriphInc = DMA_PINC_DISABLE; /* 外设地址自增禁止 */
DmaHandle.Init.MemInc = DMA_MINC_ENABLE; /* 存储器地址自增使能 */
DmaHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; /* 外设数据传输位宽选择半字,即16bit */
DmaHandle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; /* 存储器数据传输位宽选择半字,即16bit */
DmaHandle.Init.Mode = DMA_CIRCULAR; /* 循环模式 */
DmaHandle.Init.Priority = DMA_PRIORITY_LOW; /* 优先级低 */
DmaHandle.Init.FIFOMode = DMA_FIFOMODE_DISABLE; /* 禁止FIFO*/
DmaHandle.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; /* 禁止FIFO此位不起作用,用于设置阀值 */
DmaHandle.Init.MemBurst = DMA_MBURST_SINGLE; /* 禁止FIFO此位不起作用,用于存储器突发 */
DmaHandle.Init.PeriphBurst = DMA_PBURST_SINGLE; /* 禁止FIFO此位不起作用,用于外设突发 */
HAL_DMA_Init(&DmaHandle);
/* 开启DMA1 Stream1的中断 */
HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);
/* 关联ADC句柄和DMA句柄 */
__HAL_LINKDMA(&AdcHandle, DMA_Handle, DmaHandle);
}
static void Adc2Init(void)
{
ADC_ChannelConfTypeDef sConfig = {0};
__HAL_RCC_ADC12_CLK_ENABLE();
AdcHandle.Instance = ADC2;
AdcHandle.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV2; /* 采用PLL异步时钟,2分频,即72MHz/2 = 36MHz */
AdcHandle.Init.Resolution = ADC_RESOLUTION_16B; /* 16位分辨率 */
AdcHandle.Init.ScanConvMode = ADC_SCAN_ENABLE; /* 禁止扫描,因为仅开了一个通道 */ //++++
AdcHandle.Init.EOCSelection = ADC_EOC_SINGLE_CONV; /* EOC转换结束标志 */
AdcHandle.Init.LowPowerAutoWait = DISABLE; /* 禁止低功耗自动延迟特性 */
AdcHandle.Init.ContinuousConvMode = ENABLE; /* 禁止自动转换,采用的定时器触发转换 */ //++
AdcHandle.Init.NbrOfConversion = 2; /* 使用了1个转换通道 */
AdcHandle.Init.DiscontinuousConvMode = DISABLE; /* 禁止不连续模式 */
AdcHandle.Init.NbrOfDiscConversion = 1; /* 禁止不连续模式后,此参数忽略,此位是用来配置不连续子组中通道数 */
AdcHandle.Init.ExternalTrigConv = ADC_EXTERNALTRIG_T1_CC1; /* 定时器1的CC1触发 */
AdcHandle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING; /* 上升沿触发 */
AdcHandle.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR; /* DMA循环模式接收ADC转换的数据 */
AdcHandle.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN; /* ADC转换溢出的话,覆盖ADC的数据寄存器 */
AdcHandle.Init.OversamplingMode = DISABLE;
HAL_ADC_Init(&AdcHandle);
HAL_ADCEx_Calibration_Start(&AdcHandle, ADC_CALIB_OFFSET, ADC_DIFFERENTIAL_ENDED);
/* 配置ADC通道 */
sConfig.Channel = ADC_CHANNEL_4; /* 配置使用的ADC通道 */
sConfig.Rank = ADC_REGULAR_RANK_1; /* 采样序列里的第1个 */
sConfig.SamplingTime = ADC_SAMPLETIME_32CYCLES_5; /* 采样周期 */
sConfig.SingleDiff = ADC_DIFFERENTIAL_ENDED; /* 单端输入 */
sConfig.OffsetNumber = ADC_OFFSET_NONE; /* 无偏移 */
sConfig.Offset = 0; /* 无偏移的情况下,此参数忽略 */
HAL_ADC_ConfigChannel(&AdcHandle, &sConfig);
TIM1_Config();
HAL_ADC_Start_DMA(&AdcHandle, (uint32_t *)g_adc2Buffer, 128);
}
void AdcDrvInit(void)
{
AdcPreiphClkInit();
GpioInit();
Dma1Init();
Adc2Init();
}
/**
* @brief ADC DMA采集中断服务函数
* @param 无
* @retval 无
*/
uint8_t s_dmaFlag = 0;
void DMA1_Stream1_IRQHandler(void)
{
if((DMA1->LISR & DMA_FLAG_TCIF1_5) != RESET)
{
s_dmaFlag = 2;
DMA1->LIFCR = DMA_FLAG_TCIF1_5;
}
if((DMA1->LISR & DMA_FLAG_HTIF1_5) != RESET)
{
s_dmaFlag = 1;
DMA1->LIFCR = DMA_FLAG_HTIF1_5;
}
/* 传输错误中断 */
if((DMA1->LISR & DMA_FLAG_TEIF1_5) != RESET)
{
/* 清除标志 */
DMA1->LIFCR = DMA_FLAG_TEIF1_5;
}
/* 直接模式错误中断 */
if((DMA1->LISR & DMA_FLAG_DMEIF1_5) != RESET)
{
/* 清除标志 */
DMA1->LIFCR = DMA_FLAG_DMEIF1_5;
}
g_adc_dma_sta = 1;
}
void bsp_GetAdcValues(void)
{
uint32_t values;
uint32_t sam;
uint8_t byte1;
uint8_t byte2;
float temp;
/* 当前DMA操作是后半个缓冲,读取前半个缓冲的前4个数值求平均 */
if(s_dmaFlag == 1)
{
DISABLE_INT();
s_dmaFlag = 0;
for(uint16_t i = 0; i < 64; i++)
{
values = g_adc2Buffer;
printf("%d\r\n", g_adc2Buffer);
}
ENABLE_INT();
}
/* 当前DMA操作是后前个缓冲,读取后半个缓冲的前4个数值求平均 */
else if(s_dmaFlag == 2)
{
DISABLE_INT();
s_dmaFlag = 0;
for(uint16_t j = 0; j < 64; j++)
{
values = g_adc2Buffer[j+64];
printf("%d\r\n", g_adc2Buffer[j]);
}
ENABLE_INT();
}
}
|
|