0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看威廉希尔官方网站 视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

CW32L052单片机支持DMA实现高速数据传输

jf_qE49KoVBr8 来源:CW32生态社区 2024-02-27 11:36 次阅读

概述

CW32L052支持DMA(Direct Memory Access),即直接内存访问,无需CPU干预,实现高速数据传输。数据的传输可以发生在:

•外设和内存之间:例如ADC采集数据到内存,这种传输方式常见于需要将外设采集的数据快速传输到内存进行处理的应用。

•内存和内存之间:例如在两个不同的数组之间传输数据,或者在不同的内存块之间进行数据拷贝。

•外设和外设之间:例如从一个SPI主/从机传输数据到另一个SPI从/主机。

使用DMA能够有效减轻CPU的负担,特别是在大量数据需要高效传输的情况下,可以提高系统的整体性能。

框图

f8bbca9c-d51e-11ee-a297-92fbcf53809c.png

DMA功能框图

特性

使用DMA,最核心的就是配置要传输的数据,包括数据从哪里来,要到哪里去,传输的数据的单位是什么,要传多少数据,是一次传输还是连续传输等等。

4条独立DMA通道

f96ac70e-d51e-11ee-a297-92fbcf53809c.png

4个DMA通道的优先级和通道号绑定,通道号越小优先级越高,通道号越大优先级越低。

4种传输模式:

硬件触发BULK传输模式、硬件触发BLOCK传输模式、软件触发BULK传输模式和软件触发BLOCK传输模式。

硬件 BULK
BLOCK
软件 BULK
BLOCK

BULK传输模式:

适用于小数据块的传输,通常涉及大量的数据点,但每个数据点的大小较小。

与BLOCK模式不同,BULK模式下DMA会更频繁地启动新的传输,因为每个数据点通常被视为单独的传输单元,所以DMA控制器需要在每个数据点传输完成后需要重新配置或者启动DMA。在BULK传输模式下,传输过程不可被打断。

BLOCK传输模式:

适用于大数据块的高速传输,通常用于需要连续传输大量数据的情况。BLOCK模式下,DMA会将数据分成较大的块,并在传输时以这些块为单位进行操作。DMA控制器在一次配置后,连续传输多个数据块,而无需额外的干预或重新配置。每传输完成1个数据块后就要进行一次传输优先级的仲裁,允许CPU或者更高优先级的DMA通道访问当前DMA通道所占用的外设。

•硬件触发和软件触发:

要想通过DMA来传输数据,必须先给DMA控制器发送DMA请求。部分外设支持硬件触发启动DMA传输,如FLASH存储器、UART串口、TIM定时器ADC数模转换器等被配置为DMA通道的触发源时,

f97e9fb8-d51e-11ee-a297-92fbcf53809c.png

可以产生DMA请求(DMA request),硬件触发启动DMA传输,

fa145864-d51e-11ee-a297-92fbcf53809c.png

而不支持硬件DMA的外设,只能配置为软件触发启动DMA传输

fa24d4c8-d51e-11ee-a297-92fbcf53809c.png

虽然每个通道可以接收多个外设的请求,但是同一时间只能接收一个,不能同时接收多个。

•DMA中断

DMA通道在传输工程中可产生2个中断标志:传输错误中断标志和传输完成中断标志

不同 DMA 通道的中断各自独立,通过中断标志寄存器 DMA_ISR 可以获取各通道的中断标志。标志对应多个可能的产生原因,具体产生原因需查询 DMA_CSRy.STATUS 状态位,如下表所示

fa33a6d8-d51e-11ee-a297-92fbcf53809c.png

•数据宽度:

数据位宽可以设置为8bit、16bit和32bit,DMA通道的源地址和目的地址的位宽必须完全一致

•数据块数量:

传输的数据块数量可以设置为1 ~ 65535

•数据传输优先级

当CPU和DMA访问不同的外设时,数据的传输可以同时进行;

当CPU和DMA同时访问同一个外设时,CPU的优先级高于DMA。

从外设到内存

通过ADC转换完成标志触发(硬件触发)DMA方式实现外设到内存的DMA传输

核心代码:

#include "main.h" 
#include "delay.h" 
#include "gpio.h" 
#include "cw32l052_lcd.h" 
#include "cw32l052_adc.h" 
#include "cw32l052_dma.h" 
 
#define NUM0 0x070d  //段式LCD数字段码 
#define NUM1 0x0600 
#define NUM2 0x030e 
#define NUM3 0x070a 
#define NUM4 0x0603 
#define NUM5 0x050b 
#define NUM6 0x050f 
#define NUM7 0x0700 
#define NUM8 0x070f 
#define NUM9 0x070b 
 
void ADC_Configuration(void);      //ADC配置函数 
void DMA_Configuration(void);      //DMA配置函数 
void LCD_Configuration(void);      //LCD配置函数 
void LCD_Proc(uint16_t dispdata);  //LCD子程序函数 
 
/* 
**功能说明:
**ADC采集数据触发DMA,将采集到的数据(1.2V内核电压基准源)存储在内存value中,并显示在LCD屏上 
*/ 
int main(void) 
{ 
  LED_Init(); 
  LCD_Configuration(); 
  ADC_Configuration(); 
  DMA_Configuration(); 
  while (1) 
  { 
    LCD_Proc(value);  //显示采集到的ADC 
    PA15_TOG(); 
    Delay_ms(500); 
  } 
} 
 
void ADC_Configuration(void) 
{ 
  ADC_InitTypeDef   ADC_InitStruct = {0}; 
   
  __RCC_ADC_CLK_ENABLE(); 
  __RCC_GPIOA_CLK_ENABLE(); 
   
  PA00_ANALOG_ENABLE(); //PA00 (AIN0) 
   
  ADC_InitStruct.ADC_OpMode = ADC_SingleChOneMode;   //单通道单次转换模式 
  ADC_InitStruct.ADC_ClkDiv = ADC_Clk_Div128;       //PCLK 
  ADC_InitStruct.ADC_SampleTime = ADC_SampTime5Clk; //5个ADC时钟周期 
  ADC_InitStruct.ADC_VrefSel = ADC_Vref_VDDA;       //VDDA参考电压(3.3V) 
  ADC_InitStruct.ADC_InBufEn = ADC_BufEnable;       //开启跟随器 
  ADC_InitStruct.ADC_TsEn = ADC_TsDisable;           //内置温度传感器失能 
  ADC_InitStruct.ADC_DMASOCEn = ADC_DMASOCEnable;   //ADC转换完成触发DMA传输 
  ADC_InitStruct.ADC_Align = ADC_AlignRight;         //ADC转换结果右对齐 
  ADC_InitStruct.ADC_AccEn = ADC_AccDisable;         //转换结果累加不使能 
  ADC_Init(&ADC_InitStruct);                        //初始化ADC配置    
  CW_ADC->CR1_f.DISCARD = FALSE;                    //ADC转换结果保存策略配置:新数据覆盖未被读取的旧数据        
  CW_ADC->CR1_f.CHMUX = ADC_Vref1P2Input;           //待转换通道配置:1.2V内核电压基准源 
 
  ADC_ClearITPendingBit(ADC_IT_EOC); 
  ADC_ITConfig(ADC_IT_EOC, ENABLE); 
  ADC_EnableNvic(ADC_INT_PRIORITY); 
 
  ADC_Enable(); 
  ADC_SoftwareStartConvCmd(ENABLE);                  //开始转换 
} 
 
void ADC_IRQHandler(void) 
{ 
    /* USER CODE BEGIN */ 
  if(ADC_GetITStatus(ADC_IT_EOC) != RESET) 
  { 
      ADC_ClearITPendingBit(ADC_IT_EOC); 
      ADC_SoftwareStartConvCmd(ENABLE);              //开始转换 
  } 
    /* USER CODE END */ 
} 
 
void NVIC_Configuration(void) 
{ 
    __disable_irq(); 
 
    NVIC_ClearPendingIRQ(DMACH1_IRQn); 
 
    NVIC_EnableIRQ(DMACH1_IRQn); 
 
    __enable_irq(); 
} 
 
void DMA_Configuration(void) 
{ 
  DMA_InitTypeDef DMA_InitStruct = {0}; 
   
  __RCC_DMA_CLK_ENABLE(); 
   
  DMA_StructInit(&DMA_InitStruct);  
  DMA_InitStruct.DMA_Mode = DMA_MODE_BLOCK;     //BLOCK模式 
  DMA_InitStruct.DMA_TransferWidth = DMA_TRANSFER_WIDTH_32BIT; //数据宽度32bit 
  DMA_InitStruct.DMA_SrcInc = DMA_SrcAddress_Fix; //源地址固定 
  DMA_InitStruct.DMA_DstInc = DMA_DstAddress_Fix;  //目标地址固定 
  DMA_InitStruct.DMA_TransferCnt = 1;  //数据块数量1 
  DMA_InitStruct.DMA_SrcAddress = (uint32_t)&(CW_ADC->RESULT0);  //数据源地址 (外设) 
  DMA_InitStruct.DMA_DstAddress = (uint32_t)&value;   //传输目标地址   (内存) 
  DMA_InitStruct.TrigMode = DMA_HardTrig;  //硬件触发DMA传输 
  DMA_InitStruct.HardTrigSource = DMA_HardTrig_ADC_SINGLETRANSCOM;  //硬件触发源:ADC单次转换完成标志 
  DMA_Init(CW_DMACHANNEL1,&DMA_InitStruct); //DMA通道1 
  DMA_ClearITPendingBit(DMA_IT_ALL);  //清除DMA中断标志位 
  DMA_ITConfig(CW_DMACHANNEL1, DMA_IT_TC, ENABLE);   //使能DMA通道1中断 
  NVIC_Configuration(); 
  DMA_Cmd(CW_DMACHANNEL1, ENABLE); //启动DMA通道1进行传输 
} 
 
void DMACH1_IRQHandler(void) 
{ 
    /* USER CODE BEGIN */ 
  if( DMA_GetITStatus(DMA_IT_TC1) )  //DMA通道1传输完成标志 
    { 
        DMA_ClearITPendingBit(DMA_IT_TC1); 
 
        CW_DMACHANNEL1->CNT = 0x10001;     //REPEAT写1,传输数量为1                        
        DMA_Cmd(CW_DMACHANNEL1, ENABLE);  
    } 
    /* USER CODE END */ 
}

演示:ADC转换结果为1580左右,换算成电压:1580/4096*3.3=1.27V

fa4a338a-d51e-11ee-a297-92fbcf53809c.png

从内存到内存

通过软件触发DMA方式实现内存(FLASH)到内存(SRAM)的DMA传输

核心代码:

//单片机头文件
#include "main.h"
#include "cw32l052_lcd.h"
#include "cw32l052_dma.h"
//硬件外设
#include "delay.h"
#include "gpio.h"
//C库
#include 


#define NUM0 0x070d  //段式LCD数字段码
#define NUM1 0x0600
#define NUM2 0x030e
#define NUM3 0x070a
#define NUM4 0x0603
#define NUM5 0x050b
#define NUM6 0x050f
#define NUM7 0x0700
#define NUM8 0x070f
#define NUM9 0x070b


#define DATASIZE 10


uint16_t const srcBuf[DATASIZE] =   //源内存(FLASH)数据
{
  9999,8888,7777,6666,5555,
  4444,3333,2222,1111,0
};


uint16_t dstBuf[DATASIZE]={0};      //目标内存(SRAM)数据


void DMA_Configuration(void);      //DMA配置函数
void LCD_Configuration(void);      //LCD配置函数
void LCD_Proc(uint16_t dispdata);  //LCD子程序函数


uint32_t value=0;  //ADC数值


/*
**功能说明:
**将srcBuf数组中的数据通过DMA传送到dstBuf数组中,
**srcBuf数组中的数据通过const关键词存储到FLASH中,
**dstBuf数组存储在SRAM程序运行过程中
**传输完成后比较两数组内容,相同则打开LED1和LED1,LCD上循环显示dstBuf数据;
**不同则进入死循环,两指示灯闪烁
*/
int main(void)
{
  LED_Init();
  LCD_Configuration();
  DMA_Configuration();
  DMA_SWTrigCmd(CW_DMACHANNEL1);   //使能通道1软件触发
  while(DMA_GetFlagStatus(CW_DMACHANNEL1)!=DMA_CHANNEL_STATUS_TRANSCOMPLETE); //等待传输完成
  if(memcmp(srcBuf,dstBuf,DATASIZE)==0)  //如果srcBuf和dstBuf相同
  {
      LED1_ON(); //指示灯
      LED2_ON();
      for(int i=0;i<10;i++)  //LCD屏显示dstBuf数据
      {
        LCD_Proc(dstBuf[i]);
        Delay_ms(500);
      }
  }
  else  //如果不相同
  {
    while(1)  //进入while死循环
    {
      PA15_TOG();  //指示灯
      PC10_TOG();
      Delay_ms(500);
    }
  }
  
  while (1)
  {
    
  }
}


void DMA_Configuration(void)
{
  DMA_InitTypeDef DMA_InitStruct = {0};
  
  __RCC_DMA_CLK_ENABLE();
  
  DMA_StructInit(&DMA_InitStruct); 
  DMA_InitStruct.DMA_Mode = DMA_MODE_BLOCK;     //BLOCK模式
  DMA_InitStruct.DMA_TransferWidth = DMA_TRANSFER_WIDTH_16BIT; //数据宽度16bit
  DMA_InitStruct.DMA_SrcInc = DMA_SrcAddress_Increase; //源地址固定
  DMA_InitStruct.DMA_DstInc = DMA_DstAddress_Increase;  //目标地址递增
  DMA_InitStruct.DMA_TransferCnt = DATASIZE;  //数据块数量
  DMA_InitStruct.DMA_SrcAddress = (uint32_t)&srcBuf[0];  //数据源地址 (内存)
  DMA_InitStruct.DMA_DstAddress = (uint32_t)&dstBuf[0];   //传输目标地址 (内存)
  DMA_InitStruct.TrigMode = DMA_SWTrig;  //软件触发DMA传输


  DMA_Init(CW_DMACHANNEL1,&DMA_InitStruct); //DMA通道1
  DMA_Cmd(CW_DMACHANNEL1, ENABLE); //启动DMA通道1进行传输
}

演示:LCD屏上显示通过DMA传输的dstBuf的数据

fa6d0a04-d51e-11ee-a297-92fbcf53809c.png

从外设到外设

通过硬件触发DMA方式实现外设(SPI)到外设(SPI)的DMA传输

核心代码:

/*单片机头文件*/
#include "main.h"
/*硬件驱动*/
#include "delay.h"
#include "gpio.h"
#include "cw32l052_dma.h"
#include "cw32l052_spi.h"
/*C库*/
#include 


//硬件连接
//SPIY_SCK  (PA10) -- SPIX_SCK  (PB13)
//SPIY_MISO (PA11) -- SPIX_MISO (PB14)
//SPIY_MOSI (PA12) -- SPIX_MOSI (PB15)


//SPI2相关定义(Master)
#define    SPIX                     CW_SPI2               
#define   SPIX_GPIO          CW_GPIOB
#define    SPIX_SCK_PIN             GPIO_PIN_13
#define   SPIX_MISO_PIN            GPIO_PIN_14
#define    SPIX_MOSI_PIN            GPIO_PIN_15
#define    SPIX_AF_SCK              PB13_AFx_SPI2SCK()
#define    SPIX_AF_MISO             PB14_AFx_SPI2MISO()
#define    SPIX_AF_MOSI             PB15_AFx_SPI2MOSI()
#define    SPIX_RX_DMACHANNEL       CW_DMACHANNEL1
#define    SPIX_TX_DMACHANNEL       CW_DMACHANNEL2  
#define     SPIX_DMA_RXTRIGSOURCE    DMA_HardTrig_SPI2_RXBufferNE
#define     SPIX_DMA_TXTRIGSOURCE    DMA_HardTrig_SPI2_TXBufferE


//SPI1相关定义(Slave)
#define    SPIY                     CW_SPI1
#define   SPIY_GPIO          CW_GPIOA
#define    SPIY_SCK_PIN             GPIO_PIN_10
#define    SPIY_MISO_PIN            GPIO_PIN_11
#define    SPIY_MOSI_PIN            GPIO_PIN_12
#define    SPIY_AF_SCK              PA10_AFx_SPI1SCK()
#define    SPIY_AF_MISO             PA11_AFx_SPI1MISO()
#define    SPIY_AF_MOSI             PA12_AFx_SPI1MOSI()


//数组长度
#define   BUFFERSIZE                 ARRAY_SZ(TxBuffer1)


//发送内容1
uint8_t TxBuffer1[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
                       0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
                       0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
                       0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C,
                       0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23
                      };
//发送内容2
uint8_t TxBuffer2[] = {0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
                       0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E,
                       0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75,
                       0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C,
                       0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83
                      };
                    
uint8_t RxBuffer1[BUFFERSIZE];  //接收数组1
uint8_t RxBuffer2[BUFFERSIZE];  //接收数组2
uint8_t TxCounter = 0;  //发送计数
uint8_t RxCounter = 0;  //接收计数
  
uint8_t TransferStatus1 = 1;  //DMA传输状态标志1
uint8_t TransferStatus2 = 1;  //DMA传输状态标志2
                      
void DMA_Configuration(void);      //DMA配置函数
void SPI_Configuration(void);      //SPI配置函数
void SPI_GPIO_Configuration(void); //SPI相关GPIO口配置
  
/*
**功能说明:
**主机SPIY发送TxBuffer1中的数据,从机SPIX通过DMA接收数据并存储到RxBuffer1
**主机SPIY发送无效数据,启动SPI通信,同时SPIX从机通过DMA发送TxBuffer2中的数据,SIPY接收数据并存储到RxBuffer2
**单独比较TxBuffer1与RxBuffer1、TxBuffer2与RxBuffer2中的内容,比较结果通过LED灯指示
*/
int main(void)
{
  LED_Init();               //初始化LED指示灯
  SPI_GPIO_Configuration(); //配置PI相关GPIO口
  DMA_Configuration();      //配置DMA传输
  SPI_Configuration();      //配置SPI传输
  SPI_DMACmd(SPIX, SPI_DMAReq_Rx, ENABLE); //使能SPIX DMA RX
  SPI_NSSInternalSoftwareConfig(SPIX, SPI_NSSInternalSoft_Reset);//位选CS选中从机SPIX,起始信号
  while(TxCounter < BUFFERSIZE)
  {
    while(SPI_GetFlagStatus(SPIY,SPI_FLAG_TXE) == RESET);//等待发送缓冲空(为空后硬件自动置1)
    SPI_SendData(SPIY,TxBuffer1[TxCounter++]); //发送TxBuffer1中的数据,通过数据寄存器DR把数据填充到发送缓冲区中
  }
  while(DMA_GetFlagStatus(SPIX_RX_DMACHANNEL) != DMA_CHANNEL_STATUS_TRANSCOMPLETE);//等待DMA接收完成


  SPI_NSSInternalSoftwareConfig(SPIX, SPI_NSSInternalSoft_Set); //释放从机SPIX,结束信号
  TransferStatus1 = memcmp(TxBuffer1, RxBuffer1, BUFFERSIZE); //对比两数组数据
  if(TransferStatus1==0)  //如果数据相同
  {
    LED1_ON();  //LED1指示
  }
  else
  {
    LED1_OFF();
  }
  
  TxCounter = 0;
  SPI_ReceiveData(SPIY);//读DR以清除RXNE(接收非空)标志位
  SPI_DMACmd(SPIX, SPI_DMAReq_Rx, DISABLE);//失能SPIX DMA RX
  SPI_FlushSendBuff(SPIX);//清空发送缓冲区和移位寄存器
  SPI_DMACmd(SPIX, SPI_DMAReq_Tx, ENABLE);//使能SPIX DMA TX
  SPI_NSSInternalSoftwareConfig(SPIX, SPI_NSSInternalSoft_Reset);
  while(TxCounter < BUFFERSIZE)
  {      
    while(SPI_GetFlagStatus(SPIY, SPI_FLAG_TXE) == RESET){;} //主机发送数据以启动SPI通信
    SPI_SendData(SPIY, TxBuffer1[TxCounter++]);
      
    while(SPI_GetFlagStatus(SPIY, SPI_FLAG_RXNE) == RESET){;}
      RxBuffer2[RxCounter++] = SPI_ReceiveData(SPIY);  //获取接收缓冲区中的内容  
  }
  while(SPI_GetFlagStatus(SPIY,SPI_FLAG_BUSY) == SET); //检查数据是否已经全部通过SPI发送完毕  
  SPI_NSSInternalSoftwareConfig(SPIX, SPI_NSSInternalSoft_Set); //释放
  TransferStatus2 = memcmp(TxBuffer2, RxBuffer2, BUFFERSIZE);  //检查
  if(TransferStatus2 == 0)
  {
    LED2_ON();
  }
  else
  {
    LED2_OFF();
  }
  while (1)
  {
    
  }
}


void SPI_GPIO_Configuration(void)
{
    GPIO_InitTypeDef GPIO_InitStructure = {0};
    
    //打开GPIO时钟
    __RCC_GPIOA_CLK_ENABLE();
    __RCC_GPIOB_CLK_ENABLE();


    //SPI SCK MOSI MISO 复用
    SPIY_AF_SCK;
    SPIY_AF_MISO;
    SPIY_AF_MOSI;
    SPIX_AF_SCK;
    SPIX_AF_MISO;
    SPIX_AF_MOSI;


    //推挽输出
    GPIO_InitStructure.Pins = SPIY_SCK_PIN | SPIY_MOSI_PIN;
    GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_Init(SPIY_GPIO, &GPIO_InitStructure);


    GPIO_InitStructure.Pins = SPIX_MISO_PIN;
    GPIO_Init(SPIX_GPIO, &GPIO_InitStructure);


    //浮空输入
    GPIO_InitStructure.Pins = SPIX_SCK_PIN | SPIX_MOSI_PIN;
    GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
    GPIO_Init(SPIX_GPIO, &GPIO_InitStructure);


    GPIO_InitStructure.Pins = SPIY_MISO_PIN;
    GPIO_Init(SPIY_GPIO, &GPIO_InitStructure);
}


void SPI_Configuration(void)
{
  SPI_InitTypeDef SPI_InitStructure = {0};
  
  __RCC_SPI1_CLK_ENABLE();
  __RCC_SPI2_CLK_ENABLE();
  
  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //双线全双工模式
  SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //主机模式
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //数据位宽8bit
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;  //时钟极性
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;//时钟相位,奇数边缘采样
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //配置NSS引脚(片选信号线)的使用模式,软件控制
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8; //波特率:PCLK8分频
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //MSB先行模式
  SPI_InitStructure.SPI_Speed = SPI_Speed_Low; //低速
  SPI_Init(SPIY,&SPI_InitStructure);
  
  SPI_InitStructure.SPI_Mode = SPI_Mode_Slave; //从机模式
  SPI_Init(SPIX,&SPI_InitStructure);
  
  SPI_Cmd(SPIX,ENABLE);
  SPI_Cmd(SPIY,ENABLE);
}


void DMA_Configuration(void)
{
  DMA_InitTypeDef DMA_InitStructure = {0};
  
  __RCC_DMA_CLK_ENABLE();
  
  //DMA TX
  DMA_InitStructure.DMA_Mode = DMA_MODE_BLOCK; //BLOCK模式
  DMA_InitStructure.DMA_TransferWidth = DMA_TRANSFER_WIDTH_8BIT;
  DMA_InitStructure.DMA_SrcInc = DMA_SrcAddress_Increase;
  DMA_InitStructure.DMA_DstInc = DMA_DstAddress_Fix;
  DMA_InitStructure.TrigMode = DMA_HardTrig;
  DMA_InitStructure.HardTrigSource = SPIX_DMA_TXTRIGSOURCE;
  DMA_InitStructure.DMA_TransferCnt = BUFFERSIZE;
  DMA_InitStructure.DMA_SrcAddress = (uint32_t)&TxBuffer2[0];
  DMA_InitStructure.DMA_DstAddress = (uint32_t)&SPIX->DR; //数据寄存器
  DMA_Init(SPIX_TX_DMACHANNEL,&DMA_InitStructure);
  DMA_Cmd(SPIX_TX_DMACHANNEL,ENABLE);
  
  //DMA RX
  DMA_InitStructure.DMA_Mode = DMA_MODE_BLOCK;
  DMA_InitStructure.DMA_TransferWidth = DMA_TRANSFER_WIDTH_8BIT;
  DMA_InitStructure.DMA_SrcInc = DMA_SrcAddress_Fix;
  DMA_InitStructure.DMA_DstInc = DMA_DstAddress_Increase;
  DMA_InitStructure.TrigMode = DMA_HardTrig;
  DMA_InitStructure.HardTrigSource = SPIX_DMA_RXTRIGSOURCE;
  DMA_InitStructure.DMA_TransferCnt = BUFFERSIZE;
  DMA_InitStructure.DMA_SrcAddress = (uint32_t)&SPIX->DR;
  DMA_InitStructure.DMA_DstAddress = (uint32_t)&RxBuffer1[0];
  DMA_Init(SPIX_RX_DMACHANNEL,&DMA_InitStructure);
  DMA_Cmd(SPIX_RX_DMACHANNEL,ENABLE);
}




审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 单片机
    +关注

    关注

    6035

    文章

    44553

    浏览量

    634718
  • 数据传输
    +关注

    关注

    9

    文章

    1882

    浏览量

    64563
  • LCD屏
    +关注

    关注

    0

    文章

    122

    浏览量

    15422
  • dma
    dma
    +关注

    关注

    3

    文章

    560

    浏览量

    100553
  • 推挽输出
    +关注

    关注

    0

    文章

    42

    浏览量

    6513

原文标题:CW32L052单片机DMA直接内存访问

文章出处:【微信号:武汉芯源半导体,微信公众号:武汉芯源半导体】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    CW32L052 DMA直接内存访问

    CW32L052支持DMA(Direct Memory Access),即直接内存访问,无需CPU干预,实现高速
    的头像 发表于 02-28 16:48 934次阅读
    <b class='flag-5'>CW32L052</b> <b class='flag-5'>DMA</b>直接内存访问

    ADXRS453Z的芯片支持使用STM32单片机DMA数据传输功能吗?

    ADXRS453Z的芯片支持使用STM32单片机DMA数据传输功能吗?如果,不能,考虑到我们的数据传输还是挺多的,那么常规的SPI通信方式
    发表于 12-29 07:47

    单片机红外数据传输

    基于51单片机的红外数据传输系统的设计主要任务:写设计要求、报告,设计各电路控制模块、用PROTUS仿真、搭建电路模块、写出程序控制流程、写出源码、调试达到预期目标。最终目标:利用单片机实现
    发表于 07-12 23:54

    请问ADXRS453Z的芯片支持使用STM32单片机DMA数据传输功能吗?

    ADXRS453Z的芯片支持使用STM32单片机DMA数据传输功能吗?如果,不能,考虑到我们的数据传输还是挺多的,那么常规的SPI通信方式
    发表于 08-10 08:13

    超低功耗家族再添新成员,武汉芯源半导体发布32位M0+内核MCU CW32L052系列产品

    的 ARM® Cortex®-M0+ 内核、高速嵌入式存储器(最大64K字节FLASH、最大8K字节RAM),支持最多55路I/O接口。CW32L052内部框图外设包括:1路12位ADC,3路UART
    发表于 02-21 14:02

    DMA进行数据传输和CPU进行数据传输的疑问

    求大佬解答,本人正在学习STM32单片机DMA直接数据存储部分的内容 看了DMA简介后,也上手过实例代码,但是没有实际的项目经验,所以有以下疑问:
    发表于 05-25 17:18

    CW32L052微控制器数据手册

    CW32L052 是基于 eFlash 的单芯片低功耗微控制器,集成了主频高达 48MHz 的 ARM® Cortex®-M0+ 内核、高速嵌入式存储器(多至 64K 字节 FLASH 和多至 8K
    发表于 09-14 06:28

    CW32L052 StartKit软件包

    CW32L052 StartKit 软件包
    发表于 09-15 06:13

    单片机网络数据传输

    单片机网络数据传输器是由单片机以及有关电子电路组成的,可以通过互联网络来实现远程监控的一种传输装置。用户有了
    发表于 06-29 18:21 2007次阅读

    TCP/IP协议单片机在网络通信中的数据传输威廉希尔官方网站

    介绍了嵌入式TCP/IP协议单片机在网络通信中的数据传输威廉希尔官方网站 。将TCP/IP协议嵌入式单片机中,借助网卡芯片CS8900实现单片机在局域网
    发表于 04-16 22:04 4429次阅读
    TCP/IP协议<b class='flag-5'>单片机</b>在网络通信中的<b class='flag-5'>数据传输</b>威廉希尔官方网站

    DMA数据传输(源代码分享)

    手头项目也需要加入DMA数据传输,以最大限度地提升CPU效率,于是测试了一下XMEGA的DMA模块,把一块内存中的数据DMA
    的头像 发表于 04-27 09:22 9147次阅读

    DMA数据传输在SPEAR300实现高速串口驱动设计

    DMA数据传输无需CPU的参与,是一种更加高效的数据传输方式。现有的DMA数据传输方案都是基于DMA
    发表于 04-04 12:23 1616次阅读
    <b class='flag-5'>DMA</b><b class='flag-5'>数据传输</b>在SPEAR300<b class='flag-5'>实现</b><b class='flag-5'>高速</b>串口驱动设计

    AT89C52单片机与PC之间的无线数据传输设计

    和专用无线传输芯片实现简单的短距离无线传输方案,硬件部分包括单片机端和PC端,实现
    发表于 08-16 17:36 5361次阅读
    AT89C52<b class='flag-5'>单片机</b>与PC<b class='flag-5'>机</b>之间的无线<b class='flag-5'>数据传输</b>设计

    超低功耗家族再添新成员,武汉芯源半导体发布32位M0+内核MCU CW32L052系列产品

    ®Cortex®-M0+内核、高速嵌入式存储器(最大64K字节FLASH、最大8K字节RAM),支持最多55路I/O接口。CW32L052内部框图外设包括:1路12位ADC,3路UART(支持
    的头像 发表于 02-21 14:03 1016次阅读
    超低功耗家族再添新成员,武汉芯源半导体发布32位M0+内核MCU <b class='flag-5'>CW32L052</b>系列产品

    CW32L052 FLASH存储器

    CW32L052内部集成了64KB嵌入式FLASH供用户使用,可用来存储应用程序和用户数据。芯片支持对 FLASH 存储器的读、擦除和写操作,支持擦写保护和读保护。芯片内置 FLASH
    的头像 发表于 02-28 17:43 727次阅读
    <b class='flag-5'>CW32L052</b> FLASH存储器