细说STM32单片机ADC规则组多通道输入和DMA传输数据到Buffer并通过串口发送数据的方法

目录

一、ADC规则组多通道输入

二、工程配置

1、 时钟、DEBUG

2、 ADC1

(1) ADCs_Common_Settings组

(2)ADC_Settings组

(3)ADC_Regular_ConversionMode

3、USART2和Timer 3

4、NVIC

5、DMA

(1)DMA Settings

(2) 使用DMA时是否开启外设的全局中断

三、软件设计

1、main.c

四、下载运行


一、ADC规则组多通道输入

        当ADC只有一个输入通道,在转换结束后可以及时读出结果数据寄存器的内容。

        当规则转换组有多个通道时,应该使用扫描转换模式(Scan Conversion Mode),ADC在转换完一个通道后立刻转换下一个通道,直到规则组内的通道序列全部转换完成。规则转换只有一个转换结果数据寄存器,虽然可以设置在每个通道转换完之后就产生EOC事件中断,但是在多通道情况下,在EOC事件中断里读取转换结果数据可能是来不及的,更谈不上对数据进行显示或处理

        如果规则转换组有多个输入通道,应该使用DMA,使转换结果数据通过DMA传输自动保存到缓冲区中,在一个规则组转换结束后再对数据进行处理,或者采集多次数据后再处理。

        本例中建立一个工程,为规则组设置3个输入通道,使用扫描转换模式,通过DMA方式传输ADC转换结果数据。参考本文作者的文章:细说STM32单片机用定时器中断启动ADC转换并通过串口发送数据的方法-CSDN博客  https://wenchm.blog.csdn.net/article/details/144027184

二、工程配置

1、 时钟、DEBUG

        同参考文章。

2、 ADC1

(1) ADCs_Common_Settings组

  •  ADC1_IN1,single_ended;
  •  ADC1_IN2,single_ended;
  • 选中Vbat Channel;

        在ADC1的模式设置中,选择3个输入通道,IN1(PA0)、IN2(PA1)是外部模拟量输入通道,接可调电阻产生的可变电压。IN1、IN2在开发板的底板(关于底板请参考作者的其他文章中的描述,需要底板或者设计资料,请给作者留言)上调节。另外的IN3(PA2)使用内部输入通道,Vrefint Channel是内部参考电压通道,Vbat Channel是备用电源电压通道,二者择一。

(2)ADC_Settings组

  • Clock Prescaler:选择同步时钟4分频;
  • Resolution:12位;
  • Data Alignment:右对齐(Right alignment);
  • Scan Conversion Mode:Enabled
  • End of Conversion Selection:end of single conversion
  • Continuous Conversion Mode:Enabled;
  • Discontinuous Conversion Mode:Disabled;
  • DMA Continuous Requests:Enabled

        开启扫描转换模式(Scan Conversion Mode)和DMA连续请求(DMA Continuous Requests)。 

(3)ADC_Regular_ConversionMode

  • Number of Conversion:3
  • External Trigger Conversion Source:Timer 3 Trigger out envent;用于设置启动ADC转换的外部触发信号源,列表中列出了所有可选的信号源,是一些定时器的Trigger Out event或Capture Compare event,这里选择Timer 3 Trigger Out event,也就是定时器TIM3的TRGO信号。
  • External Trigger Conversion Edge:上跳沿;用于设置触发转换的跳变沿,可选上跳沿、下跳沿或双边都触发。这里选择上跳沿,因为TRGO是一个短时正脉冲信号。
  • Rank1:Channel1,采样时间(Sampling Time)=24.5,无偏移; 
  • Rank2:Channel2,采样时间(Sampling Time)=24.5,无偏移; 
  • Rank3:Channel Vbat,采样时间(Sampling Time)=24.5,无偏移; 

        设置转换个数为3,下面会自动生成3个Rank的设置,分别设置每个Rank的输入通道和采样时间,每个通道的采样时间可以不一样。3个Rank里模拟通道出现的顺序就是规则组转换的顺序。

        ADC_Settings组里的参数End of Conversion Selection的设定值不变,仍然是在每个通道转换完之后产生EOC信号。

        其它参数默认。

3、USART2和Timer 3

         同参考文章。

4、NVIC

         开启DMA的全局中断。

5、DMA

        ADC1只有一个DMA请求,为这个DMA请求配置DMA流DMA1 Channel1,设置DMA传输属性参数,DMA传输方向自动设置为Peripheral To Memory(外设到存储器)在DMA Request Settings组中将Mode(工作模式)设置为Circular(循环模式),将外设和存储器的数据宽度都设置为Word,因为ADC转换结果数据寄存器是32位的。存储器设置为地址自增加。

(1)DMA Settings

  •  为ADC1选择DMA1 Channel1,外设到内存,优先级中等;
  • Mode:Circular;
  • Data Width:Word;

(2) 使用DMA时是否开启外设的全局中断

        在使用ADC1的DMA方式传输时,即使不开启ADC1的全局中断,DMA传输功能也能正常工作,所以在NVIC设置部分关闭ADC1的全局中断。

        外设使用DMA时是否需要开启外设的全局中断,不同的外设情况不一样。例如,UART使用DMA时就必须开启UART的全局中断,虽然可以禁止UART的两个主要中断事件源。在外设使用DMA时,建议尽量不开启外设的全局中断,若必须开启,也要禁止外设的主要事件源产生硬件中断,因为DMA的传输完成事件中断使用外设的回调函数,若开启外设的中断事件源,则可能导致一个事件发生时回调函数被调用两次。

三、软件设计

1、main.c

/* USER CODE BEGIN Includes */
#include <stdio.h>
/* USER CODE END Includes */
/* USER CODE BEGIN PV */
#define	BATCH_DATA_LEN 3					// DMA data buffer length, must be an integer multiple of the number of channels
uint32_t	dmaDataBuffer[BATCH_DATA_LEN];	// DMA data buffer
/* USER CODE END PV */
/* USER CODE BEGIN 2 */
  HAL_ADC_Start_DMA(&hadc1, dmaDataBuffer, BATCH_DATA_LEN); // Start ADC1, DMA mode
  HAL_TIM_Base_Start(&htim3);								// Start TIM3
/* USER CODE END 2 */
/* USER CODE BEGIN 4 */
/* Callback function for DMA stream transfer completion event interrupt */
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
	uint32_t adcValue=0, Volt;
	for(uint8_t i=0; i<BATCH_DATA_LEN;i++)
	{
		// The buffer contains the conversion results of 3 channels.
		adcValue=dmaDataBuffer[i];
		Volt=3300*adcValue;
		Volt=Volt>>12;
		printf("ADC[%d] = %ld\r\n",i,Volt );
	}
}

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

        其中,dmaDataBuffer是DMA传输数据的缓冲区,是元素类型为uint32_t的数组,该数组的长度为BATCH_DATA_LEN。程序中定义BATCH_DATA_LEN的值为3,所以,发生DMA传输完成事件中断时,数组dmaDataBuffer中就存储了3个通道的一次转换结果,在DMA传输完成事件中断的回调函数里,就可以读出3个通道的转换结果。因为设置DMA工作模式为循环模式,所以会在定时器TIM3驱动下一直进行ADC转换和数据传输。

        DMA缓冲区长度BATCH_DATA_LEN也可以设置为3的整数倍,例如,设置为30。那么发生DMA传输完成中断时,数组dmaDataBuffer就存储了3个通道10个采样点的数据。在实际的ADC数据采集中,一般是采集一定的数据点之后再处理、显示或存储,还可以使用双缓冲区进一步提高效率。

        通过跟踪分析函数HAL_ADC_Start_DMA()和DMA流中断处理函数HAL_DMA_IRQHandler()的源代码,发现DMA流中断事件与ADC回调函数之间的关系见参考文章。DMA流的传输完成中断事件(DMA_IT_TC)关联着ADC的回调函数HAL_ADC_ConvCpltCallback()。

四、下载运行

 

        同样的参数设置和串口设置,DMA传输ADC的转换值到缓存,传输效率很高。

        串口助手上不断刷新显示3个通道的采集值。调节开发板上的电位器,可以看到Channel1、2的电压值明显变化;内部参考电压通道接的是内部1.2V调压器的输出,所以测量值是1200mV左右;VBAT通道内部有桥接分压器,实际测量的电压是VBAT/2。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wenchm

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值