【蓝桥杯嵌入式】四、各种外设驱动(九)ADC(2):双ADC同步转换方式

温馨提示:本文不会重复之前提到的内容,如需查看,请参考附录

【蓝桥杯嵌入式】附录

目录

重点提炼:

理论知识:

一、需求分析

1、需要的外设资源分析:

 2、外设具体分析:

比赛时ADC可能需要配置的部分:

二、软件配置

按照分析配置外设:

三、程序功能实现

用到的函数:

程序流程:

在MDK中编写代码:

四、运行测试


重点提炼:

按照分析配置外设:

用到的函数:

数据读取:

双ADC同步转换方式中低16位是ADC1的数据,高16位是ADC2 的数据。需要做如下处理:

uint32_t adcValue=dmaDataBuffer[0];	//dmaDataBuffer是DMA读取数据的缓冲区

uint32_t ADC1_val=adcValue&0x0000FFFF;

uint32_t ADC2_val=(adcValue&0xFFFF0000)>>16;

理论知识:

一、需求分析

        本篇文章是上一篇文章四、各种外设驱动(十一)ADC(1):软件触发与中断触发方式的进阶,使用双ADC同步转换功能。

         开发板上有两个电压采集R37和R38,如图:

查看原理图可知,R37连接PB15,R38连接PB12.而使用CubeMX可以查到:PB15是ADC2的通道15,PB12是ADC1的通道11。

        我们将使用ADC1和ADC2同步采集两个通道的信号,分别采集对应的“电压采集”的信号。

1、需要的外设资源分析:

  • ADC1_IN11——PB12——R38(电压采集2)
  • ADC2_IN15——PB15——R37(电压采集1)
  • LCD
  • DMA

 2、外设具体分析:

查看原理图,和手册:

与LCD的相关的部分请参考附录。

比赛时ADC可能需要配置的部分:
  • ADC Mode:选择需要的通道,选择single_ended模式
  • ADCs_Common_Settings独立模式或多个ADC合作的模式
    • DMA Access Mode(DMA接入方式)
    • Delay between 2 sampling phases:(可选)(2个采样相位之间的间隔)
  • Resolution:转换精度
  • DMA Continuous Requests:是否连续产生DMA请求
  • External Trigger Conversion Source:中断触发方式
  • External Trigger Conversion Edge:外部触发时使用的信号沿
  • Rank里的Sampling Time:(可选)采样时间,不设置也行,比赛时为提高准确性设置为640.5。

二、软件配置

参考附录的内容,建立名为“ ADC_DualSimu_Demo”的项目。

按照分析配置外设:

先打开ADC2_IN15和ADC1_IN11,选择single_ended

在ADC1_IN11的配置中

  • ADCs_Common_Settings设置为Dual regular simultaneous mode only(双规则同步转换模式)
  • DMA Access Mode(DMA接入方式)设置为DMA access mode enable
  • Delay between 2 sampling phases(2个采样相位之间的间隔),保持默认或根据要求。
  • External Trigger Conversion Source:设置为Timer 6 Trigger Out event,使用定时器TIM6产生的UEV中断触发ADC转换

结果如图所示:

DMA Settings:

        ADC1只有一个DMA请求,为这个DMA请求配置DMA 通道(任意通道即可),设置DMA 传输属性参数,设置界面如下图所示。

        在DMA Request Settings组中将Mode(工作模式)设置为Circular(循环模式),将外设和存储器的数据宽度都设置为Word——因为ADC转换结果数据寄存器是32位的。

ADC2一般不用再做设置,但要注意:

ADC2除了Rank通道号外的其他可配置参数参赛都要和ADC1一致,以保证两个ADC能同步采集。 

 TIM6:

按照附录中内容将TIM6设置为500ms一次触发Trigger Event Selection中断设置为Update Event(UEV)。

无需开启TIM6的中断。

生成项目文件后,打开MDK;

导入LCD驱动程序文件,编译。

三、程序功能实现

用到的函数:

中断服务函数:

void DMA1_Channel1_IRQHandler(void)

ADC函数:

	HAL_ADCEx_MultiModeStart_DMA(&hadc1,dmaDataBuffer,DATA_LEN);
	HAL_ADCEx_MultiModeStart_DMA(&hadc2,dmaDataBuffer,DATA_LEN);

程序流程:

  1. 在初始化HAL库后初始化LCD,之前实验发现中断可能会影响LCD初始化。
  2. 在main.c中定义一些全局变量,在main.h中引入这些变量。
  3. 以同步DMA方式启动ADC1和ADC2;启动定时器。
  4. 找到并实现DMA的中断服务函数。

在MDK中编写代码:

 在 main.c 的对应代码段,定义全局变量;

 /* USER CODE BEGIN PV */
uint32_t dmaDataBuffer[DATA_LEN];
/* USER CODE END PV */

main.h中的对应代码段定义宏、引用外部变量。

/* USER CODE BEGIN Private defines */
#define DATA_LEN			1
extern uint32_t dmaDataBuffer[DATA_LEN];
/* USER CODE END Private defines */

 在main.h中的对应代码段进行引入文件。

/* USER CODE BEGIN Includes */
#include "lcd.h"
#include <stdio.h>
/* USER CODE END Includes */

在 main.c 的 /* USER CODE BEGIN WHILE */ 代码段,编写以下代码 

   /* USER CODE BEGIN WHILE */
	HAL_ADCEx_MultiModeStart_DMA(&hadc1,dmaDataBuffer,DATA_LEN);
	HAL_ADCEx_MultiModeStart_DMA(&hadc2,dmaDataBuffer,DATA_LEN);
	HAL_TIM_Base_Start(&htim6);
  while (1)
  {
    /* USER CODE END WHILE */

在找到ADC对应的DMA的中断服务函数:
(详细步骤请查看附录NVIC部分)

这里与上一篇文章有些不同,因为是对两个ADC使用同一个DMA通道,所以不用判断是谁引起中断,也就是说可以直接使用中断服务函数。

在代码段编写程序:

  /* USER CODE BEGIN DMA1_Channel1_IRQn 1 */
	uint32_t Volt;
	uint32_t adcValue=dmaDataBuffer[0];
	char str[20];
	
	uint32_t ADC1_val=adcValue&0x0000FFFF;
	Volt = (3300*ADC1_val)>>12;
	sprintf(str,"R38 Volt = %d",Volt);
	LCD_DisplayStringLine(Line3,str);
	
	uint32_t ADC2_val=(adcValue&0xFFFF0000)>>16;
	Volt = (3300*ADC2_val)>>12;
	sprintf(str,"R37 Volt = %d",Volt);
	LCD_DisplayStringLine(Line5,str);
  /* USER CODE END DMA1_Channel1_IRQn 1 */

四、运行测试

编译、下载(见附录)。

运行结果如下:

ADC_DualSimu_Demo

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值