Indepent/Dual ADC+DMA+Software/Hardware Trigger

        我之前写过三篇有关ADC的文章。ADC构件制作,代码是基于STM32L431芯片。HAL ADC 代码基于STM32F103芯片。这两篇都属于单通道单次转换模式,独立ADC模式通过轮询(poll)方式完成ADC采样。后来写的第三篇ADC文章——High-resolution timer ,HRTIM(二),代码基于STM32G474,这篇文章属于Dual ADC模式,PWM中心触发ADC采样,DMA进行数据传输。前两篇属于软件触发ADC采样,第三篇属于通过硬件事件触发ADC采样。同时,第一篇属于Independent ADC,后两篇属于Dual ADC。本篇文章,将在STM32F103芯片上,分别实现Independent ADC+DMA+ Software,Dual ADC+DMA+Software/Hardware Trigger。

1.1 Independent ADC+DMA+ Software

        独立ADC模式,我选择ADC1模块,5,7,9,15通道(PTA5,PTA7,PTC5,PTB1引脚),并采用DMA进行半字传输(每次传输2个字节,一个通道数据)。进行数据演示,CubeIDE配置如下图。

int main(void)
{

  /* USER CODE BEGIN 1 */
	extern int adcSampleCount;
	uint32_t volArr[4]={0};
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_TIM1_Init();
  MX_USART1_UART_Init();
  MX_ADC1_Init();
  /* USER CODE BEGIN 2 */
  printf("indepent adc 0711\r\n");

  printf(" start dma adc\r\n");

  /* USER CODE END 2 */
  HAL_ADCEx_Calibration_Start(&hadc1);   //adc calibration,must add
  HAL_ADC_Start(&hadc1);
  HAL_ADC_PollForConversion(&hadc1,100);
  HAL_ADC_Start_DMA(&hadc1,(uint32_t *)gAdcSampleBuf,4);  //16
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	  HAL_Delay(500);
//	  HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_4);
	  printf("independent adc test %d\r\n",adcSampleCount);
	  for(int i=0;i<4;i++){
		printf("adc[%d]=%d ",i,gAdcSampleBuf[i]);
	  }
	  printf("\n");

	  HAL_ADC_Start(&hadc1);          //开启新一轮ADC采样,must
    }
}

1.2 Dual ADC+DMA+Software

        dual ADC模式下,ADC1作为主ADC,ADC2作为从ADC,分别开启2个通道,一次传输一个字,2个通道数据。主模块数据在低16位,从模块数据在高16位,这一点和STM32G474芯片不同。而且,单次转换结束后,需要分别开启ADC1,ADC2模块。开启DMA的方式也与独立ADC模式调用的函数不同。规则转换模式下的External Trigger Conversion Source选项需要配置为软件触发选项。

int main(void)
{

  /* USER CODE BEGIN 1 */
//  extern int adcSampleCount;
	uint32_t volArr[4]={0};
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_TIM1_Init();
  MX_USART1_UART_Init();
  MX_TIM3_Init();
  MX_ADC1_Init();
  MX_TIM8_Init();
  MX_TIM2_Init();
  MX_ADC2_Init();
  /* USER CODE BEGIN 2 */
  printf("pwm & dual adc,software as trigger\r\n");
  test_PWM_ADC_init();
  HAL_ADCEx_Calibration_Start(&hadc1);
  HAL_ADCEx_Calibration_Start(&hadc2);
  HAL_ADC_Start(&hadc1);
  HAL_ADC_Start(&hadc2);
  HAL_ADC_PollForConversion(&hadc1,100);
  volArr[0]=0;
  volArr[1]=0;
  HAL_ADCEx_MultiModeStart_DMA(&hadc1,(uint32_t *)volArr,2);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	  HAL_Delay(500);
//	  HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_4);

//	  printf("dual adc test %d\r\n",adcSampleCount);
	  printf("dual adc,software as trigger\r\n");
	  for(int i=0;i<2;i++){
		//		printf("volArr[%d] %d %d %x  ",i,(volArr[i]>>16),volArr[i]&0xFFFF,volArr[i]);
		printf("volArr[%d] %d %d ",i,(int)(volArr[i]>>16),(int)volArr[i]&0xFFFF);
	  }
	  printf("\n");

//	  HAL_ADCEx_MultiModeStart_DMA(&hadc1,(uint32_t *)volArr,2);
	  HAL_ADC_Start(&hadc1);
	  HAL_ADC_Start(&hadc2);
//	  LL_ADC_REG_StartConversion(ADC1);

    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

1.3 Dual ADC+DMA +Hardware Trigger

        Dual ADC 硬件触发ADC转换,我这里选择的转换源为Timer1 Capture Compare 3 Event。为此,需要再配置TIM1模块。此外,必须开启Timer1定时器3通道的输出功能,否则无法触发ADC采样。另外,设置TIM1模块3通道占空比,会改变adc数据的传输顺序,很奇怪,需要再看芯片手册。

int main(void)
{

  /* USER CODE BEGIN 1 */
	extern int adcSampleCount;
	uint32_t volArr[4]={0};
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_TIM1_Init();
  MX_USART1_UART_Init();
  MX_TIM3_Init();
  MX_ADC1_Init();
  MX_ADC2_Init();
  /* USER CODE BEGIN 2 */
  printf("pwm & dual adc,external trigger event test\r\n");
  test_PWM_ADC_init();
  HAL_ADCEx_Calibration_Start(&hadc1);
  HAL_ADCEx_Calibration_Start(&hadc2);
  HAL_ADC_Start(&hadc1);
  HAL_ADC_Start(&hadc2);
  HAL_ADC_PollForConversion(&hadc1,100);
  volArr[0]=0;
  volArr[1]=0;
  HAL_ADCEx_MultiModeStart_DMA(&hadc1,(uint32_t *)volArr,2);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	  HAL_Delay(500);

	  printf("external trigger event test\r\n");
	  for(int i=0;i<2;i++){
		printf("volData[%d] %d %d ",i,(int)(volArr[i]>>16),(int)volArr[i]&0xFFFF);
	  }
	  printf("\n");

    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}
......


void test_PWM_ADC_init(void)
{
	int PWM_PERIOD = 319;

//	HAL_TIM_PWM_Init(&htim1);

	HAL_TIM_Base_Start(&htim1);

	HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);

	HAL_TIMEx_PWMN_Start(&htim1,TIM_CHANNEL_1);

	HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_3);    //must

	__HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_1,0.2*PWM_PERIOD);

    __HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_3,0.6*PWM_PERIOD);  // affect adc data order

}




void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance == TIM1){
		HAL_ADC_Start(&hadc1);
		HAL_ADC_Start(&hadc2);
	}

}


.....


  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值