查看: 1170|回复: 0
收起左侧

第二十八章:CH32V103应用教程——DMA(外设到存储器)

[复制链接]

  离线 

  • TA的每日心情
    慵懒
    2021-7-23 17:16
  • 签到天数: 17 天

    [LV.4]

    发表于 2021-4-25 22:17:14 | 显示全部楼层 |阅读模式

    有人预言,RISC-V或将是继Intel和Arm之后的第三大主流处理器体系。欢迎访问全球首家只专注于RISC-V单片机行业应用的中文网站

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

    x
    本帖最后由 草帽王子 于 2021-9-10 17:12 编辑

    关于DMA,具有三种数据传输方式:存储器到存储器、存储器到外设、外设到存储器。在第十三章以及第二十七章,已讲解存储器到存储器传输方式以及存储器到外设传输方式,本章将讲解DMA外设到存储器传输方式。使用串口1作为外设,通过串口调试助手等向开发板发送数据,数据会被返回给开发板并通过串口调试助手显示。


    1、DMA简介及相关函数介绍

    关于DMA以及相关函数介绍在在第十三章以及第二十七章已讲解,在此不再介绍。关于DMA具体介绍,可参考CH32V103应用手册。


    2、硬件设计

    本章教程所用资源均为CH32V103开发板内部资源,无需进行其他硬件连接,只需进行程序配置即可。


    3、软件设计

    本章主要进行外设到存储器的DMA数据传输方式,其相较于存储器到存储器的传输方式,程序中对DMA配置进行一些修改即可。此外,本章还需用到串口1,在第三章基础上进行修改即可,即将串口2修改为串口1,以及对中断服务函数进行一些修改,具体如下:
    关于串口1中断服务函数:
    1. void USART1_IRQHandler(void)
    2. {
    3.     uint8_t i;
    4.     uint16_t t;
    5.     if(USART_GetITStatus(USART1,USART_IT_IDLE) == SET)  //检查中断是否发生
    6.     {
    7.         DMA_Cmd(DMA1_Channel5,DISABLE);                 //关闭DMA传输

    8.         t = DMA_GetCurrDataCounter(DMA1_Channel5);      //获取剩余的数据数量

    9.         for(i=0; i<RECEIVEBUFF_SIZE-t; i++)
    10.         {

    11.             USARTx_SendByte(USART1,ReceiveBuff[i]);              // 发送一个字节数据到USART2

    12.         }
    13.         /* 等待发送完成 */
    14.         while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);//向电脑返回数据(接收数据数量 = SENDBUFF_SIZE - 剩余未传输的数据数量)

    15.         DMA_SetCurrDataCounter(DMA1_Channel5,RECEIVEBUFF_SIZE); //重新设置传输的数据数量

    16.         DMA_Cmd(DMA1_Channel5,ENABLE);                          //开启DMA传输

    17.         USART_ReceiveData(USART1);                              //读取一次数据,不然会一直进中断
    18.         USART_ClearFlag(USART1,USART_FLAG_IDLE);                //清除串口空闲中断标志位
    19.     }
    20. }
    复制代码

    此函数主要进行串口中断以及进行DMA传输,此外在串口初始化配置中,需要将中断使能改为使能空闲中断,具体如下:

    1. USART_ITConfig(USART1,USART_IT_IDLE,ENABLE);                 //开启空闲中断
    复制代码

    dma.h文件
    1. #ifndef __DMA_H
    2. #define __DMA_H

    3. #include "ch32v10x_conf.h"

    4. #define  RECEIVEBUFF_SIZE       1000

    5. uint8_t ReceiveBuff[RECEIVEBUFF_SIZE];

    6. void DMA1_CH5_Init(void); //DMA传输参数初始化配置

    7. #endif
    复制代码
    dma.h文件主要进行宏定义及相关函数声明;

    dma.c文件
    1. #include "dma.h"

    2. uint8_t ReceiveBuff[RECEIVEBUFF_SIZE];

    3. /*******************************************************************************
    4. * Function Name  : DMA1_CH5_Init
    5. * Description    : Initializes Channel3 of DMA1 collection.
    6. * Input          : None
    7. * Return         : None
    8. *******************************************************************************/
    9. //DMA1通道5传输参数配置
    10. void DMA1_CH5_Init(void)
    11. {
    12.   DMA_InitTypeDef DMA_InitStructure;
    13.   RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);               //使能DMA1时钟

    14.   DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART1->DATAR);//设置源数据地址
    15.   DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ReceiveBuff;         //设置目标地址
    16.   DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;               //设置传输方向:外设到存储器(此处外设为内部FLASH)
    17.   DMA_InitStructure.DMA_BufferSize = RECEIVEBUFF_SIZE;             //设置传输大小
    18.   DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //指定外设地址寄存器不变。
    19.   DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;          //指定内存地址寄存器递增。
    20.   DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //设置外设数据单位
    21.   DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte;     //设置存储器数据单位
    22.   DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;           //设置对应DMA工作模式为正常模式
    23.   DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; //DMA1通道5优先级高
    24.   DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;            //使能DMA存储器到存储器的传输方式
    25.   DMA_Init(DMA1_Channel5, &DMA_InitStructure);            //根据DMA_InitStruct中指定的参数初始化DMA1通道3

    26.   DMA_Cmd(DMA1_Channel5, ENABLE); //使能DMA1通道5
    27. }
    复制代码

    dma.c文件主要进行DMA初始化配置,其相较于前两章,主要修改如下:

    关于源地址,改为外设地址,此处为串口1:
    1. DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART1->DATAR);
    复制代码

    关于目标地址,改为存储器地址:
    1. DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ReceiveBuff;
    复制代码

    关于DMA传输方式及方向,改为外设到存储器:
    1. DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
    复制代码

    关于DMA传输大小,根据目标数据进行设置:

    1. DMA_InitStructure.DMA_BufferSize = RECEIVEBUFF_SIZE;   
    复制代码

    此外,由CH32V103应用手册可知,本次所用外设串口1 USART_RX对应DMA通道5,如下图:

    CH32V CH573单片机芯片-第二十八章:CH32V103应用教程——DMA(外设到存储器)risc-v单片机中文社区(1)

    因此,初始化以及使能DMA通道5:
    1. DMA_Init(DMA1_Channel5, &DMA_InitStructure);            //根据DMA_InitStruct中指定的参数初始化DMA1通道5
    2. DMA_Cmd(DMA1_Channel5, ENABLE); //使能DMA1通道5
    复制代码


    4、下载验证

    将编译好的程序下载到开发板并复位,然后通过串口调试助手向单片机发送数据,单片机接收数据并通过串口调试助手显示,具体如下:

    CH32V CH573单片机芯片-第二十八章:CH32V103应用教程——DMA(外设到存储器)risc-v单片机中文社区(2)

    DMA(外设到存储器).rar附件下载

    CH32V CH573单片机芯片-第二十八章:CH32V103应用教程——DMA(外设到存储器)risc-v单片机中文社区(3) 27、DMA(外设到存储器) (1).rar (491.54 KB, 下载次数: 14)
    链接:https://pan.baidu.com/s/1XFSobUtv9OQ4BozcdCYusg
    提取码:pkqg
    复制这段内容后打开百度网盘手机App,操作更方便哦







    上一篇:第二十七章:CH32V103应用教程——DMA(存储器到外设)
    下一篇:第二十九章:CH32V103应用教程——ADC(单通道DMA读取方式)
    RISCV作者优文
    全球首家只专注于RISC-V单片机行业应用的中文网站
    回复

    使用道具 举报

    高级模式
    B Color Image Link Quote Code Smilies

    本版积分规则

    关闭

    RISC-V单片机中文网上一条 /2 下一条



    版权及免责声明|RISC-V单片机中文网 |网站地图

    GMT+8, 2024-3-28 18:43 , Processed in 0.427458 second(s), 48 queries .

    快速回复 返回顶部 返回列表