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

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

3天内不再提示

CW32L052 DMA直接内存访问

CW32生态社区 来源: CW32生态社区 作者: CW32生态社区 2024-02-28 16:48 次阅读

BD网盘链接:

https://pan.baidu.com/s/10WHNgB_cicTP1SbdcI4AkQ?pwd=l1et
提取码:l1et

概述

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

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

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

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

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

框图

9ef6ad3b859e526939b1d50ce98b3cb53493144165354211_.jpg

特性

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

4 条独立DMA通道
3625f5c76a6b39256dd4c2e081854abe3493144165354211_.jpg

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

4种传输模式

硬件触发BULK传输模式、硬件触发BLOCK传输模式、软件触发BULK传输模式和软件触发BLOCK传输模式。
QQ图片20240228162240.jpg

BULK传输模式 :

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

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

BLOCK传输模式 :

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

• 硬件触发和软件触发:

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

51c1a122007e5f1b02dcbd819c8ef0123493144165354211_.jpg

可以产生DMA请求(DMA request),硬件触发启动DMA传输,
ab77011b6159b98f41225496ac5f6e2f3493144165354211_.jpg
而不支持硬件DMA的外设,只能配置为 软件触发启动DMA传输
7c1277aa377d43761f820c354134c99d3493144165354211_.jpg

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

DMA中断

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

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

数据宽度

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

数据块数量

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

数据传输优先级

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

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

从外设到内存

BD网盘链接:

https://pan.baidu.com/s/1RlVVPt72fJrnBBUEHf3iJQ?pwd=oklw
提取码:oklw

通过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
bb14a42ed7249c53164cee59f53eb0083493144165354211_.jpg

从内存到内存

BD网盘链接:

https://pan.baidu.com/s/1ScCk-UqHBjJA5PxwSqMhkg?pwd=4701
提取码:4701

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

核心代码

//单片机头文件

#include "main.h"

#include "cw32l052_lcd.h"

#include "cw32l052_dma.h"

//硬件外设

#include "delay.h"

#include "gpio.h"

//C库

#include < string.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

 

#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的数据
84d8e21c06ee1765cf4f14287e94e4733493144165354211_.jpg

从外设到外设

BD网盘链接:

https://pan.baidu.com/s/1fSyMPAapft2a_Vy_d3F9vw?pwd=dw6x
提取码:dw6x

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

核心代码

/*单片机头文件*/

#include "main.h"

/*硬件驱动*/

#include "delay.h"

#include "gpio.h"

#include "cw32l052_dma.h"

#include "cw32l052_spi.h"

/*C库*/

#include < string.h >

 

//硬件连接

//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);

}

审核编辑 黄宇

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

    关注

    68

    文章

    10863

    浏览量

    211747
  • 内存
    +关注

    关注

    8

    文章

    3025

    浏览量

    74042
  • dma
    dma
    +关注

    关注

    3

    文章

    561

    浏览量

    100583
  • CW32
    +关注

    关注

    1

    文章

    203

    浏览量

    640
收藏 人收藏

    评论

    相关推荐

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

    CW32L052支持DMA(Direct Memory Access),即直接内存访问,无需CPU干预,实现高速数据传输。
    的头像 发表于 02-27 11:36 984次阅读

    什么是DMA直接内存访问

    大家好,这是关于DMA的非常基本的问题。1)什么是DMA直接内存访问)和什么时候使用?2)它是如何提高CPU性能的?或如何独立工作,以节省
    发表于 01-25 10:45

    什么是直接内存访问DMA

    我对DMA感到困惑。DMA是一种允许微控制器直接访问另一个微控制器的存储器的通信协议吗?LED,如果不是,DMA是用来做什么的?谢谢:
    发表于 04-01 07:59

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

    2023年2月,武汉芯源半导体超低功耗家族再添新成员——32位M0+内核MCU CW32L052系列芯片。CW32L052 是基于 eFlash 的单芯片低功耗微控制器,集成了主频高达 48MHz
    发表于 02-21 14:02

    CW32L052微控制器数据手册

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

    CW32L052微处理器用户手册

    CW32L052 内核为 32 位的 ARM® Cortex®-M0+ 微处理器,最大寻址空间为 4GB。芯片内置的程序存储器、数据存储器、各外设及端口寄存器被统一编址在同一个 4GB 的线性
    发表于 09-14 06:08

    CW32L052CxTx PCB封装库

    CW32L052CxTx PCB封装库(PADS)
    发表于 09-14 08:01

    CW32L052CxTx元件库

    CW32L052CxTx元件库(PADS)
    发表于 09-14 08:24

    CW32L052 StartKit软件包

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

    CW32L052RxTx StartKit原理图分享

    CW32L052RxTx StartKit原理图
    发表于 09-15 07:35

    CW32L052R8T6 StartKit用户手册

    R8T6 StartKit 评估板需要搭配 CW-DAPLINK 调试器一起使用。CW32L052R8T6 StartKit 评估板带有 CW32L052 StartKit 软件包及 CW32
    发表于 09-15 06:04

    如何设置 DMA直接内存访问

    本应用笔记解释了使用 DMAC(直接存储器访问控制器)和 DTFR(DMA 触发因子寄存器)的示例。
    的头像 发表于 06-18 17:10 3947次阅读
    如何设置 <b class='flag-5'>DMA</b>(<b class='flag-5'>直接</b><b class='flag-5'>内存</b><b class='flag-5'>访问</b>)

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

    2023年2月,武汉芯源半导体超低功耗家族再添新成员——32位M0+内核MCUCW32L052系列芯片。CW32L052是基于eFlash的单芯片低功耗微控制器,集成了主频高达48MHz的ARM
    的头像 发表于 02-21 14:03 1020次阅读
    超低功耗家族再添新成员,武汉芯源半导体发布32位M0+内核MCU <b class='flag-5'>CW32L052</b>系列产品

    STM32L4直接访问内存模块(DMA)介绍

    电子发烧友网站提供《STM32L4直接访问内存模块(DMA)介绍.pdf》资料免费下载
    发表于 08-01 10:15 1次下载
    STM32<b class='flag-5'>L</b>4<b class='flag-5'>直接访问</b><b class='flag-5'>内存</b>模块(<b class='flag-5'>DMA</b>)介绍

    CW32L052 FLASH存储器

    CW32L052内部集成了64KB嵌入式FLASH供用户使用,可用来存储应用程序和用户数据。芯片支持对 FLASH 存储器的读、擦除和写操作,支持擦写保护和读保护。芯片内置 FLASH 编程所需的高压 BOOST 威廉希尔官方网站 ,无须额外提供编程电压。
    的头像 发表于 02-28 17:43 735次阅读
    <b class='flag-5'>CW32L052</b> FLASH存储器