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

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.mfbz.cn/a/299000.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

计算机网络(2)

计算机网络&#xff08;2&#xff09; 小程一言专栏链接: [link](http://t.csdnimg.cn/ZUTXU) 计算机网络和因特网&#xff08;2&#xff09;分组交换网中的时延、丢包和吞吐量时延丢包吞吐量总结 协议层次及其服务模型模型类型OSI模型分析TCP/IP模型分析 追溯历史 小程一言 我…

数据结构——堆排序

什么是堆排序 堆排序就是利用堆&#xff08;假设利用大堆&#xff09;进行排序的算法。他的基本思想是&#xff0c;将待排序的序列构造成一个大顶堆。此时&#xff0c;整个序列的最大值就是堆顶的根节点。将他移走&#xff08;其实就是将其与堆数组的末尾元素交换&#xff0c;…

简单 Web Server 程序的设计与实现 (2024)

1.题目描述 Web 服务是 Internet 最方便与受用户欢迎的服务类型&#xff0c;它的影响力也远远超出了专业技术范畴&#xff0c; 已广泛应用于电子商务、远程教育、远程医疗与信息服务等领域&#xff0c;并且有继续扩大的趋势。目前很多 的 Internet 应用都是基于 Web 技术的&…

Java快速排序希尔排序归并排序

快速排序算法 快速排序的原理&#xff1a;选择一个关键值作为基准值。比基准值小的都在左边序列&#xff08;一般是无序的&#xff09;&#xff0c;比基准值大的都在右边&#xff08;一般是无序的&#xff09;。一般选择序列的第一个元素。 一次循环&#xff1a;从后往前比较&…

VMware中删除虚拟机

虚拟机使用完成后&#xff0c;需要删除虚拟机如何操作呢&#xff1f; 1.首先进入VMware 2.选择需要删除的虚拟机&#xff0c;点击右键 3.直接选择“移除”&#xff1f; 当然不是&#xff0c;这只是从这么目录显示中去掉了&#xff0c;并非 “真正” 删除该虚拟机 注意&#x…

使用sentinel作为熔断器

什么是sentinel Sentinel&#xff0c;中文翻译为哨兵&#xff0c;是为微服务提供流量控制、熔断降级的功能&#xff0c;它和Hystrix提供的功能一样&#xff0c;可以有效的解决微服务调用产生的“雪崩”效应&#xff0c;为微服务系统提供了稳定性的解决方案。随着Hytrxi进入了维…

labelme的json转mask,实测有效

1、创建一个conda的虚拟环境 conda creat -n labelme python3.82、转到你的标注文件夹&#xff08;包括json和图片&#xff09; cd C:/Users/Administrator/Desktop/json3、你需要在标注文件夹下用txt写下以下代码&#xff0c;并保存bat文件。 放在最后一个就可以了 echo of…

Python的核心知识点整理大全66(已完结撒花)

目录 D.3 忽略文件 .gitignore 注意 D.4 初始化仓库 D.5 检查状态 D.6 将文件加入到仓库中 D.7 执行提交 D.8 查看提交历史 D.9 第二次提交 hello_world.py D.10 撤销修改 hello_world.py 注意 D.11 检出以前的提交 往期快速传送门&#x1f446;&#xff08;在文…

微服务实战系列之Filter

前言 Filter&#xff0c;又名过滤器&#xff0c;当然不是我们日常中见到的&#xff0c;诸如此类构件&#xff1a; 而应该是微服务中常使用的&#xff0c;诸如此类&#xff08;图片来自官网&#xff0c;点击可查看原图&#xff09;&#xff1a; 一般用于字符编码转换&#xf…

MySQL--基础篇

这里写目录标题 总览MySQl各个阶段基础篇总览 MySQL概述数据库相关概念查看本机MySQL版本号启停mysql打开windows服务管理windows命令行启停 连接mysql客户端mysql运行逻辑数据模型关系型数据库 总结 SQL总览SQL通用语法SQL语句分类DDL数据库操作表操作查询表创建表结构数据类型…

【Web开发】会话管理与无 Cookie 环境下的实现策略

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a; Web开发 ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 正文 问题&#xff1a; 思路&#xff1a; 方法&#xff1a; 结语 我的其他博客 前言 在当今Web应用程序中&#xff0c;会话…

C语言-第十八周做题总结-数组3

id:454 A.字符串逆序 题目描述 输入一个字符串&#xff0c;对该字符串进行逆序&#xff0c;输出逆序后的字符串。 输入 输入在一行中给出一个不超过80个字符长度的、以回车结束的非空字符串。 输出 在一行中输出逆序后的字符串。 输入样例 输出样例 题解 先用一个while…

gRCP - 面向未来的第二代 RPC 技术,解析 HTTP2.0 和 Protobuf

目录 一、gRCP - 面向未来的第二代 RPC 技术 1.1、gRPC 简介 1.1.1、gRPC 是个啥&#xff1f; 1.1.2、gRPC 核心设计思路 1.1.3、gRPC 和 ThriftRPC 区别 1.1.4、为什么使用 gRPC&#xff1f;&#xff08;好处&#xff09; 1.2、HTTP2.0 协议 1.2.1、回顾 HTTP1.0 和 H…

C# Entity Framework 中不同的数据的加载方式

延迟加载 延迟加载是指在访问导航属性时&#xff0c;Entity Framework 会自动查询数据库并加载相关数据。这种方式在我们需要访问导航属性时比较方便&#xff0c;因为我们无需手动加载相关数据&#xff0c;而且只会在需要时才会进行查询&#xff0c;从而减少了不必要的开销。但…

基于商品列表的拖拽排序后端实现

目录 一&#xff1a;实现思路 二&#xff1a;实现步骤 二&#xff1a;实现代码 三&#xff1a;注意点 一&#xff1a;实现思路 后台实现拖拽排序通常需要与前端进行配合&#xff0c;对商品的列表拖拽排序&#xff0c;前端需要告诉后端拖拽的元素和拖动的位置。 这里我们假…

【远程计算机,这可能是由于 Credssp 加客数据库修正】解决方案

1、winR打开运行窗口 输入gpedit.msc命令&#xff0c;若找不到&#xff0c;可以进行如下文件编辑格式为cmd echo offpushd "%~dp0"dir /b C:\Windows\servicing\Packages\Microsoft-Windows-GroupPolicy-ClientExtensions-Package~3*.mum >List.txtdir /b C:\Win…

Linux stm32串口下载程序

一、工具 使用stm32flash进行串口下载 二、stm32flash安装 sudo apt-get install stm32flash 三、查看串口设备名称 先拔掉串口运行下面指令&#xff0c;获得所有设备名称,插上串口再运行一次&#xff0c;新增的就是串口设备名称&#xff0c;记住串口设备名称&#xff0c;以…

Linux目录结构及路径描述方式

1.Linux目录结构 Linux与Windows不同&#xff0c;Linux没有盘符这个概念, 只有一个根目录 /, 所有文件都在它下面 2.Linux路径的描述方式 在Linux系统中&#xff0c;路径之间的层级关系&#xff0c;使用&#xff1a;/ 来表示 在Windows系统中&#xff0c;路径之间的层级关系…

echarts图表会残留上一条数据的折线 setOption参数的第二个坑

记一下小坑 因为我的echarts图表的 series 是循环渲染上去的 所以他可能会有一条 或多条 我展示完多条的图表后 关闭 打开单条数据的图表 发现 他会残留上一个图表的数据 显示多条 之前我还以为是后端返回错了 但是log打印和查看请求数据 确实发现是我这边的问题 原因&#…

第二百四十三回 再分享一个Json工具

文章目录 1. 概念介绍2. 分析与比较2.1 分析问题2.2 比较差异 3. 使用方法4. 内容总结 我们在上一章回中介绍了"分享三个使用TextField的细节"相关的内容&#xff0c;本章回中将再 分享一个Json插件.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我…