Stm32的DMA以及相关存储器的知识

DMA知识

Stm32F103c8t6的DAM资源:DMA1

DMA通道数:7个

        对于大容量的STM32芯片有2个DMA控制器 两个DMA控制器,DMA1有7个通道,DMA2有5个通道。

名称:Direct Memory Access,直接存储器访问。

存储器:

ROM:只读存储器(全写为 read-only memory),掉电不丢失。

RAM:随机存储器(Random Access Memory),掉电丢失

两种存储器类型对应的具体存储器(参考自江协):

补充说明:寄存器属于存储器的一种。

        一些存储器被称为寄存器,是因为它们是CPU内部的一种非常快速的存储器件,用于暂存CPU执行指令和数据的地方。寄存器具有高速读写的特点,主要用于存储临时数据和进行地址计算。

        存在非CPU的寄存器,主要是为了与CPU交互信息方便。在接口内部一般会设置一些可以被CPU直接访问的寄存器,这些寄存器虽然不属于CPU,但它们是主机的一部分,用于提高数据传输和处理的效率。

运输方向:

        ①外设存储器<——>存储器

        ②存储器<——>存储器

外设:指连接的设备,相对于STM32内核上的板子上的设备而言,它们是外部设备的简称,指的是集成电路芯片外部的设备。外设就是挂载在总线上的设备,也就是在启动时需要先开启外设时钟才能使用。(?不太确定)

数据宽度的转运问题:

①高位数寄存器的数据——>低位数的寄存器:每一个数据都会舍去高位数据。

        如16位数据放在8位数据寄存器,则只留下低8位的数据,高8位被越界舍弃。

②同位数数据寄存器之间相传:数据不变。

③低位数数据寄存器——>高位数数据寄存器:高位补0,数值不变。

工作特点:配置好后无需CPU干预,硬件自发完成(转运,地址自增),节省了CPU资源。

触发方式:

        ①软件触发:多用于存储器之间,目的是为了快速传输完数据。(适用于已知全部数据源的情况,不能和重装计数器一起用,否则卡死)

        ②硬件触发:外设存储器<—>存储器,目的是为了在保证外设输入完整数据,或外设接收完整数据之后,再进行下一次传输。(适用于需要一定时间等待数据完整传输的情况)

访问权:

        ①因为DMA可以硬件转运存储器、外设存储器之间的数据,所以DMA有对外设存储器的访问权。

        ②又因为DMA的启动需要软件配置,所以CPU对DMA有访问权

        ③所以DMA虽然也挂在上AHB上(让CPU访问),又拥有对挂在在AHB上其他寄存器的访问权

        ④Flash是ROM类型,无论是CPU还是DMA都是能直接读,不能直接写,要写的话需要通过Flash寄存器进行间接操作。

DMA请求:

        ①外设可以产生DMA请求(硬件信号),让DMA转运数据。不同触发源的通道不同,详细见表。

        ②软件触发可以直接触发,但是硬件触发则需要选择对应通道才能触发

        ③优先级是序号越小优先级越高

        ④ADC的扫描模式,虽然在ADC转换一次数据之后不会产生EOC转换完成标志位,但是会产生DMA请求

配置内容(接收双方都需要,只要是DMA可以直接访问进行直接读写操作的都可以,否则只读的只能作为发送源):

        ①数据传输的起始地址:数据源和接收方的地址,用变量传输的话那就是直接给变量地址

        ②数据的宽度(数据个数):要用DMA传输几个数据

        ③存储器地址是否自增:

                数据源地址(发送方)自增,每次传输一次之后指向下一个地址,能够传输不同数据

                接受方地址自增,能够在接收一次数据之后,指向下一个存储空间,防止许多数据都放在同一个空间导致新数据覆盖旧数据,避免发送多个数据却只能收到最新数据的情况

        ④传输计数器(循环次数,配置重装计数器):

                每转一次,自减一次,减完后地址重置为起始地址,同时重装值重置,配合ADC的连续+扫描模式。

                当传输计数器为0时且没有配置重装计数器时,哪怕使能了也不会再转运,需要失能后重新写入值才能接着转运

        ⑤M2M:Memory to Memory(存储器到存储器)

                置1:软件触发——快转,多用于存储器到存储器

                置0:硬件触发——需时机,多用于外设存储器到存储器

        ⑥接收字节对齐:左对齐(降低精度),右对齐(直接取值)

        ⑧DMA通道:   每个DMA通道都可以独立选择软硬件触发

主要代码(参考自江科大)

DMA的初始化

void MyDMA_Init(uint32_t AddrA, uint32_t AddrB, uint16_t Size)//数据源地址,数据目标地址,数据个数
{    /*开启时钟*/
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);                        //开启DMA的时钟
    
    /*DMA初始化*/
    DMA_InitTypeDef DMA_InitStructure;                                        //定义结构体变量
    DMA_InitStructure.DMA_PeripheralBaseAddr = AddrA;                        //外设基地址,给定形参AddrA
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;    //外设数据宽度,选择字节
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;            //外设地址自增,选择使能
    DMA_InitStructure.DMA_MemoryBaseAddr = AddrB;                            //存储器基地址,给定形参AddrB
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;            //存储器数据宽度,选择字节
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                    //存储器地址自增,选择使能
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;                        //数据传输方向,选择由外设到存储器
    DMA_InitStructure.DMA_BufferSize = Size;                                //转运的数据大小(转运次数)
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                            //模式,选择正常模式
    DMA_InitStructure.DMA_M2M = DMA_M2M_Enable;                                //存储器到存储器,选择使能
    DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;                    //优先级,选择中等
    DMA_Init(DMA1_Channel1, &DMA_InitStructure);                            //将结构体变量交给DMA_Init,配置DMA1的通道1
    
    /*DMA使能*/
    DMA_Cmd(DMA1_Channel1, DISABLE);    //这里先不给使能,初始化后不会立刻工作,等后续调用Transfer后,再开始
}

DMA的调度代码
void MyDMA_Transfer(uint16_t MyDMA_Size)//每次启动DMA需要传参说明转运多少个数据
{
    DMA_Cmd(DMA1_Channel1, DISABLE);                    //DMA失能,在写入传输计数器之前,需要DMA暂停工作
    DMA_SetCurrDataCounter(DMA1_Channel1, MyDMA_Size);    //写入传输计数器,指定将要转运的次数
    DMA_Cmd(DMA1_Channel1, ENABLE);                        //DMA使能,开始工作
    
    while (DMA_GetFlagStatus(DMA1_FLAG_TC1) == RESET);    //等待DMA工作完成
    DMA_ClearFlag(DMA1_FLAG_TC1);                        //清除工作完成标志位
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值