• Lesson23 DMA操作


    这里是一个最简单的DMA传输的例子。DMA包括:

    外设到存储器,存储器到外设,存储器到存储器之间的传输。传输的通道和数据流是有限定的,可查看数据手册的通道分配表格确定。

    具体的工程见D:2 Learn2 UC_OSmyproLesson 23 DMA

    //我们采用的是存储器到外设UART1的传输.只能选择DMA2的通道7.根据数据手册的DMA章节的通道表格
    //DMA_Streamx: 数据流 DMA1_Stream0~7/DMA2_Stream0~7
    //chx:通道选择,@ref DMA_channel DMA_Channel_0~DMA_Channel_7
    //par:外设地址
    //mar:存储器地址·
    //ndtr:传输数据个数 
    void MYDMA_Config(DMA_Stream_TypeDef *DMA_Streamx,u32 chx,u32 par,u32 mar,u16 ndtr)
    {  DMA_InitTypeDef myDMA;
         //判断是哪个通道,使能相应的时钟
         if((u32)DMA_Streamx>(u32)DMA2)
             RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);
         else
             RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE);
         //
         myDMA.DMA_BufferSize=ndtr; //DMA_SxNDTR[15:0] 数据传输量,只有禁止传输的时候,才能写入。启动传输后,表示剩余数据量
         myDMA.DMA_Channel= DMA_Channel_4;            //DMA_SxCR[27:25] 通道选择
         myDMA.DMA_DIR=DMA_DIR_MemoryToPeripheral;    //DMA_SxCR[7:6] 传输方向 存储器到外设
         myDMA.DMA_FIFOMode=DMA_FIFOMode_Disable;     //DMA_SxFCR[2] 使能直接模式
         myDMA.DMA_FIFOThreshold=DMA_FIFOThreshold_Full;//DMA_SxFCR[1:0] 使用直接模式,这个配不配都可以
         myDMA.DMA_Memory0BaseAddr=mar;               // DMA_SxM0AR[] 存储器地址
         myDMA.DMA_MemoryBurst=DMA_MemoryBurst_Single; // DMA_SxCR[24:23] 突发传输配置
         myDMA.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte;//DMA_SxCR[14:13] 存储器数据大小
         myDMA.DMA_MemoryInc=DMA_MemoryInc_Enable;          //DMA_SxCR[10] 存储器地址递增
         myDMA.DMA_Mode= DMA_Mode_Normal  ;  //DMA_SxCR[8]  禁止循环模式
         myDMA.DMA_PeripheralBaseAddr=par;      //外设地址 DMA_SxPAR
         myDMA.DMA_PeripheralBurst= DMA_PeripheralBurst_Single; ////DMA_SxCR[22:21] 外设突发配置
         myDMA.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte; //DMA_SxCR[12:11] 外设数据大小
         myDMA.DMA_PeripheralInc= DMA_PeripheralInc_Disable; //DMA_SxCR[9]  外设地址固定
         myDMA.DMA_Priority= DMA_Priority_Medium;//中等优先级 DMA_SxCR[17:16] 
         DMA_Init(DMA_Streamx, &myDMA);  //初始化   
        
    }
    
    
    // 完成一次传输
    void MYDMA_Enable(DMA_Stream_TypeDef *DMA_Streamx,u16 ndtr)
    { 
        DMA_Cmd(DMA_Streamx,DISABLE);  //关闭DMA传输 DMA_SxCR[0] EN位
        while (DMA_GetCmdStatus(DMA_Streamx) != DISABLE){}  //重新读EN位,确保关闭
        DMA_SetCurrDataCounter(DMA_Streamx,ndtr);     //DMA_SxNDTR[15:0] 关闭后才能配置传输数量
        DMA_Cmd(DMA_Streamx,ENABLE);   //使能
    }

    1

    2

    3

    #define SEND_BUF_SIZE 8200    //传输的数据量
    
    u8 SendBuff[SEND_BUF_SIZE];    // 开一个RAM空间
    const u8 TEXT_TO_SEND[]={"123456789abcde"};     
      
    int main(void)
    { 
        u8 b; 
         
        u16 i;
        u8 t=0;
        u8 j,mask=0;
        float pro=0;//
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 
        delay_init(168);     // 
        uart_init(115200);    // 
        LED_Init();                    // 
         LCD_Init();                    // 
        KEY_Init();                 // 
         MYDMA_Config(DMA2_Stream7,DMA_Channel_4,(u32)&USART1->DR,(u32)SendBuff,SEND_BUF_SIZE);//DMA2,STEAM7,CH4,串口1
    
    //把开辟的RAM空间填满
      j=sizeof(TEXT_TO_SEND)+1;    
        for(i=0;i<SEND_BUF_SIZE;i++)
        { b= i% j;
            if(b==j-2)
                SendBuff[i]=0x0d;
            if(b==j-1)
                SendBuff[i]=0x0a;
            if(b<j-2)
                SendBuff[i]=TEXT_TO_SEND[b];
        }
    
    
    
    
            
    
        i=0;
        while(1)
        {
            t=KEY_Scan(0);
            if(t==KEY0_PRES)
            { printf("start to transfer date from ram to uart by DMA
    ");
                USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE); //配置串口的CR3寄存器,这个很重要,让串口支持DMA
                MYDMA_Enable(DMA2_Stream7,SEND_BUF_SIZE);
                while(1)
                { if(DMA_GetFlagStatus(DMA2_Stream7,DMA_FLAG_TCIF7)!=RESET) //等待传输结束
                       { DMA_ClearFlag(DMA2_Stream7,DMA_FLAG_TCIF7);   //结束后要清除标志位
                        break;
                         }
                 pro=DMA_GetCurrDataCounter(DMA2_Stream7);
                 pro=1-pro/SEND_BUF_SIZE;
                 pro=pro*100;    
           //delay_ms(20);
           //printf("have already transfer %f percent data",pro);                     
                }
                 printf("
     transfer finish");
                
            }
        }
  • 相关阅读:
    常用的 写代码 的 指令
    boos
    超级搬运工
    那些年,我读过的书籍(读完一本就在此处更新),立贴。
    ExtJs combobox模糊匹配
    整理了一下eclipse 快捷键注释的一份文档
    中国省份按照拼音排序出现的问题以及临时解决方案
    JetBrains WebStorm 安装破解问题
    ExtJs Grid 删除,编辑,查看详细等超链接处理
    ExtJs Panel 滚动条设置
  • 原文地址:https://www.cnblogs.com/nasduc/p/5049788.html
Copyright © 2020-2023  润新知