【STM32】STM32学习笔记-DMA数据转运+AD多通道(24)

news2024/11/27 12:38:29

00. 目录

文章目录

    • 00. 目录
    • 01. DMA简介
    • 02. DMA相关API
      • 2.1 DMA_Init
      • 2.2 DMA_InitTypeDef
      • 2.3 DMA_Cmd
      • 2.4 DMA_SetCurrDataCounter
      • 2.5 DMA_GetFlagStatus
      • 2.6 DMA_ClearFlag
    • 03. DMA数据单通道接线图
    • 04. DMA数据单通道示例
    • 05. DMA数据多通道接线图
    • 06. DMA数据多通道示例一
    • 07. DMA数据多通道示例二
    • 08. 程序下载
    • 09. 附录

01. DMA简介

小容量产品是指闪存存储器容量在16K至32K字节之间的STM32F101xx、STM32F102xx和STM32F103xx微控制器。

中容量产品是指闪存存储器容量在64K至128K字节之间的STM32F101xx、STM32F102xx和STM32F103xx微控制器。

大容量产品是指闪存存储器容量在256K至512K字节之间的STM32F101xx和STM32F103xx微控制器。

互联型产品是指STM32F105xx和STM32F107xx微控制器。

直接存储器存取(DMA)用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。无须CPU干预,数据可以通过DMA快速地移动,这就节省了CPU的资源来做其他操作。

两个DMA控制器有12个通道(DMA1有7个通道,DMA2有5个通道),每个通道专门用来管理来自于一个或多个外设对存储器访问的请求。还有一个仲裁器来协调各个DMA请求的优先权。

02. DMA相关API

2.1 DMA_Init

/**
  * @brief  Initializes the DMAy Channelx according to the specified
  *         parameters in the DMA_InitStruct.
  * @param  DMAy_Channelx: where y can be 1 or 2 to select the DMA and 
  *   x can be 1 to 7 for DMA1 and 1 to 5 for DMA2 to select the DMA Channel.
  * @param  DMA_InitStruct: pointer to a DMA_InitTypeDef structure that
  *         contains the configuration information for the specified DMA Channel.
  * @retval None
  */
void DMA_Init(DMA_Channel_TypeDef* DMAy_Channelx, DMA_InitTypeDef* DMA_InitStruct)
功能:
	根据 DMA_InitStruct 中指定的参数初始化 DMA 的通道 x 寄存器
参数:
   DMA Channelx:x 可以是 12…,或者 7 来选择 DMA 通道 x
   DMA_InitStruct:指向结构 DMA_InitTypeDef 的指针,包含了 DMA 通道 x 的配置信息    
返回值:

2.2 DMA_InitTypeDef

/** 
  * @brief  DMA Init structure definition
  */

typedef struct
{
  uint32_t DMA_PeripheralBaseAddr; /*!< Specifies the peripheral base address for DMAy Channelx. */

  uint32_t DMA_MemoryBaseAddr;     /*!< Specifies the memory base address for DMAy Channelx. */

  uint32_t DMA_DIR;                /*!< Specifies if the peripheral is the source or destination.
                                        This parameter can be a value of @ref DMA_data_transfer_direction */

  uint32_t DMA_BufferSize;         /*!< Specifies the buffer size, in data unit, of the specified Channel. 
                                        The data unit is equal to the configuration set in DMA_PeripheralDataSize
                                        or DMA_MemoryDataSize members depending in the transfer direction. */

  uint32_t DMA_PeripheralInc;      /*!< Specifies whether the Peripheral address register is incremented or not.
                                        This parameter can be a value of @ref DMA_peripheral_incremented_mode */

  uint32_t DMA_MemoryInc;          /*!< Specifies whether the memory address register is incremented or not.
                                        This parameter can be a value of @ref DMA_memory_incremented_mode */

  uint32_t DMA_PeripheralDataSize; /*!< Specifies the Peripheral data width.
                                        This parameter can be a value of @ref DMA_peripheral_data_size */

  uint32_t DMA_MemoryDataSize;     /*!< Specifies the Memory data width.
                                        This parameter can be a value of @ref DMA_memory_data_size */

  uint32_t DMA_Mode;               /*!< Specifies the operation mode of the DMAy Channelx.
                                        This parameter can be a value of @ref DMA_circular_normal_mode.
                                        @note: The circular buffer mode cannot be used if the memory-to-memory
                                              data transfer is configured on the selected Channel */

  uint32_t DMA_Priority;           /*!< Specifies the software priority for the DMAy Channelx.
                                        This parameter can be a value of @ref DMA_priority_level */

  uint32_t DMA_M2M;                /*!< Specifies if the DMAy Channelx will be used in memory-to-memory transfer.
                                        This parameter can be a value of @ref DMA_memory_to_memory */
}DMA_InitTypeDef;

DMA_PeripheralBaseAddr

该参数用以定义 DMA 外设基地址

DMA_MemoryBaseAddr

该参数用以定义 DMA 内存基地址

DMA_DIR

/** @defgroup DMA_data_transfer_direction 
  * @{
  */

#define DMA_DIR_PeripheralDST              ((uint32_t)0x00000010)
#define DMA_DIR_PeripheralSRC              ((uint32_t)0x00000000)

DMA_PeripheralInc

/** @defgroup DMA_peripheral_incremented_mode 
  * @{
  */

#define DMA_PeripheralInc_Enable           ((uint32_t)0x00000040)
#define DMA_PeripheralInc_Disable          ((uint32_t)0x00000000)

DMA_MemoryInc

/** @defgroup DMA_memory_incremented_mode 
  * @{
  */

#define DMA_MemoryInc_Enable               ((uint32_t)0x00000080)
#define DMA_MemoryInc_Disable              ((uint32_t)0x00000000)

DMA_PeripheralDataSize

/** @defgroup DMA_peripheral_data_size 
  * @{
  */

#define DMA_PeripheralDataSize_Byte        ((uint32_t)0x00000000)
#define DMA_PeripheralDataSize_HalfWord    ((uint32_t)0x00000100)
#define DMA_PeripheralDataSize_Word        ((uint32_t)0x00000200)

DMA_MemoryDataSize

/** @defgroup DMA_memory_data_size 
  * @{
  */

#define DMA_MemoryDataSize_Byte            ((uint32_t)0x00000000)
#define DMA_MemoryDataSize_HalfWord        ((uint32_t)0x00000400)
#define DMA_MemoryDataSize_Word            ((uint32_t)0x00000800)

DMA_Mode

/** @defgroup DMA_circular_normal_mode 
  * @{
  */

#define DMA_Mode_Circular                  ((uint32_t)0x00000020)
#define DMA_Mode_Normal                    ((uint32_t)0x00000000)

DMA_Priority

/** @defgroup DMA_priority_level 
  * @{
  */

#define DMA_Priority_VeryHigh              ((uint32_t)0x00003000)
#define DMA_Priority_High                  ((uint32_t)0x00002000)
#define DMA_Priority_Medium                ((uint32_t)0x00001000)
#define DMA_Priority_Low                   ((uint32_t)0x00000000)

DMA_M2M

/** @defgroup DMA_memory_to_memory 
  * @{
  */

#define DMA_M2M_Enable                     ((uint32_t)0x00004000)
#define DMA_M2M_Disable                    ((uint32_t)0x00000000)

2.3 DMA_Cmd

/**
  * @brief  Enables or disables the specified DMAy Channelx.
  * @param  DMAy_Channelx: where y can be 1 or 2 to select the DMA and 
  *   x can be 1 to 7 for DMA1 and 1 to 5 for DMA2 to select the DMA Channel.
  * @param  NewState: new state of the DMAy Channelx. 
  *   This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void DMA_Cmd(DMA_Channel_TypeDef* DMAy_Channelx, FunctionalState NewState)
功能:
	使能或者失能指定的通道 x
参数:
   DMA Channelx:x 可以是 12…,或者 7 来选择 DMA 通道 x
   NewState:DMA 通道 x 的新状态 这个参数可以取:ENABLE 或者 DISABLE  
返回值:

2.4 DMA_SetCurrDataCounter

/**
  * @brief  Sets the number of data units in the current DMAy Channelx transfer.
  * @param  DMAy_Channelx: where y can be 1 or 2 to select the DMA and 
  *         x can be 1 to 7 for DMA1 and 1 to 5 for DMA2 to select the DMA Channel.
  * @param  DataNumber: The number of data units in the current DMAy Channelx
  *         transfer.   
  * @note   This function can only be used when the DMAy_Channelx is disabled.                 
  * @retval None.
  */
void DMA_SetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx, uint16_t DataNumber)
功能:
	设置DMA转换数据个数
参数:
   DMA Channelx:x 可以是 12…,或者 7 来选择 DMA 通道 x
   DataNumber:数据个数
返回值:

2.5 DMA_GetFlagStatus

/**
  * @brief  Checks whether the specified DMAy Channelx flag is set or not.
  * @param  DMAy_FLAG: specifies the flag to check.
  *   This parameter can be one of the following values:
  *     @arg DMA1_FLAG_GL1: DMA1 Channel1 global flag.
  *     @arg DMA1_FLAG_TC1: DMA1 Channel1 transfer complete flag.
  *     @arg DMA1_FLAG_HT1: DMA1 Channel1 half transfer flag.
  *     @arg DMA1_FLAG_TE1: DMA1 Channel1 transfer error flag.
  *     @arg DMA1_FLAG_GL2: DMA1 Channel2 global flag.
  *     @arg DMA1_FLAG_TC2: DMA1 Channel2 transfer complete flag.
  *     @arg DMA1_FLAG_HT2: DMA1 Channel2 half transfer flag.
  *     @arg DMA1_FLAG_TE2: DMA1 Channel2 transfer error flag.
  *     @arg DMA1_FLAG_GL3: DMA1 Channel3 global flag.
  *     @arg DMA1_FLAG_TC3: DMA1 Channel3 transfer complete flag.
  *     @arg DMA1_FLAG_HT3: DMA1 Channel3 half transfer flag.
  *     @arg DMA1_FLAG_TE3: DMA1 Channel3 transfer error flag.
  *     @arg DMA1_FLAG_GL4: DMA1 Channel4 global flag.
  *     @arg DMA1_FLAG_TC4: DMA1 Channel4 transfer complete flag.
  *     @arg DMA1_FLAG_HT4: DMA1 Channel4 half transfer flag.
  *     @arg DMA1_FLAG_TE4: DMA1 Channel4 transfer error flag.
  *     @arg DMA1_FLAG_GL5: DMA1 Channel5 global flag.
  *     @arg DMA1_FLAG_TC5: DMA1 Channel5 transfer complete flag.
  *     @arg DMA1_FLAG_HT5: DMA1 Channel5 half transfer flag.
  *     @arg DMA1_FLAG_TE5: DMA1 Channel5 transfer error flag.
  *     @arg DMA1_FLAG_GL6: DMA1 Channel6 global flag.
  *     @arg DMA1_FLAG_TC6: DMA1 Channel6 transfer complete flag.
  *     @arg DMA1_FLAG_HT6: DMA1 Channel6 half transfer flag.
  *     @arg DMA1_FLAG_TE6: DMA1 Channel6 transfer error flag.
  *     @arg DMA1_FLAG_GL7: DMA1 Channel7 global flag.
  *     @arg DMA1_FLAG_TC7: DMA1 Channel7 transfer complete flag.
  *     @arg DMA1_FLAG_HT7: DMA1 Channel7 half transfer flag.
  *     @arg DMA1_FLAG_TE7: DMA1 Channel7 transfer error flag.
  *     @arg DMA2_FLAG_GL1: DMA2 Channel1 global flag.
  *     @arg DMA2_FLAG_TC1: DMA2 Channel1 transfer complete flag.
  *     @arg DMA2_FLAG_HT1: DMA2 Channel1 half transfer flag.
  *     @arg DMA2_FLAG_TE1: DMA2 Channel1 transfer error flag.
  *     @arg DMA2_FLAG_GL2: DMA2 Channel2 global flag.
  *     @arg DMA2_FLAG_TC2: DMA2 Channel2 transfer complete flag.
  *     @arg DMA2_FLAG_HT2: DMA2 Channel2 half transfer flag.
  *     @arg DMA2_FLAG_TE2: DMA2 Channel2 transfer error flag.
  *     @arg DMA2_FLAG_GL3: DMA2 Channel3 global flag.
  *     @arg DMA2_FLAG_TC3: DMA2 Channel3 transfer complete flag.
  *     @arg DMA2_FLAG_HT3: DMA2 Channel3 half transfer flag.
  *     @arg DMA2_FLAG_TE3: DMA2 Channel3 transfer error flag.
  *     @arg DMA2_FLAG_GL4: DMA2 Channel4 global flag.
  *     @arg DMA2_FLAG_TC4: DMA2 Channel4 transfer complete flag.
  *     @arg DMA2_FLAG_HT4: DMA2 Channel4 half transfer flag.
  *     @arg DMA2_FLAG_TE4: DMA2 Channel4 transfer error flag.
  *     @arg DMA2_FLAG_GL5: DMA2 Channel5 global flag.
  *     @arg DMA2_FLAG_TC5: DMA2 Channel5 transfer complete flag.
  *     @arg DMA2_FLAG_HT5: DMA2 Channel5 half transfer flag.
  *     @arg DMA2_FLAG_TE5: DMA2 Channel5 transfer error flag.
  * @retval The new state of DMAy_FLAG (SET or RESET).
  */
FlagStatus DMA_GetFlagStatus(uint32_t DMAy_FLAG)
功能:
	检查指定的 DMA 通道 x 标志位设置与否
参数:
   DMA_FLAG:待检查的 DMA 标志位
返回值:
	DMA_FLAG 的新状态(SET 或者 RESET)     

2.6 DMA_ClearFlag

/**
  * @brief  Clears the DMAy Channelx's pending flags.
  * @param  DMAy_FLAG: specifies the flag to clear.
  *   This parameter can be any combination (for the same DMA) of the following values:
  *     @arg DMA1_FLAG_GL1: DMA1 Channel1 global flag.
  *     @arg DMA1_FLAG_TC1: DMA1 Channel1 transfer complete flag.
  *     @arg DMA1_FLAG_HT1: DMA1 Channel1 half transfer flag.
  *     @arg DMA1_FLAG_TE1: DMA1 Channel1 transfer error flag.
  *     @arg DMA1_FLAG_GL2: DMA1 Channel2 global flag.
  *     @arg DMA1_FLAG_TC2: DMA1 Channel2 transfer complete flag.
  *     @arg DMA1_FLAG_HT2: DMA1 Channel2 half transfer flag.
  *     @arg DMA1_FLAG_TE2: DMA1 Channel2 transfer error flag.
  *     @arg DMA1_FLAG_GL3: DMA1 Channel3 global flag.
  *     @arg DMA1_FLAG_TC3: DMA1 Channel3 transfer complete flag.
  *     @arg DMA1_FLAG_HT3: DMA1 Channel3 half transfer flag.
  *     @arg DMA1_FLAG_TE3: DMA1 Channel3 transfer error flag.
  *     @arg DMA1_FLAG_GL4: DMA1 Channel4 global flag.
  *     @arg DMA1_FLAG_TC4: DMA1 Channel4 transfer complete flag.
  *     @arg DMA1_FLAG_HT4: DMA1 Channel4 half transfer flag.
  *     @arg DMA1_FLAG_TE4: DMA1 Channel4 transfer error flag.
  *     @arg DMA1_FLAG_GL5: DMA1 Channel5 global flag.
  *     @arg DMA1_FLAG_TC5: DMA1 Channel5 transfer complete flag.
  *     @arg DMA1_FLAG_HT5: DMA1 Channel5 half transfer flag.
  *     @arg DMA1_FLAG_TE5: DMA1 Channel5 transfer error flag.
  *     @arg DMA1_FLAG_GL6: DMA1 Channel6 global flag.
  *     @arg DMA1_FLAG_TC6: DMA1 Channel6 transfer complete flag.
  *     @arg DMA1_FLAG_HT6: DMA1 Channel6 half transfer flag.
  *     @arg DMA1_FLAG_TE6: DMA1 Channel6 transfer error flag.
  *     @arg DMA1_FLAG_GL7: DMA1 Channel7 global flag.
  *     @arg DMA1_FLAG_TC7: DMA1 Channel7 transfer complete flag.
  *     @arg DMA1_FLAG_HT7: DMA1 Channel7 half transfer flag.
  *     @arg DMA1_FLAG_TE7: DMA1 Channel7 transfer error flag.
  *     @arg DMA2_FLAG_GL1: DMA2 Channel1 global flag.
  *     @arg DMA2_FLAG_TC1: DMA2 Channel1 transfer complete flag.
  *     @arg DMA2_FLAG_HT1: DMA2 Channel1 half transfer flag.
  *     @arg DMA2_FLAG_TE1: DMA2 Channel1 transfer error flag.
  *     @arg DMA2_FLAG_GL2: DMA2 Channel2 global flag.
  *     @arg DMA2_FLAG_TC2: DMA2 Channel2 transfer complete flag.
  *     @arg DMA2_FLAG_HT2: DMA2 Channel2 half transfer flag.
  *     @arg DMA2_FLAG_TE2: DMA2 Channel2 transfer error flag.
  *     @arg DMA2_FLAG_GL3: DMA2 Channel3 global flag.
  *     @arg DMA2_FLAG_TC3: DMA2 Channel3 transfer complete flag.
  *     @arg DMA2_FLAG_HT3: DMA2 Channel3 half transfer flag.
  *     @arg DMA2_FLAG_TE3: DMA2 Channel3 transfer error flag.
  *     @arg DMA2_FLAG_GL4: DMA2 Channel4 global flag.
  *     @arg DMA2_FLAG_TC4: DMA2 Channel4 transfer complete flag.
  *     @arg DMA2_FLAG_HT4: DMA2 Channel4 half transfer flag.
  *     @arg DMA2_FLAG_TE4: DMA2 Channel4 transfer error flag.
  *     @arg DMA2_FLAG_GL5: DMA2 Channel5 global flag.
  *     @arg DMA2_FLAG_TC5: DMA2 Channel5 transfer complete flag.
  *     @arg DMA2_FLAG_HT5: DMA2 Channel5 half transfer flag.
  *     @arg DMA2_FLAG_TE5: DMA2 Channel5 transfer error flag.
  * @retval None
  */
void DMA_ClearFlag(uint32_t DMAy_FLAG)
功能:
	清除 DMA 通道 x 待处理标志位
参数:
    DMA_FLAG:待清除的 DMA 标志位,使用操作符“|”可以同时选中多个DMA 标志位
返回值:

03. DMA数据单通道接线图

在这里插入图片描述

04. DMA数据单通道示例

dma.h

#ifndef __DMA_H__

#define __DMA_H__


#include "stm32f10x.h"                  // Device header


void dma_init(uint32_t src, uint32_t dest, uint32_t size);


void dma_trasfer(uint32_t size);



#endif

dma.c


#include "dma.h"


void dma_init(uint32_t src, uint32_t dest, uint32_t size)
{
	 DMA_InitTypeDef DMA_InitStruct;
	
	//开启时钟
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
	

	DMA_InitStruct.DMA_MemoryBaseAddr = dest;
	DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
	DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
	DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;
	DMA_InitStruct.DMA_PeripheralBaseAddr = src;
	DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
	DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Enable;
	DMA_InitStruct.DMA_Priority = DMA_Priority_Low;
	DMA_InitStruct.DMA_BufferSize = size;
	DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;
	DMA_InitStruct.DMA_M2M = DMA_M2M_Enable;
	
	DMA_Init(DMA1_Channel1, &DMA_InitStruct);
	
	DMA_Cmd(DMA1_Channel1, DISABLE);
	
}


void dma_trasfer(uint32_t size)
{
	DMA_Cmd(DMA1_Channel1, DISABLE);
	DMA_SetCurrDataCounter(DMA1_Channel1, size);
	DMA_Cmd(DMA1_Channel1, ENABLE);
	
	while(DMA_GetFlagStatus(DMA1_FLAG_TC1) == RESET);
	DMA_ClearFlag(DMA1_FLAG_TC1);
}

测试程序1 main.c

#include "stm32f10x.h"

#include "delay.h"
#include "oled.h"
#include "dma.h"


const uint8_t src[] = {0x1, 0x2, 0x3, 0x4};

uint8_t dest[] = {0, 0, 0, 0};

 int main(void)
 {		 
	 //初始化
	 OLED_Init();
	 
	dma_init((uint32_t)src, (uint32_t)dest, 4);
	 
	OLED_ShowHexNum(1, 1, src[0], 2);
	OLED_ShowHexNum(1, 4, src[1], 2);
	OLED_ShowHexNum(1, 7, src[2], 2);
	OLED_ShowHexNum(1, 10, src[3], 2);
	 
	OLED_ShowHexNum(2, 1, dest[0], 2);
	OLED_ShowHexNum(2, 4, dest[1], 2);
	OLED_ShowHexNum(2, 7, dest[2], 2);
	OLED_ShowHexNum(2, 10, dest[3], 2); 
	 
	dma_trasfer(4);
	
	OLED_ShowHexNum(3, 1, src[0], 2);
	OLED_ShowHexNum(3, 4, src[1], 2);
	OLED_ShowHexNum(3, 7, src[2], 2);
	OLED_ShowHexNum(3, 10, src[3], 2);
	 
	OLED_ShowHexNum(4, 1, dest[0], 2);
	OLED_ShowHexNum(4, 4, dest[1], 2);
	OLED_ShowHexNum(4, 7, dest[2], 2);
	OLED_ShowHexNum(4, 10, dest[3], 2); 	 
	 
	 while(1)
	 {
		 
	 }
	 
	 return 0;
 }

测试程序2 main.c

#include "stm32f10x.h"

#include "delay.h"
#include "oled.h"
#include "dma.h"


uint8_t src[] = {0x1, 0x2, 0x3, 0x4};

uint8_t dest[] = {0, 0, 0, 0};

 int main(void)
 {		 
	 //初始化
	 OLED_Init();
	 
	dma_init((uint32_t)src, (uint32_t)dest, 4);
	 
	 
	OLED_ShowString(1, 1, "DataA");

	OLED_ShowString(3, 1, "DataB");
	OLED_ShowHexNum(1, 8, (uint32_t)src, 8);
	OLED_ShowHexNum(3, 8, (uint32_t)dest, 8);
	 
	 
	while(1)
	{
		src[0] ++;
		src[1] ++;
		src[2] ++;
		src[3] ++;
		
		OLED_ShowHexNum(2, 1, src[0], 2);		 
		OLED_ShowHexNum(2, 4, src[1], 2);
		OLED_ShowHexNum(2, 7, src[2], 2);
		OLED_ShowHexNum(2, 10, src[3], 2);

		OLED_ShowHexNum(4, 1, dest[0], 2);
		OLED_ShowHexNum(4, 4, dest[1], 2);
		OLED_ShowHexNum(4, 7, dest[2], 2);
		OLED_ShowHexNum(4, 10, dest[3], 2); 
			 
		delay_ms(1000);
		
		dma_trasfer(4);
		OLED_ShowHexNum(2, 1, src[0], 2);		 
		OLED_ShowHexNum(2, 4, src[1], 2);
		OLED_ShowHexNum(2, 7, src[2], 2);
		OLED_ShowHexNum(2, 10, src[3], 2);

		OLED_ShowHexNum(4, 1, dest[0], 2);
		OLED_ShowHexNum(4, 4, dest[1], 2);
		OLED_ShowHexNum(4, 7, dest[2], 2);
		OLED_ShowHexNum(4, 10, dest[3], 2); 

		delay_ms(1000);
		 
	 }
	 
	 return 0;
 }

 

05. DMA数据多通道接线图

在这里插入图片描述

06. DMA数据多通道示例一

单次转换 扫描模式

adc.h

#ifndef __ADC_H__
#define __ADC_H__

#include "stm32f10x.h"                  // Device header


extern uint16_t adc_value[4];

void adc_init(void);

void adc_getvalue(void);


#endif /*__ADC_H__*/

adc.c

#include "adc.h"

uint16_t adc_value[4] = {0};

void adc_init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	ADC_InitTypeDef ADC_InitStruct;
	DMA_InitTypeDef DMA_InitStruct;
	
	
	//开启ADC时钟  PA0 --> ADC1_0
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
	
	//开启GPIOA的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	//开启时钟
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
	
	//设置为6分频  72M / 6 = 12M 
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);
	
	
	//GPIO配置 
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
	GPIO_InitStructure.GPIO_Speed =   GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	// 4个ADC通道
	ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);
	ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_55Cycles5);
	ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_55Cycles5);
	ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 4, ADC_SampleTime_55Cycles5);
		
		
	//ADC配置
	ADC_InitStruct.ADC_ContinuousConvMode = DISABLE; //单次转换
	ADC_InitStruct.ADC_ScanConvMode = ENABLE; //扫描模式
	ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;
	ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
	ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;
	ADC_InitStruct.ADC_NbrOfChannel = 4; //4个通道
	ADC_Init(ADC1, &ADC_InitStruct);
	
	
	DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)adc_value;
	DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
	DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
	DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;
	DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
	DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
	DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
	DMA_InitStruct.DMA_Priority = DMA_Priority_Low;
	DMA_InitStruct.DMA_BufferSize = 4;
	DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;
	DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;
	
	DMA_Init(DMA1_Channel1, &DMA_InitStruct);
	
	DMA_Cmd(DMA1_Channel1, DISABLE);

	ADC_DMACmd(ADC1, ENABLE);
	
	//使能ADC
	ADC_Cmd(ADC1, ENABLE);
	
	//校准ADC
	ADC_ResetCalibration(ADC1);
	while(ADC_GetResetCalibrationStatus(ADC1));
	
	ADC_StartCalibration(ADC1);
	while(ADC_GetCalibrationStatus(ADC1));
	
}

void adc_getvalue(void)
{
	DMA_Cmd(DMA1_Channel1, DISABLE);
	DMA_SetCurrDataCounter(DMA1_Channel1, 4);
	DMA_Cmd(DMA1_Channel1, ENABLE);
	
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);
	
	while(DMA_GetFlagStatus(DMA1_FLAG_TC1) == RESET);
	DMA_ClearFlag(DMA1_FLAG_TC1);
}

main.c

#include "stm32f10x.h"

#include "delay.h"
#include "oled.h"
#include "adc.h"


 int main(void)
 {	
	 //初始化
	 OLED_Init();
	 adc_init();

	 //显示字符串
	 OLED_ShowString(1, 1, "AD0: ");
	 OLED_ShowString(2, 1, "AD1: ");
	 OLED_ShowString(3, 1, "AD2: ");
     OLED_ShowString(4, 1, "AD3: ");
	 
	 while(1)
	 {
		adc_getvalue();
		 
		OLED_ShowNum(1, 5, adc_value[0], 4);
		OLED_ShowNum(2, 5, adc_value[1], 4);
		OLED_ShowNum(3, 5, adc_value[2], 4);
		OLED_ShowNum(4, 5, adc_value[3], 4);		 	 
		 delay_ms(100);
	 }
	 
 }

07. DMA数据多通道示例二

连续扫描,循环转换

adc.h

#ifndef __ADC_H__
#define __ADC_H__

#include "stm32f10x.h"                  // Device header


extern uint16_t adc_value[4];

void adc_init(void);



#endif /*__ADC_H__*/

adc.c

#include "adc.h"

uint16_t adc_value[4] = {0};

void adc_init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	ADC_InitTypeDef ADC_InitStruct;
	DMA_InitTypeDef DMA_InitStruct;
	
	
	//开启ADC时钟  PA0 --> ADC1_0
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
	
	//开启GPIOA的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	
	//开启时钟
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
	
	//设置为6分频  72M / 6 = 12M 
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);
	
	
	//GPIO配置 
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
	GPIO_InitStructure.GPIO_Speed =   GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	// 4个ADC通道
	ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);
	ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_55Cycles5);
	ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_55Cycles5);
	ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 4, ADC_SampleTime_55Cycles5);
		
		
	//ADC配置
	ADC_InitStruct.ADC_ContinuousConvMode = ENABLE; //连续模式
	ADC_InitStruct.ADC_ScanConvMode = ENABLE; //扫描模式
	ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;
	ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
	ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;
	ADC_InitStruct.ADC_NbrOfChannel = 4; //4个通道
	ADC_Init(ADC1, &ADC_InitStruct);
	
	
	DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)adc_value;
	DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
	DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
	DMA_InitStruct.DMA_Mode = DMA_Mode_Circular; //DMA循环模式
	DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
	DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
	DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
	DMA_InitStruct.DMA_Priority = DMA_Priority_Low;
	DMA_InitStruct.DMA_BufferSize = 4;
	DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;
	DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;
	
	DMA_Init(DMA1_Channel1, &DMA_InitStruct);
	
	DMA_Cmd(DMA1_Channel1, ENABLE);

	ADC_DMACmd(ADC1, ENABLE);
	
	//使能ADC
	ADC_Cmd(ADC1, ENABLE);
	
	//校准ADC
	ADC_ResetCalibration(ADC1);
	while(ADC_GetResetCalibrationStatus(ADC1));
	
	ADC_StartCalibration(ADC1);
	while(ADC_GetCalibrationStatus(ADC1));
	
	//ADC触发
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);
	
}

main.c

#include "stm32f10x.h"

#include "delay.h"
#include "oled.h"
#include "adc.h"


 int main(void)
 {	
	 
	 //初始化
	 OLED_Init();
	 adc_init();

	 //显示字符串
	 OLED_ShowString(1, 1, "AD0: ");
	 OLED_ShowString(2, 1, "AD1: ");
	 OLED_ShowString(3, 1, "AD2: ");
     OLED_ShowString(4, 1, "AD3: ");
	 
	 while(1)
	 {	 
		OLED_ShowNum(1, 5, adc_value[0], 4);
		OLED_ShowNum(2, 5, adc_value[1], 4);
		OLED_ShowNum(3, 5, adc_value[2], 4);
		OLED_ShowNum(4, 5, adc_value[3], 4);		 
		 
		 
		 delay_ms(100);
	 }
	 
 }

08. 程序下载

19-DMA单通道.rar

20-DMA-ADC多通道1.rar

21-DMA-ADC多通道2.rar

09. 附录

参考: 【STM32】江科大STM32学习笔记汇总

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1365779.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

STM32(HAL库) CubeMX+Keil5 建立工程

STM32&#xff08;HAL库&#xff09; CubeMXKeil5 建立工程 目标选择 菜单栏 File 新建工程打开工程退出软件 Window 输出窗口的开启软件字体设置 Help 软件帮助文档检查软件更新管理MCU 已存在工程&#xff08;Existing Projects&#xff09; 最近打开过的工程(Recent Open…

如何科学评价视频生成模型?AIGCBench:全面可扩展的视频生成任务基准来了!

AIGC领域正迅速发展&#xff0c;特别是在视频生成方面取得了显著进展。本文介绍了AIGCBench&#xff0c;这是一个首创的全面而可扩展的基准&#xff0c;旨在评估各种视频生成任务&#xff0c;主要关注图像到视频&#xff08;I2V&#xff09;生成。AIGCBench解决了现有基准的局限…

苹果显示连接iTunes是什么意思?你知道吗?答案来了!

相信使用苹果手机的小伙伴都听说过iTunes软件&#xff0c;但是可能还有小部分人不知道iTunes是什么&#xff0c;以及苹果设备上显示连接itunes是什么意思。对于使用iTunes进行数据备份、恢复等操作的用户来说&#xff0c;出现这个提示意味着您的苹果设备已经与电脑成功连接&…

vue-springboot基于java的实验室安全考试系统

本系统为用户而设计制作实验室安全考试系统&#xff0c;旨在实现实验室安全考试智能化、现代化管理。本实验室安全考试管理自动化系统的开发和研制的最终目的是将实验室安全考试的运作模式从手工记录数据转变为网络信息查询管理&#xff0c;从而为现代管理人员的使用提供更多的…

【Docker基础一】Docker安装Elasticsearch,Kibana,IK分词器

安装elasticsearch 下载镜像 查看版本&#xff1a;Elasticsearch Guide [8.11] | Elastic # 下载镜像 docker pull elasticsearch:7.17.16 # 查看镜像是否下载成功 docker images创建网络 因为需要部署kibana容器&#xff0c;要让es和kibana容器互联 # 创建一个网络&…

并发(10)

目录 61.ReentrantReadWriteLock底层读写状态如何设计的&#xff1f; 62.读锁和写锁的最大数量是多少&#xff1f; 63.本地线程计数器ThreadLocalHoldCounter是用来做什么的&#xff1f; 64.写锁的获取与释放是怎么实现的&#xff1f; 65.读锁的获取与释放是怎么实现的&…

【算法】递归算法理解(持续更新)

这里写目录标题 一、递归算法1、什么情况下可以使用递归&#xff1f;2、递归算法组成部分3、案例&#xff1a;求n的阶乘4、编写一个递归函数来计算列表包含的元素数。5、通过递归找到列表中最大的数字。6、通过递归的方式实现二分查找算法。 一、递归算法 递归&#xff08;Rec…

浅谈LCD屏幕引脚定义识别

学习单片机&#xff0c;总要驱动LCD屏幕&#xff0c;但是对于没有引脚定义的LCD屏幕该如何应对&#xff1f; 本人研究不深&#xff0c;只谈体会。 比如下面这款屏幕 一、第一种方法 百度大法查引脚定义。查询条件可以是FPC上的丝印&#xff0c;或者是屏幕的尺寸&#xff0c;引脚…

sublime如何取消运行代码状态

sublime如何取消运行代码状态 解决方案待续、更新中 解决方案 1 顶部取消: 工具-----取消编译 这个看自己编译器sublime取消编译是否可用,可用则用 ,否则使用下面方法 2 底部栏取消–如图所示: 取消成功: 待续、更新中 ————————————————————— 以上就…

2024前端炫酷源码分享(附效果图及在线演示)

分享10款非常有趣的前端特效源码 其中包含css动画特效、js原生特效、svg特效以及小游戏等 下面我会给出特效样式图或演示效果图 但你也可以点击在线预览查看源码的最终展示效果及下载源码资源 GSAP-火箭动画特效 GSAP 火箭动画 当氮气充足的情况下 火箭会冲出 并继续飞行 图片…

【Java】设计模式之顺序控制

实际开发中&#xff0c;有时候一些场景需求让多个线程按照固定的顺序依次执行。这个时候就会使用这种模式。 这种模式说白了&#xff0c;就是给线程设定不同的条件&#xff0c;不符合条件的话&#xff0c;就算线程拿到锁也会释放锁进入等待&#xff1b;符合条件才让线程拿到锁…

【解决方案】电能质量在线监测装置和防孤岛保护装置在特斯拉工厂分布式光伏项目的应用

摘要&#xff1a; 随着全球对可再生能源的关注度不断提高&#xff0c;分布式光伏发电系统在近年来得到了广泛应用。分布式光伏发电系统具有环保、灵活等优势&#xff0c;能够有效地缓解能源短缺和环境污染问题。同时&#xff0c;电能质量在线监测装置和防孤岛保护装置在分布式…

leetcode:412. Fizz Buzz(python3解法)

难度&#xff1a;简单 给你一个整数 n &#xff0c;找出从 1 到 n 各个整数的 Fizz Buzz 表示&#xff0c;并用字符串数组 answer&#xff08;下标从 1 开始&#xff09;返回结果&#xff0c;其中&#xff1a; answer[i] "FizzBuzz" 如果 i 同时是 3 和 5 的倍数。a…

开心自走棋:使用 Laf 云开发支撑数百万玩家

先介绍一下开心自走棋 开心自走棋是一款剑与魔法的烧脑自走棋游戏。以著名的魔幻世界观为蓝本&#xff0c;采用了轻松可爱的画面风格&#xff0c;精致细腻的动画和特效来还原魔兽之战。 现在市面上自走棋游戏多是 PvP 玩法为主&#xff0c;而开心自走棋是以 PvE 玩法为主的&a…

刷了四百道算法题,我在项目里用过哪几道呢?

大家好&#xff0c;我是老三&#xff0c;今天和大家聊一个话题&#xff1a;项目中用到的力扣算法。 不知道从什么时候起&#xff0c;算法已经成为了互联网面试的标配&#xff0c;在十年前&#xff0c;哪怕如日中天的百度&#xff0c;面试也最多考个冒泡排序。后来&#xff0c;…

VTK将二维图像向三维空间中无参数化的曲面表面进行纹理映射(含代码)

实现纹理映射主要是建立纹理空间与模型空间、模型空间与屏幕空间之间的映射关系(见图 6-28)&#xff1a; 其中纹理空间可以定义为u-v 空间&#xff0c;每个轴标范围为 (0.1)。其中对于一个纹理图像&#xff0c;其左下角 v 标为 0.0)&#xff0c;右上角标为 1.1)。而对于简单的参…

假设与灵敏度分析

灵敏度分析 关系究竟有多敏感&#xff0c;就要进行灵敏度分析 如果你改变了系统参数后&#xff0c;引起这个模型&#xff08;公式&#xff09;输出的变化的程度不大&#xff0c;则说明你的模型稳定性较强&#xff08;即灵敏性较差&#xff09;&#xff0c;反之则反&#xff01…

【Python期末】动态爬取电影Top250数据可视化处理(有GUI界面/无数据库)

诚接计算机专业编程作业(C语言、C、Python、Java、HTML、JavaScript、Vue等)&#xff0c;10/15R左右&#xff0c;如有需要请私信我&#xff0c;或者加我的企鹅号&#xff1a;1404293476 本文资源&#xff1a;https://download.csdn.net/download/weixin_47040861/88713693 目录…

简析云能耗管理系统在某高校建筑系统平台的设计与应用

叶根胜 安科瑞电气股份有限公司 上海嘉定 201801 摘要&#xff1a;根据本项目&#xff0c;依托某学院电能计量管理系统、供水计量监督系统、供热计量管理系统等基础平台&#xff0c;制定了高校建筑能耗综合管理系统平台应用的总体框架和方案。该系统可以实时监控、统计能耗和…

https配置证书

HTTPS 基本原理 https 介绍 HTTPS&#xff08;全称&#xff1a;HyperText Transfer Protocol over Secure Socket Layer&#xff09;&#xff0c;其实 HTTPS 并不是一个新鲜协议&#xff0c;Google 很早就开始启用了&#xff0c;初衷是为了保证数据安全。 国内外的大型互联网…