【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之上。它提供了强大的全文搜索功能和复杂的分析能力,适用于各种场景,包括应用日志分析、电子商务搜索…...
多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度
一、引言:多云环境的技术复杂性本质 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时,基础设施的技术债呈现指数级积累。网络连接、身份认证、成本管理这三大核心挑战相互嵌套:跨云网络构建数据…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...
python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
基于Docker Compose部署Java微服务项目
一. 创建根项目 根项目(父项目)主要用于依赖管理 一些需要注意的点: 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件,否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...
大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计
随着大语言模型(LLM)参数规模的增长,推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长,而KV缓存的内存消耗可能高达数十GB(例如Llama2-7B处理100K token时需50GB内存&a…...
html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...
NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合
在汽车智能化的汹涌浪潮中,车辆不再仅仅是传统的交通工具,而是逐步演变为高度智能的移动终端。这一转变的核心支撑,来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒(T-Box)方案:NXP S32K146 与…...
打手机检测算法AI智能分析网关V4守护公共/工业/医疗等多场景安全应用
一、方案背景 在现代生产与生活场景中,如工厂高危作业区、医院手术室、公共场景等,人员违规打手机的行为潜藏着巨大风险。传统依靠人工巡查的监管方式,存在效率低、覆盖面不足、判断主观性强等问题,难以满足对人员打手机行为精…...
PHP 8.5 即将发布:管道操作符、强力调试
前不久,PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5!作为 PHP 语言的又一次重要迭代,PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是,借助强大的本地开发环境 ServBay&am…...
