STM32CubeIDE STM32H743实现TIM定时触发ADC实现多通道DMA方式采样

在STM32CubeIDE 1.4.0环境下测试通过。

1. ADC设置

在这里插入图片描述
在这里插入图片描述

2. DMA设置

在这里插入图片描述
在这里插入图片描述

3. TIM设置

TIM4位于APB1,
在这里插入图片描述
在这里插入图片描述
APB1 Timer时钟是200MHz
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

f=200MHz/200/1000=1kHz, 以上实现1ms触发一次中断。

4. 代码如下:
HAL_TIM_Base_Start(&htim4);//打开定时器
HAL_ADCEx_Calibration_Start(&hadc1,ADC_CALIB_OFFSET,ADC_SINGLE_ENDED);
HAL_ADC_Start_DMA(&hadc1, (uint32_t *)&buf, 4);
5. 测试代码
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
  /* Prevent unused argument(s) compilation warning */
	if(hadc == &hadc1)
	{
		Cnt ++;
    	HAL_GPIO_TogglePin(TP_GPIO_Port, TP_Pin);
	}
}

测试波形
实现DMA方式1ms采样4个通道,因为数组只有4个元素,则采集完之后就进入HAL_ADC_ConvCpltCallback中断。定时的时间实际是采样一遍所有通道的时间,而不是采集一个AD通道的时间。
如果buf数组改大例如buf[4000],则1s进一次HAL_ADC_ConvCpltCallback中断。
在这里插入图片描述

6. 说明

https://cloud.tencent.com/developer/article/1572183
在这里插入图片描述

1. ScanConvMode

用于使能或者禁止ADC的扫描模式,即多通道转换。此参数配合成员DiscontinuousConvMode可以将主转换序列分成多个子系列进行逐步转换。
禁止扫描模式,表示单通道转换,成员NbrOfConversion和InjectedNbrOfConversion不起作用,等效为1,即仅进行一个通道转换。
使能扫描模式,表示支持多通道转换,成员NbrOfConversion和InjectedNbrOfConversion分别用于规则通道和注入通道转换序列数。
支持的参数如下:

在这里插入图片描述

2. ContinuousConvMode

用于配置使用单次转换还是连续转换,此参数仅对规则通道有效。触发方式可以选择软件触发或者外部触发。
参数可以是使能ENABLE,表示连续转换或者DISABLE禁能,表示单次转换。
在这里插入图片描述

3. DiscontinuousConvMode

用于配置ADC规则组转换序列的不连续方式。这里的不连续含义是指每次触发进行一个子组的转换。注意跟参数成员ContinuousConvMode的含义区分开。
使能此参数,要转换的整个序列通道1,2,6,7,8,10,设置2个为一个子组,那么第1次触发会进行通道1和通道2的转换,下次触发进行通道6和通道7的转换,以此进行了。
禁止此参数,要转换的整个序列通道1,2,6,7,8,10,那么第1次触发会进行所有通道的转换。
使用此参数要注意以下两点:
只有参数成员ScanConvMode使能的情况下,此参数才有使用的意义,否则忽略此参数。
只有参数成员ContinuousConvMode禁止的情况下,此参数才有使用的意义,否则忽略此参数。也就是说这两个参数不能同时使能。
参数可以是使能ENABLE或者禁止DISABLE。
在这里插入图片描述

NbrOfDiscConversion

使能了参数DiscontinuousConvMode的情况下,用于设置子组的大小。
仅用于规则通道。
如果参数DiscontinuousConvMode禁止的情况下,忽略此参数。
此参数范围1到8。

ExternalTrigConv

用于规则通道外部触发源的选择。如果使能了软件触发,那么外部触发将被关闭,使用软件触发。ADC1,ADC2和ADC3支持的触发源是相同的。具体支持的触发源参数如下:

/** @defgroup ADC_regular_external_trigger_source ADC group regular trigger source * @{ // External triggers of regular group for ADC1, ADC2, ADC3 */#define ADC_EXTERNALTRIG_T1_CC1 ((uint32_t)0x00000000)#define ADC_EXTERNALTRIG_T1_CC2 ((uint32_t)ADC_CFGR_EXTSEL_0)#define ADC_EXTERNALTRIG_T1_CC3 ((uint32_t)ADC_CFGR_EXTSEL_1)#define ADC_EXTERNALTRIG_T2_CC2 ((uint32_t)(ADC_CFGR_EXTSEL_1 | ADC_CFGR_EXTSEL_0))#define ADC_EXTERNALTRIG_T3_TRGO ((uint32_t)ADC_CFGR_EXTSEL_2)#define ADC_EXTERNALTRIG_T4_CC4 ((uint32_t)(ADC_CFGR_EXTSEL_2 | ADC_CFGR_EXTSEL_0))#define ADC_EXTERNALTRIG_EXT_IT11 ((uint32_t)(ADC_CFGR_EXTSEL_2 | ADC_CFGR_EXTSEL_1))#define ADC_EXTERNALTRIG_T8_TRGO ((uint32_t)(ADC_CFGR_EXTSEL_2 | ADC_CFGR_EXTSEL_1 | ADC_CFGR_EXTSEL_0))#define ADC_EXTERNALTRIG_T8_TRGO2 ((uint32_t) ADC_CFGR_EXTSEL_3)#define ADC_EXTERNALTRIG_T1_TRGO ((uint32_t)(ADC_CFGR_EXTSEL_3 | ADC_CFGR_EXTSEL_0))#define ADC_EXTERNALTRIG_T1_TRGO2 ((uint32_t)(ADC_CFGR_EXTSEL_3 | ADC_CFGR_EXTSEL_1))#define ADC_EXTERNALTRIG_T2_TRGO ((uint32_t)(ADC_CFGR_EXTSEL_3 | ADC_CFGR_EXTSEL_1 | ADC_CFGR_EXTSEL_0))#define ADC_EXTERNALTRIG_T4_TRGO ((uint32_t)(ADC_CFGR_EXTSEL_3 | ADC_CFGR_EXTSEL_2))#define ADC_EXTERNALTRIG_T6_TRGO ((uint32_t)(ADC_CFGR_EXTSEL_3 | ADC_CFGR_EXTSEL_2 | ADC_CFGR_EXTSEL_0))#define ADC_EXTERNALTRIG_T15_TRGO ((uint32_t)(ADC_CFGR_EXTSEL_3 | ADC_CFGR_EXTSEL_2 | ADC_CFGR_EXTSEL_1))#define ADC_EXTERNALTRIG_T3_CC4 ((uint32_t)(ADC_CFGR_EXTSEL_3 | ADC_CFGR_EXTSEL_2 | ADC_CFGR_EXTSEL_1 | ADC_CFGR_EXTSEL_0))#define ADC_EXTERNALTRIG_HR1_ADCTRG1 ((uint32_t) ADC_CFGR_EXTSEL_4)#define ADC_EXTERNALTRIG_HR1_ADCTRG3 ((uint32_t) (ADC_CFGR_EXTSEL_4 | ADC_CFGR_EXTSEL_0))#define ADC_EXTERNALTRIG_LPTIM1_OUT ((uint32_t) (ADC_CFGR_EXTSEL_4 | ADC_CFGR_EXTSEL_1))#define ADC_EXTERNALTRIG_LPTIM2_OUT ((uint32_t) (ADC_CFGR_EXTSEL_4 | ADC_CFGR_EXTSEL_1| ADC_CFGR_EXTSEL_0))#define ADC_EXTERNALTRIG_LPTIM3_OUT ((uint32_t) (ADC_CFGR_EXTSEL_4 | ADC_CFGR_EXTSEL_2))

ExternalTrigConvEdge

如果使用外部触发的话,设置触发沿类型,支持上升沿、下降沿或者双沿触发。
#define ADC_EXTERNALTRIGCONVEDGE_NONE ((uint32_t)0x00000000) #define ADC_EXTERNALTRIGCONVEDGE_RISING ((uint32_t)ADC_CFGR_EXTEN_0) #define ADC_EXTERNALTRIGCONVEDGE_FALLING ((uint32_t)ADC_CFGR_EXTEN_1) #define ADC_EXTERNALTRIGCONVEDGE_RISINGFALLING ((uint32_t)ADC_CFGR_EXTEN)
注意,如果使能了软件触发,那么外部触发将被关闭,使用软件触发,此参数已经不起作用。

ConversionDataManagement

此参数成员用于ADC采集数据的管理,可以存到ADC的DR寄存器,传输给DFSDM,又或者通过DMA的单次或者循环模式传输数据到指定地址。

/** @defgroup ADC_ConversionDataManagement ADC Conversion Data Management * @{ */#define ADC_CONVERSIONDATA_DR ((uint32_t)0x00000000) #define ADC_CONVERSIONDATA_DFSDM ((uint32_t)ADC_CFGR_DMNGT_1) #define ADC_CONVERSIONDATA_DMA_ONESHOT ((uint32_t)ADC_CFGR_DMNGT_0) #define ADC_CONVERSIONDATA_DMA_CIRCULAR ((uint32_t)(ADC_CFGR_DMNGT_0 | ADC_CFGR_DMNGT_1))

使用此参数成员注意以下问题:
如果参数成员ContinuousConvMode配置为连续转换模式,那么DMA必须配置为循环模式,否则会造成DMA传输溢出。
仅当规则通道上没有后续的转换时才可以修改此参数(即ADC禁止的情况下或者ADC单次转换模式,又或者无外部触发)。

以下是基于HAL库的stm32f407定时触发adc dma多通道采样代码: 首先,需要初始化定时器和ADC: ``` TIM_HandleTypeDef htim; ADC_HandleTypeDef hadc; void MX_TIM_Init(void) { TIM_MasterConfigTypeDef sMasterConfig = {0}; htim.Instance = TIMx; htim.Init.Prescaler = TIMx_PRESCALER; htim.Init.CounterMode = TIM_COUNTERMODE_UP; htim.Init.Period = TIMx_PERIOD; htim.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim.Init.RepetitionCounter = 0; HAL_TIM_Base_Init(&htim); sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; HAL_TIMEx_MasterConfigSynchronization(&htim, &sMasterConfig); } void MX_ADC_Init(void) { ADC_ChannelConfTypeDef sConfig = {0}; hadc.Instance = ADCx; hadc.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV2; hadc.Init.Resolution = ADC_RESOLUTION_12B; hadc.Init.ScanConvMode = ENABLE; hadc.Init.ContinuousConvMode = DISABLE; hadc.Init.DiscontinuousConvMode = DISABLE; hadc.Init.NbrOfDiscConversion = 0; hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING; hadc.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_Tx_TRGO; hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT; hadc.Init.NbrOfConversion = ADC_CHANNEL_NUM; hadc.Init.DMAContinuousRequests = ENABLE; hadc.Init.EOCSelection = ADC_EOC_SEQ_CONV; HAL_ADC_Init(&hadc); for (int i = 0; i < ADC_CHANNEL_NUM; ++i) { sConfig.Channel = ADC_CHANNEL_x[i]; sConfig.Rank = i + 1; sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES; HAL_ADC_ConfigChannel(&hadc, &sConfig); } } ``` 然后,需要初始化DMA和中断: ``` DMA_HandleTypeDef hdma_adc; void MX_DMA_Init(void) { hdma_adc.Instance = DMAx_STREAMx; hdma_adc.Init.Channel = DMA_CHANNELx; hdma_adc.Init.Direction = DMA_PERIPH_TO_MEMORY; hdma_adc.Init.PeriphInc = DMA_PINC_DISABLE; hdma_adc.Init.MemInc = DMA_MINC_ENABLE; hdma_adc.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; hdma_adc.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; hdma_adc.Init.Mode = DMA_CIRCULAR; hdma_adc.Init.Priority = DMA_PRIORITY_HIGH; hdma_adc.Init.FIFOMode = DMA_FIFOMODE_DISABLE; HAL_DMA_Init(&hdma_adc); __HAL_LINKDMA(&hadc, DMA_Handle, hdma_adc); } void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) { if (hadc->Instance == ADCx) { HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin); } } ``` 最后,在main函数中启动定时器和DMA: ``` int main(void) { HAL_Init(); MX_TIM_Init(); MX_ADC_Init(); MX_DMA_Init(); HAL_TIM_Base_Start(&htim); HAL_ADC_Start_DMA(&hadc, (uint32_t*)adc_buf, ADC_CHANNEL_NUM); while (1) { HAL_Delay(1000); } } ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值