【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之上。它提供了强大的全文搜索功能和复杂的分析能力,适用于各种场景,包括应用日志分析、电子商务搜索…...
synchronized 学习
学习源: https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖,也要考虑性能问题(场景) 2.常见面试问题: sync出…...
前端倒计时误差!
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...
【Linux】C语言执行shell指令
在C语言中执行Shell指令 在C语言中,有几种方法可以执行Shell指令: 1. 使用system()函数 这是最简单的方法,包含在stdlib.h头文件中: #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...
Objective-C常用命名规范总结
【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名(Class Name)2.协议名(Protocol Name)3.方法名(Method Name)4.属性名(Property Name)5.局部变量/实例变量(Local / Instance Variables&…...
Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...
图表类系列各种样式PPT模版分享
图标图表系列PPT模版,柱状图PPT模版,线状图PPT模版,折线图PPT模版,饼状图PPT模版,雷达图PPT模版,树状图PPT模版 图表类系列各种样式PPT模版分享:图表系列PPT模板https://pan.quark.cn/s/20d40aa…...
什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...
均衡后的SNRSINR
本文主要摘自参考文献中的前两篇,相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程,其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt 根发送天线, n r n_r nr 根接收天线的 MIMO 系…...
QT3D学习笔记——圆台、圆锥
类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体(对象或容器)QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质(定义颜色、反光等)QFirstPersonC…...
