【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 可以是 1,2…,或者 7 来选择 DMA 通道 xDMA_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_PeripheralDataSizeor 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-memorydata 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 可以是 1,2…,或者 7 来选择 DMA 通道 xNewState: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 可以是 1,2…,或者 7 来选择 DMA 通道 xDataNumber:数据个数
返回值:无
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 headervoid 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 headerextern 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_0RCC_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);//使能ADCADC_Cmd(ADC1, ENABLE);//校准ADCADC_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 headerextern 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_0RCC_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);//使能ADCADC_Cmd(ADC1, ENABLE);//校准ADCADC_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学习笔记汇总
相关文章:

【STM32】STM32学习笔记-DMA数据转运+AD多通道(24)
00. 目录 文章目录 00. 目录01. DMA简介02. DMA相关API2.1 DMA_Init2.2 DMA_InitTypeDef2.3 DMA_Cmd2.4 DMA_SetCurrDataCounter2.5 DMA_GetFlagStatus2.6 DMA_ClearFlag 03. DMA数据单通道接线图04. DMA数据单通道示例05. DMA数据多通道接线图06. DMA数据多通道示例一07. DMA数…...

即时设计:设计流程图,让您的设计稿更具条理和逻辑
流程图小助手 更多内容 在设计工作中,流程图是一种重要的工具,它可以帮助设计师清晰地展示设计思路和流程,提升设计的条理性和逻辑性。今天,我们要向您推荐一款强大的设计工具,它可以帮助您轻松为设计稿设计流程图&a…...
单个独立按键控制直流电机开关
/*----------------------------------------------- 内容:对应的电机接口需用杜邦线连接到uln2003电机控制端 使用5V-12V 小功率电机皆可 ------------------------------------------------*/ #include<reg52.h> //包含头文件,一般情况…...
前端插件库-VUE3 使用 JSEncrypt 插件
JSEncrypt 是一个用于在客户端进行加密的 JavaScript 库。它基于 RSA 加密算法,可以用于在浏览器中对数据进行加密和解密操作。 以下是使用 JSEncrypt 进行加密和解密的基本示例: 第一步:安装 JSEncrypt 首先,你需要引入 JSEn…...

Neo4j备份
这里主要讲Neo4j在windows环境下如何备份,Linux环境同理 Neo4j恢复看这里:Neo4j恢复-CSDN博客 Step1:停服 关闭neo4j.bat console会话窗口即可 Step2: 备份 找到数据目录,并备份、压缩 copy即可 data - 20240108.7z Step3: 启动服务 进入命令行&am…...

【LangChain学习之旅】—(5) 提示工程(上):用少样本FewShotTemplate和ExampleSelector创建应景文案
【LangChain学习之旅】—(5) 提示工程(上):用少样本FewShotTemplate和ExampleSelector创建应景文案 提示的结构LangChain 提示模板的类型使用 PromptTemplate使用 ChatPromptTemplateFewShot 的思想起源使用 FewShotPr…...
Python从入门到精通秘籍一
Python速成,知识点超详细,跟着这个系列边输入边学习体会吧! 一、字面量 下面是一些使用代码示例来说明Python的字面量的具体用法: 1.数字字面量: integer_literal = 42 # 整数字面量 float_literal = 3.14 # 浮点数字面量 complex_literal = 2 + 3j # 复数字面量# …...

【IC设计】移位寄存器
目录 理论讲解背景介绍什么是移位寄存器按工作模式分类verilog语法注意事项 设计实例循环移位寄存器算术双向移位寄存器5位线性反馈移位寄存器伪随机码发生器3位线性反馈移位寄存器32位线性反馈移位寄存器串行移位寄存器(打4拍)双向移位寄存器࿱…...

【Flutter 开发实战】Dart 基础篇:最基本的语法内容
在深入了解 Dart 这门编程语言之前,我们需要了解一些关于 Dart 的最基本的知识,像是常量、变量、函数等等,这样才能够让我们的开发效率更上一层楼。在本节,我们将探讨一些基础语法,包括入口方法 main、变量、常量以及命…...

中国光伏展
中国光伏展是中国最大的光伏产业展览会,每年在国内举办一次。该展览会汇集了国内外光伏行业的领先企业和专业人士,展示最新的光伏技术、产品和解决方案。 中国光伏展旨在促进光伏行业的发展和创新,提升光伏产业的国际竞争力。展览会涵盖了光伏…...

Nacos的统一配置管理
Nacos的统一配置管理 一 项目添加nacos和bootstrap依赖二 nacos客户端配置2.1 创建命名空间2.2 创建配置 三、配置bootstrap.yml四 不同环境配置切换步骤一:nacos中添加开发、测试配置步骤二:指定bootstrap.yml中spring.profiles.active参数值 扩展链接 …...

SpringBoot项目docker镜像生成
1. 本文思路 拉取基础镜像基于镜像创建容器在容器中,安装所需依赖部署脚本提交容器,生成新的镜像编写Dockerfile,添加启动命令,生成最终镜像导出镜像 2. 操作步骤 2.1 基础环境 # 拉取镜像 docker pull centos:7.6.1810 # 运行…...

JDBC初体验(二)——增、删、改、查
本课目标 理解SQL注入的概念 掌握 PreparedStatement 接口的使用 熟练使用JDBC完成数据库的增、删、改、查操作 SQL注入 注入原理:利用现有应用程序,将(恶意的)SQL命令注入到后台数据库引擎执行能力,它可以通过在…...
Eva.js是什么(互动小游戏开发)
前言 Eva.js 是一个专注于开发互动游戏项目的前端游戏引擎。 易用:Eva.js 提供开箱即用的游戏组件供开发人员立即使用。是的,它简单而优雅! 高性能:Eva.js 由高效的运行时和渲染管道 (Pixi.JS) 提供支持,这使得释放设…...
监听 beforeunload 事件,阻止页面刷新导致的信息丢失
尤其是一个有编辑器的页面,可以监听 windwo.beforeunload 事件,在用户试图关闭当前标签页的时候提醒用户,内容可能会丢失。 Window:beforeunload 事件 - Web API 接口参考 | MDN...

Java 常见缓存详解以及解决方案
一. 演示Mybatis 一级缓存 首先我们准备一个接口 两个实现的方法, 当我们调用这个queryAll()方法时我们需要调用selectAll()方法来查询数据 调用此接口实现效果 这个时候我们就可以发现了问题,我们调用方法…...

Golang 交叉编译之一文详解
博客原文 文章目录 Golang 中的交叉编译不同操作系统间的编译Linux 下编译windowsmacos windows 下编译Linuxmacos macos 下编译Linuxwindows 不同架构下的编译amd64x86 参考 Golang 中的交叉编译 在 Golang 中,交叉编译指的是在同一台机器上生成针对不同操作系统或…...

最新ThinkPHP版本实现证书查询系统,实现批量数据导入,自动生成电子证书
前提:朋友弄了一个培训机构,培训考试合格后,给发证书,需要一个证书查询系统。委托我给弄一个,花了几个晚上给写的证书查询系统。 实现功能: 前端按照姓名手机号码进行证书查询证书信息展示证书展示&#x…...
windows安装运行Apache James(基于spring的版本)
下载地址 下载列表 https://james.apache.org/download.cgi 直接下载基于spring版本 https://www.apache.org/dyn/closer.lua/james/server/3.8.0/james-server-app-3.8.0-app.zip 设置签名 解压,并切换到james-server-spring-app-3.8.0目录下,在powe…...
Elasticsearch 基本概念:快速入门指南【记录】
简单记录,后续整理补充 介绍: Elasticsearch是一个分布式、可扩展、实时的搜索和分析引擎,建立在开源搜索库Lucene之上。它提供了强大的全文搜索功能和复杂的分析能力,适用于各种场景,包括应用日志分析、电子商务搜索…...

SpringBoot-17-MyBatis动态SQL标签之常用标签
文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

测试微信模版消息推送
进入“开发接口管理”--“公众平台测试账号”,无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息: 关注测试号:扫二维码关注测试号。 发送模版消息: import requests da…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

IT供电系统绝缘监测及故障定位解决方案
随着新能源的快速发展,光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域,IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选,但在长期运行中,例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...

Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
稳定币的深度剖析与展望
一、引言 在当今数字化浪潮席卷全球的时代,加密货币作为一种新兴的金融现象,正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而,加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下,稳定…...

脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)
一、OpenBCI_GUI 项目概述 (一)项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台,其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言,首次接触 OpenBCI 设备时,往…...
深入浅出Diffusion模型:从原理到实践的全方位教程
I. 引言:生成式AI的黎明 – Diffusion模型是什么? 近年来,生成式人工智能(Generative AI)领域取得了爆炸性的进展,模型能够根据简单的文本提示创作出逼真的图像、连贯的文本,乃至更多令人惊叹的…...

stm32wle5 lpuart DMA数据不接收
配置波特率9600时,需要使用外部低速晶振...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现指南针功能
指南针功能是许多位置服务应用的基础功能之一。下面我将详细介绍如何在HarmonyOS 5中使用DevEco Studio实现指南针功能。 1. 开发环境准备 确保已安装DevEco Studio 3.1或更高版本确保项目使用的是HarmonyOS 5.0 SDK在项目的module.json5中配置必要的权限 2. 权限配置 在mo…...