当前位置:网站首页>STM32——DMA笔记
STM32——DMA笔记
2022-07-26 03:00:00 【最穷不过要饭、不死总会出头】
一、DMA是什么
DMA 传输将数据从一个 地址空间复制到另外一个地址空间。当 CPU 初始化这个传输动作,传输动作本身是由 DMA 控制器 来实行和完成。典型的例子就是移动一个外部内存的区块到芯片内部更快的 内存区。像是这样的操作并没有让处理器工作拖延,反而可以被重新排程去处理其他的工 作。DMA 传输方式无需 CPU 直接 控制传输,通过硬件为 RAM 与 I/O 设备 开辟一条直接传送数据的通路,能使 CPU 的效率大为提高。
二、DMA的作用
“搬运”,将外部数据搬运进MCU,这件事不需要CPU去做,CPU可以去处理别的事情。
三、DMA1的通道对应的“搬用源”

四、DMA的相关配置
其中主要配置前三个标红的框,第四个紫色框根据一次搬运的长度选择,有一个8位、16位、32位。
u16 ADC1_Value[C_Channel_Sample][C_ADC_Channel] = { 0 }; // DMA搬运数据存放处(数组)

DMA的配置:
void DMA_Init_JX(void)
{
DMA_InitTypeDef DMA_InitStructure;
//NVIC_InitTypeDef NVIC_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); // 使能DMA时钟
// DMA_CH1(ADC1)参数设置
//--------------------------------------------------------------------------------------------------------------------------
DMA_DeInit(DMA1_Channel1); // 将DMA的通道1寄存器重设为缺省值
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&ADC1->DR; // DMA外设ADC基地址
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ADC1_Value; // DMA内存基地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; // 内存作为数据传输的目的地
DMA_InitStructure.DMA_BufferSize = C_ADC_Channel * C_Channel_Sample; // DMA通道的DMA缓存的大小
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // 外设地址寄存器不变
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; // 内存地址寄存器递增
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; // 数据宽度为16位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; // 数据宽度为16位
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; // 工作在循环缓存模式
DMA_InitStructure.DMA_Priority = DMA_Priority_High; // DMA通道 x拥有高优先级
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; // DMA通道x没有设置为内存到内存传输
DMA_Init(DMA1_Channel1, &DMA_InitStructure); // 根据DMA_InitStruct中指定的参数初始化DMA的通道
//--------------------------------------------------------------------------------------------------------------------------
DMA_Cmd(DMA1_Channel1, ENABLE); // 启动DMA通道
}ADC通道的配置:
void ADC1_Rocker_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
// NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_ADC1, ENABLE); // 使能PA端口和ADC1时钟
// 模拟输入:PA1、PA2、PA3、PA6
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; // 模拟输入引脚
//GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; // 输入模式无需设置端口速度
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 配置ADC1_CH1、ADC1_CH2、ADC1_CH3、ADC1_CH6
// ADC工作条件:ADC的时钟频率<=14MHz && ADC采样频率<=1MHz
// ADC的总转换周期(必须>=1us) = (采样周期(1.5~239.5) + 12.5(固定转换周期)) / ADC时钟频率
// 当:ADC的时钟频率==12MHz、采样周期==1.5,ADC转换周期≈1.17us
//---------------------------------------------------------------------------------------------------------------------
RCC_ADCCLKConfig(RCC_PCLK2_Div6); // ADC时钟6分频:72M/6=12M
ADC_DeInit(ADC1); // 复位ADC1
// 设置ADC1的工作模式
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; // ADC工作模式:ADC1和ADC2工作在独立模式
ADC_InitStructure.ADC_ScanConvMode = ENABLE; // "扫描转换模式"使能。即:ADC工作在多通道模式
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; // "连续转换模式"失能。即:ADC工作在单次转换模式
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; // 转换由软件启动(也可以设置为外部触发)
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; // ADC数据对齐方式:右对齐
ADC_InitStructure.ADC_NbrOfChannel = C_ADC_Channel; // 设置顺序进行规则转换的ADC通道的数目
ADC_Init(ADC1, &ADC_InitStructure); // 初始化ADC1
// 为了能够正确地配置每一个 ADC 通道,用户在调用 ADC_Init()之后,
// 必须调用ADC_xxxChannelConfig()来配置每个所使用通道的转换次序和采样时间。
//--------------------------------------------------------------------
ADC_RegularChannelConfig(ADC1, N_ADC_Channel_1, 1, ADC_SampleTime_239Cycles5); // 参数:ADC1,要设置的ADC通道序号,规则组采样顺序,采样周期
// 此函数:配置的是"ADC1"的通道"1",它在规则组中的采样顺序是"1",采样周期是"ADC_SampleTime_239Cycles5"
ADC_RegularChannelConfig(ADC1, N_ADC_Channel_3, 2, ADC_SampleTime_239Cycles5);
// 此函数:配置的是"ADC1"的通道"3",它在规则组中的采样顺序是"2",采样周期是"ADC_SampleTime_239Cycles5"
//---------------------------------------------------------------------------------------------------------------------
/*
//ADC1的中断NVIC设置
//---------------------------------------------------------------------------------
NVIC_InitStructure.NVIC_IRQChannel = ADC1_2_IRQn; // ADC1中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; // 抢占优先级3级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; // 子优先级3级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // 使能ADC1_2_IRQn中断
NVIC_Init(&NVIC_InitStructure); // 初始化NVIC寄存器
ADC_ITConfig(ADC1,ADC_IT_EOC,ENABLE ); // 允许ADC1的EOC中断
//---------------------------------------------------------------------------------
*/
// 开启ADC的DMA支持
ADC_DMACmd(ADC1, ENABLE); // 要实现DMA功能,还需独立配置DMA通道等参数
ADC_Cmd(ADC1, ENABLE); // 使能ADC1
ADC_ResetCalibration(ADC1); // 使能ADC1复位校准
while(ADC_GetResetCalibrationStatus(ADC1)); // 等待ADC1复位校准结束
ADC_StartCalibration(ADC1); // 开启ADC1校准
while(ADC_GetCalibrationStatus(ADC1)); // 等待ADC1校准结束
}ADC采集:
在配置时,配置为软件触发方式。在使用ADC时,使用程序使能ADC1转换,也就是第一句。
搬运时DMA一次搬运16位数据,前8位为ADC1通道1的值,放在二维数组的第一列
后8位为ADC1通道3的值,放在二维数组的第二列
void ADC1_Value_average(void)
{
// 摇杆检测
//------------------------------------------------------------------------
ADC_SoftwareStartConvCmd(ADC1, ENABLE); // 软件使能ADC1转换
// 转换完成后,DMA自动将数据搬运到指定位置
//while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC )); // 等待转换结束
AM_ADC_Channel1_Sample += ADC1_Value[C_ADC_Sample][0]; // 得到
AM_ADC_Channel3_Sample += ADC1_Value[C_ADC_Sample][1];
C_ADC_Sample++ ; // ADC实际采样次数
// 判断是否已经采样10次
if(C_ADC_Sample >= C_Channel_Sample)
{
C_ADC_Sample = 0;
AV_ADC_Channel1_Sample = AM_ADC_Channel1_Sample / C_Channel_Sample; // 求通道1的平均值
AM_ADC_Channel1_Sample = 0 ;
AV_ADC_Channel3_Sample = AM_ADC_Channel3_Sample / C_Channel_Sample; // 求通道3的平均值
AM_ADC_Channel3_Sample = 0 ;
}
}边栏推荐
- Win11更改磁盘驱动器号的方法
- 1.软件测试-----软件测试的基本概念
- Games101 review: rasterization
- Annotation development management third-party beans
- From the annual reports of major apps, we can see that user portraits - labels know you better than you do
- Nahamcon CTF 2022 babyrev reverse analysis
- Information system project managers must recite the core examination site (50). The contract content is not clearly stipulated
- FPGA_ Initial use process of vivado software_ Ultra detailed
- Oxycon 2022 network capture frontier conference is about to open!
- 第3章业务功能开发(删除线索)
猜你喜欢
![[sql] usage of self connection](/img/92/92474343b4b4e6ea60453b4799cb55.jpg)
[sql] usage of self connection

文件操作(一)——文件简介与文件的打开方式和关闭
![[steering wheel] use the 60 + shortcut keys of idea to share with you, in order to improve efficiency (live template & postfix completion)](/img/b8/56c4541602c5a6e787e2455f80febd.png)
[steering wheel] use the 60 + shortcut keys of idea to share with you, in order to improve efficiency (live template & postfix completion)

Information system project managers must recite the core examination site (50). The contract content is not clearly stipulated
![[SQL] CASE表达式](/img/05/1bbb0b5099443f7ce5f5511703477e.png)
[SQL] CASE表达式

OxyCon 2022 网络抓取前沿大会即将开启!

Simply use MySQL index

第3章业务功能开发(删除线索)

MySQL教程:MySQL数据库学习宝典(从入门到精通)

Autojs cloud control source code + display
随机推荐
移位距离和假设的应用
朋友刚学完自动化测试就拿25Koffer,我功能测试何时才能到头?
多线程编程
Autojs cloud control source code + display
Chapter 3 business function development (delete clues)
Pipnet: face key point detection for natural scenes "pixel in pixel net: directions efficient facial landmark detection in the wild"
[translation] cloud like internal load balancer for kubernetes?
How about GF Securities? Is it safe to open an account online?
基础知识-网络与服务器
Vofa+ serial port debugging assistant
JS get the time composition array of two time periods
Extended Physics-InformedNeural Networks论文详解
[C language] deeply understand integer lifting and arithmetic conversion
关于mysql的问题,希望个位能帮一下忙
Basics - network and server
pbootcms上传缩略图尺寸自动缩小变模糊
After clicking play, the variables in editorwindow will be destroyed inexplicably
[SQL] CASE表达式
Pinia plugin persist, a data persistence plug-in of Pinia
图像识别(六)| 激活函数