关联:STM32总结超全笔记【秋招自用】
【引言】
我们在上一节已经了解了ADC以及AD单通道采集的过程,那么既然有AD单通道,那么必然有AD多通道,上一节也已经铺垫了一下:
【问】如果一个规则组同时用多个通道采集数据,那么数据如何读取?
--DMA--
按照规则组的顺序:上一个通道转换的数据会被下一个通道转换的数据所覆盖。
所以通道转换完毕后要及时使用DMA把数据取走。
【问】CPU不是也可以访问这条ADC采集的数据总线吗?为什么一定要DMA去做?
CPU相当于STM32的大脑,对于数据的复制和存储这种“小事情”,完全可以让他的小助手DMA去做。
【DMA】
DMA,全称Direct Memory Access,即直接存储器访问。
DMA将数据从一个地址空间复制到另一个地址空间,提供在外设和存储器之间的高速数据传输。
【DMA工作流程】
如图所示:
【DMA数据传输方式】
1.增量模式:DMA数据传输的数据源和目的地址会自动递增。
优点:可以方便的连续传输数据块
适用于:从连续内存区域读取或写入数据
2.循环模式:DMA数据传输的数据源和目的地之在达到终点后会回到起始地址。
优点:可以重复传输一定长度的数据
适用于:周期性传输数据 或 循环缓冲区
【STM32的DMA】
STM32F103具有2个DMA控制器 ,DMA1有7个通道,DMA2有5个通道。每个通道都可以配置一些外设的地址。
这是DMA1可以产生的7个通道的DMA请求 ,每个通道对应不同的外设
【例程10】AD多通道+DMA转运实验
【GPIO的配置】
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA的时钟
/*GPIO初始化*/
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//将PA0、PA1、PA2和PA3引脚初始化为模拟输入
四个引脚都配置为模拟输入
【ADC的配置】
/*开启时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); //开启ADC1的时钟
/*设置ADC时钟*/
RCC_ADCCLKConfig(RCC_PCLK2_Div6); //选择时钟6分频,ADCCLK = 72MHz / 6 = 12MHz
/*规则组通道配置*/
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5); //规则组序列1的位置,配置为通道0
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_55Cycles5); //规则组序列2的位置,配置为通道1
ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_55Cycles5); //规则组序列3的位置,配置为通道2
ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 4, ADC_SampleTime_55Cycles5); //规则组序列4的位置,配置为通道3
/*ADC初始化*/
ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //独立模式,单独使用ADC1
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //数据右对齐
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //使用软件触发
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //连续转换
ADC_InitStructure.ADC_ScanConvMode = ENABLE; //扫描模式使能,扫描规则组的序列,扫描数量由ADC_NbrOfChannel确定
ADC_InitStructure.ADC_NbrOfChannel = 4; //通道数为4,扫描规则组的前4个通道
ADC_Init(ADC1, &ADC_InitStructure);
规则组通道配置:看图即可。
多通道(4个通道)使能了连续转换和扫描模式 。
【DMA的配置】
uint16_t AD_Value[4]; //定义用于存放AD转换结果的全局数组
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //开启DMA1的时钟
/*DMA初始化*/
DMA_InitTypeDef DMA_InitStructure;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
//外设基地址,给定形参AddrA
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
//外设数据宽度,选择半字,对应16为的ADC数据寄存器
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
//外设地址自增,选择失能,始终以ADC数据寄存器为源
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)AD_Value;
//存储器基地址,给定存放AD转换结果的全局数组AD_Value
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
//存储器数据宽度,选择半字,与源数据宽度对应
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
//存储器地址自增,选择使能,每次转运后,数组移到下一个位置
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
//数据传输方向,选择由外设到存储器,ADC数据寄存器转到数组
DMA_InitStructure.DMA_BufferSize = 4;
//转运的数据大小(转运次数),与ADC通道数一致
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
//模式,选择循环模式,与ADC的连续转换一致
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
//存储器到存储器,选择失能,数据由ADC外设触发转运到存储器
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
//优先级,选择中等
DMA_Init(DMA1_Channel1, &DMA_InitStructure); //将结构体变量交给DMA_Init,配置DMA1的通道1
DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
指的是DMA传输的外设基地址,本实验是DMA转运ADC的数据,自然是从ADC1的DR寄存器读数据。
DMA_PeripheralDataSize_HalfWord;
每次从外设读取或向外设写入数据时,DMA传输的数据大小为16位(2字节),
DMA_PeripheralInc_Disable;
外设地址自增失能,因为始终要以ADC数据寄存器为源
DMA_Priority_Medium
当多个DMA通道同时请求访问DMA控制器时,这个优先级决定了哪个通道会被优先服务。文章来源:https://www.toymoban.com/news/detail-858923.html
【使能ADC和DMA,触发ADC】
/*DMA和ADC使能*/
DMA_Cmd(DMA1_Channel1, ENABLE); //DMA1的通道1使能
ADC_DMACmd(ADC1, ENABLE); //ADC1触发DMA1的信号使能
ADC_Cmd(ADC1, ENABLE); //ADC1使能
/*ADC触发*/
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //软件触发ADC开始工作
【主函数】
while (1)
{
OLED_ShowNum(1, 5, AD_Value[0], 4); //显示转换结果第0个数据
OLED_ShowNum(2, 5, AD_Value[1], 4); //显示转换结果第1个数据
OLED_ShowNum(3, 5, AD_Value[2], 4); //显示转换结果第2个数据
OLED_ShowNum(4, 5, AD_Value[3], 4); //显示转换结果第3个数据
Delay_ms(100); //延时100ms,手动增加一些转换的间隔时间
}
把数组中的数据在OLED上显示出来文章来源地址https://www.toymoban.com/news/detail-858923.html
到了这里,关于【第五章】STM32-ADC模数转换(2.AD多通道+DMA转运实验)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!