目录
前言
上文讲述了使用非扫描模式配置ADC多通道,但是为了提高效率,本文会用扫描模式配置多通道。
但是规则组的数据寄存器只能放得下一个通道的转换结果,后来的数据会将已在的数据进行覆盖,为避免出现这种情况,本文会使用DMA将每个通道的数据进行搬运,以此实现扫描模式配置ADC多通道。
提示:以下是本篇文章正文内容,下面案例可供参考
一、介绍DMA
(1)概念
DMA的全称是Direct Memory Access,意为直接存储器存取。
DMA用于外设和存储器以及存储器和存储器之间的高速数据传输,并且这个传输过程无需CPU干涉,节省了CPU的资源。
(2)硬件资源
对于大容量的STM32芯片,一般都有两个DMA外设。分别是DMA1(7个通道),DMA2(5个通道)。
每个通道都支持软件触发和特定的硬件触发。
硬件触发一般用于外设和存储器之间,软件触发用于存储器和存储器之间。
(3)整体框图
上图为DMA的整体框图,从图中我们可得以下几点信息
- DMA仲裁器配置通道优先级。在总线矩阵中也有仲裁器,当DMA和CPU同时向同一个数据发送请求时,会暂停CPU的请求,但也会有一半的带宽留给CPU。
- 外设和存储器以及存储器和存储器之间可互相进行数据传输。
- 必须配置传输计数器,来确定传输的次数,次数必须要大于0。
- 通过配置自动重装器,来确定是否需要不停地连续传输。
- DMA传输必须要有触发信号
- DMA传输必须要使能DMA通道和对应外设的DMA使能
二、代码实现
(1)DMA初始化
代码如下:
DMA_InitTypeDef DMA_InitStructure;
DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1->DR; //起点地址为ADC1的DR寄存器
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //传输的数据宽度为半字
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //因为起点地址固定,所以失能地址自增模式
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)AD_Value; //因为地址是32位的 所以强转为32位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//传输的数据宽度为半字
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;//因为终点地址固定,所以失能地址自增模式
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //设置DMA通道优先级为中等
DMA_InitStructure.DMA_BufferSize = 3;//因为有三个数值要传输,所以将传输计数器的值设为3
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//从ADC外设传输到SRAM存储器,所以ADC寄存器地址为源地址
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //是否开启软件触发:否 因为ADC属于硬件触发源
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //开启DMA循环转运模式
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
DMA结构体的参数较多,所以配置时应当细心。
(2)使能通道
代码如下:
DMA_Cmd(DMA1_Channel1,ENABLE); //使能DMA1的通道1
ADC_DMACmd(ADC1, ENABLE); //使能ADC1触发DMA1的信号
ADC_Cmd(ADC1, ENABLE); //使能ADC1,ADC开始运行
(3)定义存放数组
定义一个SRAM数组,用于存放ADC转换后的值。
uint16_t AD_Value[3];
(4)主函数
int main(void)
{
ADC1_DMA_Init();
OLED_Init();
OLED_ShowString(0, 0, "AD0:", OLED_8X16);
OLED_ShowString(0, 16, "AD1:", OLED_8X16);
OLED_ShowString(0, 32, "AD2:", OLED_8X16);
while (1)
{
OLED_ShowNum(32, 0, AD_Value[0], 4, OLED_8X16);//DMA搬运后的数据
OLED_ShowNum(32, 16, AD_Value[1], 4, OLED_8X16);
OLED_ShowNum(32, 32, AD_Value[2], 4, OLED_8X16);
Delay_ms(100);
OLED_Update();
}
}
三、应用实现
(1)硬件连接
光敏传感器------AO PA0 热敏传感器----- AO PA1 对射式红外传感器---AO PA2
(2)实验目的
利用DMA搬运ADC扫描模式下转换完成的多通道AD数据至SRAM数组
熟练掌握DMA搬运原理以及ADC多通道配置
(3)实验现象
(4)实验结果
DMA搬运正常,实验完成。
总结
本文实现了外设与外设之间的互相合作,但这仅仅只是基础实现,希望各位读者可以不断继续学习进步。