• STM32直接存储器存取DMA


    前提知识:

    1、STM32F103内部存储器结构以及映射

            STM32F103的程序存储器、数据存储器、寄存器和IO端口被组织在同一个4GB的线性地址空间内。数据字节以小端模式存放在存储器中。即低地址中存放的是字数据的低字节,高地址中存放的是字数据的高字节

             可访问 的存储器空间被分成 8个主要块 每个块为512MB 。 其他所有没有分配给片上存储器和外设的存储器空间都是保留的地址空间
    第一块(0x0000 0000 ~ 0x1FFF FFFF,512MB):
            启动空间(0x0000 0000 ~ 0x0800 0000,128MB): 代码区始终从0x0000 0000开始,通过ICode和DCode总线访问。
            启动之后, CPU从地址0x0000 0000获取堆栈顶SP的地址,并从存储器的0x0000 0004指示的地址(程序计数器指针PC)执行代码
            之所以产生上述步骤,则因为不同厂商可能会把0x0000 0000以及0x0000 0004地址映射到其他地址。因此,根据映射到不同地址分为不同的启动方式(由BOOT引脚决定)
            在系统复位后,SYSCLK 的第4个上升沿,BOOT 引脚的值将被锁存。用户可以通过设置 BOOT1 和BOOT0 引脚的状态,来选择在复位后的启动模式
    启动模式1:从Flash开始启动,正常的下载启动程序
    启动模式2:从系统存储器( 存储BOOTLoader程序,用于串口下载,将下载好的程序刷新到Flash位置)开始启动,由于系统存储器存储串口下载程序,通过这种启动方式可以通过串口将程序下载到Flash。 串口程序下载完成后,需要设置为从Flash启动,这样复位后才能正常运行程序(只能通过USART1下载)
    启动模式3:SRAM用来 存储程序运行过程中的临时变量,不能存储程序,所以该方式只用于调试程序
    启动文件的执行流程:
    复位中断函数:主要用来执行SystemInit()和main()
    Flash(0x0800 0000 ~ 0x0801 FFFF,128KB): 存储编译后的程序代码
    系统存储区 (0x1FFF F000 ~ 0x1FFF F800,8KB):存储用于串口下载程序
            系统存储器, 存储BOOTLoader程序,用于串口下载,将下载好的程序刷新到Flash位置。当从该位置启动, 其实是 执行串口下载程序,BOOTLoder会将下载的程序存放进Flash 。串口程序下载完成后,需要设置为 从Flash启动,这样复位后才能正常运行程序
    选项字节 (0x1FFF F800 ~ 0x1FFF F80F,16B):存储一些独立于程序代码的配置参数
            读保护字节、看门狗、停机或待机是否产生复位、用户字节数据(0x1FFF F804 ~ 0x1FFF F806 )(这两字节可供用户独立使用)、写保护字节(Flash的每几页)
    第二块(0x2000 0000 ~ 0x3FFF FFFF,512MB):
             SRAM(0x2000 0000 ~ 0x2000 4FFF,20KB): 存储程序运行过程中的临时变量
    作用:
    (1)选项字节中的数据不随程序的更新而改变,可以存放一些
    (2)用上位机可以很方便修改,可以用在产品中可供用户配置的参数
    第三块(0x4000 0000 ~ 0x5FFF FFFF,512MB):
            外设(0x4000 0000 ~ 0x4002 3FFF):外设寄存器空间地址
    第八块(0xE000 0000 ~ 0xFFFF FFFF,512MB):
            Cortex_M3内核外设(0xE000 0000 ~ 0xE010 0000)
    其他存储器区域均保留

    一、DMA简介

            DMA( Direct Memory Access直接存储器存取/直接存储器访问, 可以提供外设与外设之间、外设与存储器之间、存储器和存储器之间的高速数据传输,无须CPU 干预,节省了 CPU 的资源
            在DMA传输前,CPU把总线控制权交给DMA控制器,在结束DMA传输后,DMA控制器立即把总线控制权交回CPU
    DMA过程:DMA请求、DMA响应、DMA传输、DMA结束
    12个独立可配置的通道: DMA1 7 个通道), DMA2 5 个通道)
    每个通道都支持软件触发和特定的硬件触发
    STM32F103C8T6 DMA 资源: DMA17个通道)

    二、DMA结构

    (1)每个通道都直接连接 专用的硬件DMA请求,每个通道都 同样支持软件触发。这些功能通过
    软件来配置。
    (2)在同一个 DMA 模块上,多个请求间的 优先权可以通过软件编程 设置 ( 共有四级:很高、高、
    中等和低 ) 优先权相等时由硬件决定 ( 请求 0 优先于请求 1 ,依此类推 )
    (3)独立数据源和目标数据区的传输宽度 ( 字节、半字、全字 ) ,模拟打包和拆包的过程。源和目
    标地址必须按数据传输宽度对齐。
    (4)循环模式/非循环模式
    (5)每个通道都有 3 个事件标志 (DMA 半传输、 DMA 传输完成和 DMA 传输出错 ) ,这 3 个事件标志
    逻辑或成为一个单独的中断请求。
    (6)可编程的数据传输数目: 最大为65535
            DMA是AHB总线上的外设,有两个AHB端口:一个是从端口,用于配置DMA;另一个是主端口,用于设备间的数据传输。所以,DMA既是总线矩阵的主动单元,可以读写各种存储器;又是AHB总线上的被动单元,可被CPU进行配置
            STM32的Cortex-M3内核和DMA控制器通过总线矩阵连接到Flash控制总线、SRAM总线和AHB总线,进而通过AHB总线连接到AHB总线服务外设

    DMA的工作流程:

    (1)DMA传送
            当外设发送DMA请求,DMA控制器根据通道的优先权来处理请求。当DMA控制器开始访问外设时,DMA控制器首先向外设发送一个应答信号,外设得到应答信号后立即撤销请求,DMA控制器同时撤销应答信号
    (2)仲裁器
            根据优先级管理各通道的请求以及启动外设/存储器访问的顺序
            软件:最高、高、中等、低
            硬件:如果两个通道请求的优先级相同,则 低编号的通道有高优先级
    (3)DMA通道
            每个通道可以实现固定地址的外设寄存器和存储器地址之间的DMA传输。DMA传输的数据量是可编程的,最大达到65535,在 每次传输后递减
    (4)地址自增
            外设和存储器的指针可以设置为在每次传输结束后自增
    (5)中断
            3个事件标志 (DMA 半传输、 DMA 传输完成和 DMA 传输出错 ) ,这 3 个事件标志逻辑或成为一个单独的中断请求
    (6)循环模式
            数据传输数目变为0时,将自动恢复为设置的初始值,DMA操作继续。循环模式用于处理循环缓冲区和连续的数据传输,例如,ADC的扫描模式
    (7)存储器到存储器模式: 不可以与循环模式同时使用
    (8)DMA请求映射
            从外设产生的7个请求,通过逻辑或输入到DMA控制器,这意味着 某一时刻只有一个DMA请求有效(分时复用)
            MEM2MEN(Memory to Memory,存储器到存储器),当此位为1时,由软件触发,不可以和循环模式同时使用
    可编程的数据传输宽度、对齐方式和数据大小端
             当源数据宽度 = 目标数据宽度,正常传输
            当源数据宽度 < 目标数据宽度,高位补0
            当源数据宽度 > 目标数据宽度,高位舍弃,只保留低位

    三、DMA相关库函数

    (1)初始化:DMA_Init()

    (2)设置计数器:DMA_SetCurrDataCounter()
    可以单独设置DMA_BufferSize的值,即传输计数器的值

    四、DMA配置

    (1)开启DMA时钟(AHB总线)
    (2)配置DMA,完成初始化
    1. DMA_InitTypeDef DMA_InitStruct;
    2. DMA_InitStruct.DMA_PeripheralBaseAddr = source; //外设基地址
    3. DMA_InitStruct.DMA_MemoryBaseAddr = destination; //内存基地址
    4. DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Enable; //外设基地址是否递增:
    5. DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable; //内存基地址是否递增:
    6. DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //外设数据宽度:一字节
    7. DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //内存数据宽度:一字节
    8. DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC; //外设作为数据来源or数据目的地:数据来源
    9. DMA_InitStruct.DMA_BufferSize = number; //DMA缓存数据的大小:传输计数器的大小
    10. DMA_InitStruct.DMA_Mode = DMA_Mode_Normal; //工作模式 是否循环:不循环
    11. DMA_InitStruct.DMA_Priority = DMA_Priority_High; //优先级:高优先级
    12. DMA_InitStruct.DMA_M2M = DMA_M2M_Enable; //内存到内存:使能
    13. DMA_Init(DMA1_Channel1, &DMA_InitStruct);
    (3)使能DMA
    DMA工作的三个条件:
    DMA使能,打开开关
    ②传输计数器必须 大于0
    必须有触发源
    注:在写传输计数器的值时,必须 关闭DMA
  • 相关阅读:
    互联网商业模式设计方案
    Kubernetes API的流编解码器StreamSerializer
    java毕业设计小说网站mybatis+源码+调试部署+系统+数据库+lw
    vue computed和watch的区别 v-if和v-show的区别 v-if和v-for优先级的问题
    苍穹外卖-day12 - 工作台 - Apache POI - 导出运营数据Excel报表
    安卓Activity的setContentView()流程分析
    视频文件转换器有哪些?什么视频文件转换器好用?
    华为杯数学建模比赛经验分享第二期——编程手篇
    终究还是错付了~这2种Python字符串格式化的写法已经被淘汰了,你是不是还在用?
    adobe国际认证证书有用吗?
  • 原文地址:https://blog.csdn.net/qq_68719489/article/details/137922071