细说STM32单片机软件触发设置DAC并在同一管脚上同时传递给ADC1和ADC2转换的方法

目录

一、实例说明

二、工程配置

1、KEYLED

2、RCC、DEBUG、CodeGenerator、USART3

3、GPIO

4、TIM3

5、DAC_OUT1、ADC1_IN4、ADC2_IN4

6、NVIC 

三、软件设计

1、keyled.c、keyled.h

2、main.c

四、运行调试


        在配置STM32单片机的管脚时,有的管脚可以同时配置为多种功能,这种情况给使用单片机的人带来十分的便利。比如,STM32F407ZGT6单片机只有一个DAC模块,这个模块有2个输出通道DAC_OUT1、DAC_OUT2。其中,DAC_OUT1输出引脚是PA4,DAC_OUT2输出引脚是PA5。在配置PA4为DAC_OUT1后,配置窗口出现绿色的“+”号,可以同时配置这个引脚为ADC1_IN4、ADC2_IN4。同理,当PA5管脚配置为DAC_OUT2后,可以同时配置这个引脚为ADC1_IN5、ADC2_IN5。

一、实例说明

         本实例的首要目的是介绍软件触发DAC的用法。另外介绍单片机的某些引脚,可以同时选择多个功能的,就比如本例的STM32F407ZG,可以同时配置PA4引脚为DAC_OUT1、ADC1_IN4、ADC2_IN4。

  • 本文将继续使用旺宝红龙开发板STM32F407ZGT6 KIT V1.0。
  • ADC1、ADC2使用IN4输入,在定时器TIM3的TRGO信号触发下采集,定时器周期500ms。
  • 通过开发板上的KeyUp、KeyDown按键控制DAC输出值的增加、减少,用软件出发方式设置DAC的输出值。
  • 在串口助手上显示设置的DAC值和转换的ADC值。
  • 菜单设计:
//菜单提示
[S2]KeyUp:   控制DAC1_OUT值增加,用软件触发方式设置DAC1输出
[S3]KeyDown: 控制DAC1_OUT值减少,用软件触发方式设置DAC1输出
[S6]SysReset 系统复位

        部分内容可参考本文作者的其他文章:写文章-CSDN创作中心  https://mpbeta.csdn.net/mp_blog/creation/editor/145881886

二、工程配置

1、KEYLED

        本文将继续引用KEYLED文件夹下的keyled.c和keyled.h文件,其使用方法参考本文作者发布的其他文章。

2、RCC、DEBUG、CodeGenerator、USART3

        同参考文章。

3、GPIO

        配置PA0为KeyUp,PD3为KeyDown,依此对应开发板上的按键S2、S3。

4、TIM3

         设置预分频因子为49999,计数周期为499,选择UpdateEvent。

5、DAC_OUT1、ADC1_IN4、ADC2_IN4

        配置PA4同时为 DAC_OUT1、ADC1_IN4、ADC2_IN4。

 

6、NVIC 

        设置ADC全局中断,其它中断根据需要设置。

三、软件设计

1、keyled.c、keyled.h

        参考本文作者的其他文章。

2、main.c

/* USER CODE BEGIN Includes */
#include <stdio.h>
#include "keyled.h"
/* USER CODE END Includes */
 /* USER CODE BEGIN 2 */
  //菜单设计
  uint8_t hello1[] = "Demo15_1_DAC:DAC1 by soft trigger\r\n";
  HAL_UART_Transmit(&huart3,hello1,sizeof(hello1),500);	//阻塞模式
  HAL_Delay(10);
  uint8_t hello2[] = "ADC1_OUT同时输出给DAC1_IN4和DCA2_IN4,直接在PA4上设置无需外部连接线.\r\n\r\n";
  HAL_UART_Transmit_IT(&huart3,hello2,sizeof(hello2));	//非阻塞模式
  HAL_Delay(10);

  //菜单提示
  printf("[S2]KeyUp:   控制DAC1_OUT值增加,用软件触发方式设置DAC1输出。\r\n");
  printf("[S3]KeyDown: 控制DAC1_OUT值减少,用软件触发方式设置DAC1输出。\r\n");
  printf("[S6]SysReset.\r\n\r\n");

  HAL_DAC_Start(&hdac,DAC_CHANNEL_1);		//启动DAC_OUT1
  uint32_t DacOutValue = 1000;   			//DAC1输出设定值,范围0--4095
  HAL_DAC_SetValue(&hdac, DAC_CHANNEL_1, DAC_ALIGN_12B_R, DacOutValue);
  printf("DAC1_OUT设置的初始值:%ld\r\n",DacOutValue);

  HAL_ADC_Start_IT(&hadc1);					//启动ADC1中断方式输入
  HAL_ADC_Start_IT(&hadc2);					//启动ADC2中断方式输入
  HAL_TIM_Base_Start(&htim3);				//启动TIM3,触发ADC定时采集
  /* USER CODE END 2 */
/* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	  KEYS curKey=ScanPressedKey(KEY_WAIT_ALWAYS);
	  if(curKey==KEY_UP)
		  DacOutValue += 50;
	  else if(curKey==KEY_DOWN)
		  DacOutValue -= 50;
	  else
		  return 0;

	  HAL_DAC_SetValue(&hdac, DAC_CHANNEL_1, DAC_ALIGN_12B_R, DacOutValue);
	  printf("DAC设置值并传递给ADC:%ld\r\n",DacOutValue);
	  HAL_Delay(300); //消除按键抖动影响
  }
  /* USER CODE END 3 */
/* USER CODE BEGIN 4 */
// ADC转换完毕中断回调函数
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
	if(hadc->Instance==ADC1)
	{
		uint32_t val=HAL_ADC_GetValue(hadc);  //读取ADC转换结果
		printf("ADC1_IN4采集的原始值:%ld\r\n",val);

		uint32_t Volt=3300*val;	//单位:mV
		Volt=Volt>>12;			//除以 2^12
		printf("ADC1_IN4转换的工程值:%ld\r\n",Volt);
	}
	if(hadc->Instance==ADC2)
	{
		uint32_t val=HAL_ADC_GetValue(hadc);  //读取ADC转换结果
		printf("ADC2_IN4采集的原始值:%ld\r\n",val);

		uint32_t Volt=5000*val;	//单位:mV,刻意为之以示区别
		Volt=Volt>>12;			//除以 2^12
		printf("ADC2_IN4转换的工程值:%ld\r\n",Volt);
	}
}

//串口打印
int __io_putchar(int ch)
{
	HAL_UART_Transmit(&huart3,(uint8_t*)&ch,1,0xFFFF);
	return ch;
}
/* USER CODE END 4 */

四、运行调试

        首次下载或S6复位后,最先在串口助手上显示的是系统菜单,之后,在助手上连续显示设置的DAC_OUT1值和转换后的ADC1_IN4、ADC2_IN4。 

        当按下S2键后,设置值+50,当按下S3键后,设置值-50。修改后的设置值软件方法设置给DAC。