STM32-15-DMA

打印 上一主题 下一主题

主题 953|帖子 953|积分 2859

STM32-01-熟悉单片机
STM32-02-基础知识
STM32-03-HAL库
STM32-04-时钟树
STM32-05-SYSTEM文件夹
STM32-06-GPIO
STM32-07-外部中断
STM32-08-串口
STM32-09-IWDG和WWDG
STM32-10-定时器
STM32-11-电容触摸按键
STM32-12-OLED模块
STM32-13-MPU
STM32-14-FSMC_LCD

  
STM32-15-DMA

1. DMA与中断的区别

DMA(Direct Memory Access,直接内存访问) 和中断是两种不同的机制,用于管理盘算机体系中外围设备与处理器之间的数据传输和处理。
1. DMA

工作原理:


  • 独立传输:DMA允许外设直接与体系内存交换数据,而不必要通过处理器(CPU)。当必要大量数据传输时,DMA控制器接受传输任务,释放CPU去执行其他任务。
  • 传输过程:DMA传输数据时,CPU启动DMA传输,然后DMA控制器接受整个传输过程。传输完成后,DMA控制器通过中断通知CPU传输完成。
作用:


  • 提高服从:DMA淘汰了CPU在数据传输过程中的参与,使得CPU可以或许执行其他任务,从而提高体系的整体服从。
  • 淘汰耽误:由于DMA可以独立进行传输,因此数据传输的耽误更低,特殊是在处理大块数据时。
  • 应用场景:DMA广泛应用于音频视频数据流网络数据包的传输存储设备的数据读写等场景。
对程序的影响:


  • 复杂度增长:引入DMA必要对DMA控制器进行配置,可能增长程序的复杂性。
  • 同步题目:在DMA传输过程中,程序必要处理好数据同步题目,制止数据不一致性题目。
2. 中断

工作原理:


  • 中断触发:中断是外设通过中断信号通知CPU某个事故发生,如输入设备有新数据可读取,定时器到期等。
  • 中断处理:CPU相应中断后,暂停当前任务,跳转到相应的中断处理程序(ISR)执行。当中断处理程序执行完毕后,CPU恢复先前任务的执行。
作用:


  • 实时相应:中断机制使CPU可以或许实时相应外设事故,保证体系对外部事故的快速反应。
  • 事故驱动:中断使得程序可以基于事故驱动,而不是定期轮询外设状态,从而节省CPU资源。
  • 应用场景键盘输入鼠标移动网络数据包到达定时器事故等。
对程序的影响:


  • 中断处理程序计划:中断处理程序必要尽可能简短、快速,制止长时间占用CPU。
  • 中断优先级管理:体系中可能有多个中断源,必要合理计划中断优先级,以确保关键中断可以或许及时相应。
  • 上下文切换开销:中断会引起上下文切换,带来一定的性能开销。
   总结
  

  • DMA:适用于大量数据传输,低沉CPU负载,提高体系服从。
  • 中断:适用于实时事故相应,保证体系对外部事故的快速处理。
  两者结合利用,可以构建高效、实时的嵌入式体系。比方,DMA用于大数据块的传输,而中断用于触发DMA传输和处理传输完成事故。
  2. DMA介绍



  • DMA: 即直接存储器访问。DMA传输方式无需CPU直接控制传输,也没有中断处理方式那样保留现场和恢复现场的过程,通过硬件为RAM与I/O设备开发一条直接传送数据的通路,能使CPU的服从大为提高。
  • STM32F103内部有2个DMA控制器,DMA1有7个通道,DMA2有5个通道。每个通道专门用来管理来自于一个或多个外设对存储器访问的请求,还有一个仲裁器来调和各个DMA请求的优先权。
  • 特性:

    • 每个通道都直接毗连专用的硬件DMA请求,每个通道都支持软件触发。这些功能通过软件来配置。
    • 在七个请求间的优先权可以通过软件编程设置,当软件雷同时,由硬件决定。
    • 独立的源和目标数据区的传输宽度,模仿打包和拆包的过程。源和目标地址必须按数据传输宽度对齐。
    • 支持循环的缓冲器管理。
    • 每个通道都有3个事故标志,这3个事故标志逻辑或成为一个单独的中断请求。
    • 存储器和存储器间的传输。
    • 外设和存储器,存储器和外设的传输。
    • 闪存、SRAM、外设的SRAM、APB1、APB2和AHB外设均可作为访问的源和目标。
    • 可编程的数据传输数量最大为65535。

3. DMA结构框图

1. DMA框图




  • DMA请求
    如果外假想要通过DMA来传输数据,必须先给DMA控制器发送DMA请求,DMA收到请求信号之后,控制器会给外设一个应答信号,当外设应答后且DMA控制器收到应答信号之后,就会启动DMA的传输,直到传输完毕。
  • DMA通道
    DMA具有12个独立可编程的通道,此中DMA1有7个通道,DMA2有5个通道,每个通道对应不同的外设的DMA请求。虽然每个通道可以接收多个外设的请求,但是同一时间只能接收一个,不能同时接收多个。
  • DMA优先级
    当发生多个DMA通道请求时,就意味着有先后相应处理的顺序题目,这个就由仲裁器管理。仲裁器管理DMA通道请求分为两个阶段。第一阶段属于软件阶段,可以在DMA_CCRx寄存器中设置,有4个品级:非常高四个优先级。第二阶段属于硬件阶段,如果两个或以上的DMA通道请求设置的优先级一样,则他们优先级取决于通道编号,编号越低优先权越高,比如通道0高于通道1。在大容量产品和互联型产品中,DMA1控制器拥有高于DMA2控制器的优先级。
2. DMA处理过程


DMA(Direct Memory Access,直接内存访问)是一种允许外设直接与体系内存进行数据传输的机制,不必要CPU的直接干预。以下是DMA处理过程的详细描述:
DMA处理过程

  • 配置DMA控制器

    • 源地址:设置数据传输的源地址(可以是外设寄存器地址或内存地址)。
    • 目标地址:设置数据传输的目标地址(可以是外设寄存器地址或内存地址)。
    • 传输方向:指定数据传输的方向,是从外设到内存,照旧从内存到外设。
    • 数据长度:设置必要传输的数据长度(字节数)。
    • 传输模式:选择传输模式,可以是单次传输、块传输或连续传输模式。

  • 启动DMA传输

    • 触发传输:在配置完成后,通过设置DMA控制器的启动位,开始数据传输。
    • 数据搬运:DMA控制器接受数据传输任务,将数据从源地址搬运到目标地址。这个过程中,DMA控制器直接与内存控制器和外设总线进行交互,不必要CPU干预。

  • 中断通知

    • 传输完成中断:数据传输完成后,DMA控制器产生中断信号,通知CPU传输已经完成。CPU执行相应的中断服务程序(ISR)处理后续任务。
    • 错误处理:如果在传输过程中发生错误(如总线错误),DMA控制器也会产生中断,通知CPU进行错误处理。

3. DMA通道

DMA1通道与外设的对应关系

DMA2通道与外设的对应关系

4. DMA相关寄存器

寄存器名称作用DMA_CCRxDMA通道x配置寄存器用于配置DMA(焦点控制寄存器)DMA_ISRDMA中断状态寄存器用于查询当前DMA传输状态DMA_IFCRDMA中断标志清除寄存器用来清除DMA_ISR对应位DMA_CNDTRxDMA通道x传输数量寄存器用于控制DMA通道x每次传输的数据量DMA_CPARxDMA通道x外设地址寄存器用于存储STM32外设地址DMA_CMARxDMA通道x存储器地址寄存器用于存放存储器的地址USART_CR3USART控制寄存器3用于使能串口DMA发送

  • DMA通道x配置寄存器(DMA_CCRx)

  • DMA中断状态寄存器(DMA_ISR)

  • DMA 中断标志清除寄存器(DMA_IFCR)

  • DMA通道x传输数量寄存器(DMA_CNDTRx)

    该寄存器控制着DMA通道x的每次传输所要传输的数据量。其设置范围为0~65535。而且该寄存器的值随着传输的进行而淘汰,当该寄存器的值为0的时候就代表此次数据传输己经全部发送完成。可以通过这个寄存器的值来获取当前DMA传输的进度
  • DMA通道x外设地址寄存器(DMA_CPARx)

    用来存储 STM32 外设的地址。
  • DMA通道x存储器地址寄存器(DMA_CMARx)

    用来存放存储器的地址。
5. DMA相关HAL库驱动


  • 使能DMA时钟
    1. __HAL_RCC_DMA1_CLK_ENABLE();
    复制代码
  • 初始化DMA
    1. HAL_StatusTypeDef HAL_DMA_Init(DMA_HandleTypeDef *hdma);
    2. typedef struct
    3. {
    4. uint32_t Direction; /* 传输方向,例如存储器到外设 DMA_MEMORY_TO_PERIPH */
    5. uint32_t PeriphInc; /* 外设(非)增量模式,非增量模式 DMA_PINC_DISABLE */
    6. uint32_t MemInc; /* 存储器(非)增量模式,增量模式 DMA_MINC_ENABLE */
    7. uint32_t PeriphDataAlignment; /* 外设数据大小:8/16/32 位 */
    8. uint32_t MemDataAlignment; /* 存储器数据大小:8/16/32 位 */
    9. uint32_t Mode; /* 模式:循环模式/普通模式 */
    10. uint32_t Priority; /* DMA 优先级:低/中/高/非常高 */
    11. }DMA_InitTypeDef;
    12. __HAL_LINKDMA(&g_uart1_handler, hdmatx, g_dma_handle);
    复制代码
  • 使能串口的DMA发送,启动传输
    1. HAL_UART_Transmit_DMA()
    2.    
    3. HAL_StatusTypeDef HAL_UART_DMAStop(UART_HandleTypeDef *huart); /* 停止 */
    4. HAL_StatusTypeDef HAL_UART_DMAPause(UART_HandleTypeDef *huart); /* 暂停 */
    5. HAL_StatusTypeDef HAL_UART_DMAResume(UART_HandleTypeDef *huart); /* 恢复 */
    复制代码
  • 查询DMA传输状态
    1. //查询DMA传输通道的状态
    2. __HAL_DMA_GET_FLAG(&g_dma_handle, DMA_FLAG_TC4);
    3. //获取当前传输剩余数据量
    4. __HAL_DMA_GET_COUNTER(&g_dma_handle);
    5. //设置对应的DMA数据流传输的数据量大小
    6. __HAL_DMA_SET_COUNTER (&g_dma_handle, 1000);
    复制代码
  • DMA中断利用
    1. //通用中断处理函数
    2. void HAL_DMA_IRQHandler();
    3. //相关中断回调函数
    4. //发送完成回调函数
    5. void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart);
    6. //发送一半回调函数
    7. void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart);
    8. //接收完成回调函数
    9. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);
    10. //接收一半回调函数
    11. void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart);
    12. //传输出错回调函数
    13. void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart);
    复制代码
6. 代码实现



  • 功能
    每按下按键KEY0,串口1就会以DMA方式发送数据,同时在LCD上面体现传送进度。打开串口调试助手,可以收到DMA发送的内容。LED0闪烁用于提示程序正在运行。
  • DMA初始化函数
    1. void dma_init(DMA_Channel_TypeDef* DMAx_CHx)
    2. {
    3.     if((uint32_t)DMAx_CHx > (uint32_t)DMA1_Channel7)
    4.     {
    5.         __HAL_RCC_DMA2_CLK_ENABLE();
    6.     }
    7.     else
    8.     {
    9.         __HAL_RCC_DMA2_CLK_ENABLE();
    10.     }
    11.    
    12.     //将DMA与USART1连接起来
    13.     __HAL_LINKDMA(&g_uart1_handle, hdmatx, g_dma_handle);
    14.    
    15.    
    16.     g_dma_handle.Instance = DMAx_CHx;                   //USART1_TX使用的DMA通道为DMA_Channel4
    17.     g_dma_handle.Init.Direction = DMA_MEMORY_TO_PERIPH; //模式选择为从存储器到外设
    18.     g_dma_handle.Init.PeriphInc = DMA_PINC_DISABLE;     //外设非增量模式
    19.     g_dma_handle.Init.MemInc = DMA_MINC_ENABLE;         //存储器增量模式
    20.     g_dma_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; //外设数据长度为8位
    21.     g_dma_handle.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;    //存储器数据长度为8位
    22.     g_dma_handle.Init.Priority = DMA_PRIORITY_MEDIUM;            //中等优先级
    23.    
    24.     HAL_DMA_Init(&g_dma_handle);
    25. }
    复制代码
  • 主函数
    1. int main(void)
    2. {
    3.     uint16_t i, k;
    4.     uint16_t len;
    5.     uint8_t  mask = 0;
    6.     float pro = 0;          /* 进度 */
    7.     HAL_Init();                         /* 初始化HAL库 */
    8.     sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
    9.     delay_init(72);                     /* 延时初始化 */
    10.     usart_init(115200);                 /* 串口初始化为115200 */
    11.     led_init();                         /* 初始化LED */
    12.     lcd_init();                         /* 初始化LCD */
    13.     key_init();                         /* 初始化按键 */
    14.     dma_init(DMA1_Channel4);            /* 初始化串口1 TX DMA */
    15.     lcd_show_string(30, 50, 200, 16, 16, "STM32", RED);
    16.     lcd_show_string(30, 70, 200, 16, 16, "DMA TEST", RED);
    17.     lcd_show_string(30, 90, 200, 16, 16, "ATOM@ALIENTEK", RED);
    18.     lcd_show_string(30, 110, 200, 16, 16, "KEY0:Start", RED);
    19.     len = sizeof(TEXT_TO_SEND);
    20.     k = 0;
    21.    
    22.     for (i = 0; i < SEND_BUF_SIZE; i++) /* 填充ASCII字符集数据 */
    23.     {
    24.         if (k >= len)   /* 入换行符 */
    25.         {
    26.             if (mask)
    27.             {
    28.                 g_sendbuf[i] = 0x0a;
    29.                 k = 0;
    30.             }
    31.             else
    32.             {
    33.                 g_sendbuf[i] = 0x0d;
    34.                 mask++;
    35.             }
    36.         }
    37.         else     /* 复制TEXT_TO_SEND语句 */
    38.         {
    39.             mask = 0;
    40.             g_sendbuf[i] = TEXT_TO_SEND[k];
    41.             k++;
    42.         }
    43.     }
    44.     i = 0;
    45.     while (1)
    46.     {
    47.         if (key_scan(0) == 1)       /* KEY0按下 */
    48.         {
    49.             printf("\r\nDMA DATA:\r\n");
    50.             lcd_show_string(30, 130, 200, 16, 16, "Start Transimit....", BLUE);
    51.             lcd_show_string(30, 150, 200, 16, 16, "   %", BLUE);    /* 显示百分号 */
    52.             HAL_UART_Transmit_DMA(&g_uart1_handle, g_sendbuf, SEND_BUF_SIZE);
    53.             /* 等待DMA传输完成,此时我们来做另外一些事情,比如点灯  
    54.              * 实际应用中,传输数据期间,可以执行另外的任务
    55.              */
    56.             while (1)
    57.             {
    58.                 if ( __HAL_DMA_GET_FLAG(&g_dma_handle, DMA_FLAG_TC4))   /* 等待 DMA1_Channel4 传输完成 */
    59.                 {
    60.                     __HAL_DMA_CLEAR_FLAG(&g_dma_handle, DMA_FLAG_TC4);
    61.                     HAL_UART_DMAStop(&g_uart1_handle);                  /* 传输完成以后关闭串口DMA */
    62.                     break;
    63.                 }
    64.                 pro = DMA1_Channel4->CNDTR; /* 得到当前还剩余多少个数据 */
    65.                 len = SEND_BUF_SIZE;        /* 总长度 */
    66.                 pro = 1 - (pro / len);      /* 得到百分比 */
    67.                 pro *= 100;                 /* 扩大100倍 */
    68.                 lcd_show_num(30, 150, pro, 3, 16, BLUE);
    69.             }
    70.             lcd_show_num(30, 150, 100, 3, 16, BLUE);    /* 显示100% */
    71.             lcd_show_string(30, 130, 200, 16, 16, "Transimit Finished!", BLUE); /* 提示传送完成 */
    72.         }
    73.         i++;
    74.         delay_ms(10);
    75.         if (i == 20)
    76.         {
    77.             LED0_TOGGLE();  /* LED0闪烁,提示系统正在运行 */
    78.             i = 0;
    79.         }
    80.     }
    81. }
    复制代码
  • 实验效果
    通过LCD屏可以看到数据传输的百分比,通过串口助手可以看到传输的数据

               
       

   声明:资料来源(战舰STM32F103ZET6开发板资源包)
  

  • Cortex-M3权威指南(中文).pdf
  • STM32F10xxx参考手册_V10(中文版).pdf
  • STM32F103 战舰开发指南V1.3.pdf
  • STM32F103ZET6(中文版).pdf
  • 战舰V4 硬件参考手册_V1.0.pdf

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

农妇山泉一亩田

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表