0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

CW32L052 DMA直接內(nèi)存訪問

CW32生態(tài)社區(qū) ? 來(lái)源: CW32生態(tài)社區(qū) ? 作者: CW32生態(tài)社區(qū) ? 2024-02-28 16:48 ? 次閱讀

BD網(wǎng)盤鏈接:

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

概述

CW32L052支持DMA(Direct Memory Access),即直接內(nèi)存訪問,無(wú)需CPU干預(yù),實(shí)現(xiàn)高速數(shù)據(jù)傳輸。數(shù)據(jù)的傳輸可以發(fā)生在:

? 外設(shè)和內(nèi)存之間 :例如ADC采集數(shù)據(jù)到內(nèi)存,這種傳輸方式常見于需要將外設(shè)采集的數(shù)據(jù)快速傳輸?shù)絻?nèi)存進(jìn)行處理的應(yīng)用。

? 內(nèi)存和內(nèi)存之間 :例如在兩個(gè)不同的數(shù)組之間傳輸數(shù)據(jù),或者在不同的內(nèi)存塊之間進(jìn)行數(shù)據(jù)拷貝。

? 外設(shè)和外設(shè)之間 :例如從一個(gè)SPI主/從機(jī)傳輸數(shù)據(jù)到另一個(gè)SPI從/主機(jī)。

使用DMA能夠有效減輕CPU的負(fù)擔(dān),特別是在大量數(shù)據(jù)需要高效傳輸?shù)那闆r下,可以提高系統(tǒng)的整體性能。

框圖

9ef6ad3b859e526939b1d50ce98b3cb53493144165354211_.jpg

特性

使用DMA,最核心的就是配置要傳輸?shù)臄?shù)據(jù),包括數(shù)據(jù)從哪里來(lái),要到哪里去,傳輸?shù)臄?shù)據(jù)的單位是什么,要傳多少數(shù)據(jù),是一次傳輸還是連續(xù)傳輸?shù)鹊取?/p>

4 條獨(dú)立DMA通道
3625f5c76a6b39256dd4c2e081854abe3493144165354211_.jpg

4個(gè)DMA通道的優(yōu)先級(jí)和通道號(hào)綁定,通道號(hào)越小優(yōu)先級(jí)越高,通道號(hào)越大優(yōu)先級(jí)越低。

4種傳輸模式

硬件觸發(fā)BULK傳輸模式、硬件觸發(fā)BLOCK傳輸模式、軟件觸發(fā)BULK傳輸模式和軟件觸發(fā)BLOCK傳輸模式。
QQ圖片20240228162240.jpg

BULK傳輸模式 :

適用于小數(shù)據(jù)塊的傳輸,通常涉及大量的數(shù)據(jù)點(diǎn),但每個(gè)數(shù)據(jù)點(diǎn)的大小較小。

與BLOCK模式不同,BULK模式下DMA會(huì)更頻繁地啟動(dòng)新的傳輸,因?yàn)槊總€(gè)數(shù)據(jù)點(diǎn)通常被視為單獨(dú)的傳輸單元,所以DMA控制器需要在每個(gè)數(shù)據(jù)點(diǎn)傳輸完成后需要重新配置或者啟動(dòng)DMA。在BULK傳輸模式下,傳輸過程不可被打斷。

BLOCK傳輸模式 :

適用于大數(shù)據(jù)塊的高速傳輸,通常用于需要連續(xù)傳輸大量數(shù)據(jù)的情況。BLOCK模式下,DMA會(huì)將數(shù)據(jù)分成較大的塊,并在傳輸時(shí)以這些塊為單位進(jìn)行操作。DMA控制器在一次配置后,連續(xù)傳輸多個(gè)數(shù)據(jù)塊,而無(wú)需額外的干預(yù)或重新配置。每傳輸完成1個(gè)數(shù)據(jù)塊后就要進(jìn)行一次傳輸優(yōu)先級(jí)的仲裁,允許CPU或者更高優(yōu)先級(jí)的DMA通道訪問當(dāng)前DMA通道所占用的外設(shè)。

? 硬件觸發(fā)和軟件觸發(fā):

要想通過DMA來(lái)傳輸數(shù)據(jù),必須先給DMA控制器發(fā)送DMA請(qǐng)求。部分外設(shè)支持 硬件觸發(fā)啟動(dòng)DMA傳輸 ,如FLASH存儲(chǔ)器、UART串口、TIM定時(shí)器、ADC數(shù)模轉(zhuǎn)換器等被配置為DMA通道的觸發(fā)源時(shí),

51c1a122007e5f1b02dcbd819c8ef0123493144165354211_.jpg

可以產(chǎn)生DMA請(qǐng)求(DMA request),硬件觸發(fā)啟動(dòng)DMA傳輸,
ab77011b6159b98f41225496ac5f6e2f3493144165354211_.jpg
而不支持硬件DMA的外設(shè),只能配置為 軟件觸發(fā)啟動(dòng)DMA傳輸 。
7c1277aa377d43761f820c354134c99d3493144165354211_.jpg

雖然每個(gè)通道可以接收多個(gè)外設(shè)的請(qǐng)求,但是同一時(shí)間只能接收一個(gè),不能同時(shí)接收多個(gè)。

? DMA中斷

DMA通道在傳輸工程中可產(chǎn)生2個(gè)中斷標(biāo)志:傳輸錯(cuò)誤中斷標(biāo)志和傳輸完成中斷標(biāo)志

不同 DMA 通道的中斷各自獨(dú)立,通過中斷標(biāo)志寄存器 DMA_ISR 可以獲取各通道的中斷標(biāo)志。標(biāo)志對(duì)應(yīng)多個(gè)可能的產(chǎn)生原因,具體產(chǎn)生原因需查詢 DMA_CSRy.STATUS 狀態(tài)位,如下表所示
60bd017b9abd57ca9eabff17f4627fb63493144165354211_.jpg

? 數(shù)據(jù)寬度

數(shù)據(jù)位寬可以設(shè)置為8bit、16bit和32bit,DMA通道的源地址和目的地址的位寬必須完全一致

? 數(shù)據(jù)塊數(shù)量

傳輸?shù)臄?shù)據(jù)塊數(shù)量可以設(shè)置為1 ~ 65535

? 數(shù)據(jù)傳輸優(yōu)先級(jí)

當(dāng)CPU和DMA訪問不同的外設(shè)時(shí),數(shù)據(jù)的傳輸可以同時(shí)進(jìn)行;

當(dāng)CPU和DMA同時(shí)訪問同一個(gè)外設(shè)時(shí),CPU的優(yōu)先級(jí)高于DMA。

從外設(shè)到內(nèi)存

BD網(wǎng)盤鏈接:

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

通過ADC轉(zhuǎn)換完成標(biāo)志觸發(fā)(硬件觸發(fā))DMA方式實(shí)現(xiàn)外設(shè)到內(nèi)存的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數(shù)字段碼
#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配置函數(shù)
void DMA_Configuration(void);      //DMA配置函數(shù)
void LCD_Configuration(void);      //LCD配置函數(shù)
void LCD_Proc(uint16_t dispdata);  //LCD子程序函數(shù)

/*
**功能說(shuō)明:
**ADC采集數(shù)據(jù)觸發(fā)DMA,將采集到的數(shù)據(jù)(1.2V內(nèi)核電壓基準(zhǔn)源)存儲(chǔ)在內(nèi)存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;   //單通道單次轉(zhuǎn)換模式
  ADC_InitStruct.ADC_ClkDiv = ADC_Clk_Div128;       //PCLK
  ADC_InitStruct.ADC_SampleTime = ADC_SampTime5Clk; //5個(gè)ADC時(shí)鐘周期
  ADC_InitStruct.ADC_VrefSel = ADC_Vref_VDDA;       //VDDA參考電壓(3.3V)
  ADC_InitStruct.ADC_InBufEn = ADC_BufEnable;       //開啟跟隨器
  ADC_InitStruct.ADC_TsEn = ADC_TsDisable;           //內(nèi)置溫度傳感器失能
  ADC_InitStruct.ADC_DMASOCEn = ADC_DMASOCEnable;   //ADC轉(zhuǎn)換完成觸發(fā)DMA傳輸
  ADC_InitStruct.ADC_Align = ADC_AlignRight;         //ADC轉(zhuǎn)換結(jié)果右對(duì)齊
  ADC_InitStruct.ADC_AccEn = ADC_AccDisable;         //轉(zhuǎn)換結(jié)果累加不使能
  ADC_Init(&ADC_InitStruct);                        //初始化ADC配置
  CW_ADC- >CR1_f.DISCARD = FALSE;                    //ADC轉(zhuǎn)換結(jié)果保存策略配置:新數(shù)據(jù)覆蓋未被讀取的舊數(shù)據(jù)
  CW_ADC- >CR1_f.CHMUX = ADC_Vref1P2Input;           //待轉(zhuǎn)換通道配置:1.2V內(nèi)核電壓基準(zhǔn)源

  ADC_ClearITPendingBit(ADC_IT_EOC);
  ADC_ITConfig(ADC_IT_EOC, ENABLE);
  ADC_EnableNvic(ADC_INT_PRIORITY);

  ADC_Enable();
  ADC_SoftwareStartConvCmd(ENABLE);                  //開始轉(zhuǎn)換
}

void ADC_IRQHandler(void)
{
    /* USER CODE BEGIN */
  if(ADC_GetITStatus(ADC_IT_EOC) != RESET)
  {
      ADC_ClearITPendingBit(ADC_IT_EOC);
      ADC_SoftwareStartConvCmd(ENABLE);              //開始轉(zhuǎn)換
  }
    /* 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; //數(shù)據(jù)寬度32bit
  DMA_InitStruct.DMA_SrcInc = DMA_SrcAddress_Fix; //源地址固定
  DMA_InitStruct.DMA_DstInc = DMA_DstAddress_Fix;  //目標(biāo)地址固定
  DMA_InitStruct.DMA_TransferCnt = 1;  //數(shù)據(jù)塊數(shù)量1
  DMA_InitStruct.DMA_SrcAddress = (uint32_t)&(CW_ADC- >RESULT0);  //數(shù)據(jù)源地址 (外設(shè))
  DMA_InitStruct.DMA_DstAddress = (uint32_t)&value;   //傳輸目標(biāo)地址   (內(nèi)存)
  DMA_InitStruct.TrigMode = DMA_HardTrig;  //硬件觸發(fā)DMA傳輸
  DMA_InitStruct.HardTrigSource = DMA_HardTrig_ADC_SINGLETRANSCOM;  //硬件觸發(fā)源:ADC單次轉(zhuǎn)換完成標(biāo)志
  DMA_Init(CW_DMACHANNEL1,&DMA_InitStruct); //DMA通道1
  DMA_ClearITPendingBit(DMA_IT_ALL);  //清除DMA中斷標(biāo)志位
  DMA_ITConfig(CW_DMACHANNEL1, DMA_IT_TC, ENABLE);   //使能DMA通道1中斷
  NVIC_Configuration();
  DMA_Cmd(CW_DMACHANNEL1, ENABLE); //啟動(dòng)DMA通道1進(jìn)行傳輸
}

void DMACH1_IRQHandler(void)
{
    /* USER CODE BEGIN */
  if( DMA_GetITStatus(DMA_IT_TC1) )  //DMA通道1傳輸完成標(biāo)志
    {
        DMA_ClearITPendingBit(DMA_IT_TC1);

        CW_DMACHANNEL1- >CNT = 0x10001;     //REPEAT寫1,傳輸數(shù)量為1
        DMA_Cmd(CW_DMACHANNEL1, ENABLE);
    }
    /* USER CODE END */
}

演示:ADC轉(zhuǎn)換結(jié)果為1580左右,換算成電壓:1580/4096*3.3=1.27V
bb14a42ed7249c53164cee59f53eb0083493144165354211_.jpg

從內(nèi)存到內(nèi)存

BD網(wǎng)盤鏈接:

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

通過軟件觸發(fā)DMA方式實(shí)現(xiàn)內(nèi)存(FLASH)到內(nèi)存(SRAM)的DMA傳輸

核心代碼

//單片機(jī)頭文件

#include "main.h"

#include "cw32l052_lcd.h"

#include "cw32l052_dma.h"

//硬件外設(shè)

#include "delay.h"

#include "gpio.h"

//C庫(kù)

#include < string.h >

 

#define NUM0 0x070d  //段式LCD數(shù)字段碼

#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] =   //源內(nèi)存(FLASH)數(shù)據(jù)

{

  9999,8888,7777,6666,5555,

  4444,3333,2222,1111,0

};

 

uint16_t dstBuf[DATASIZE]={0};      //目標(biāo)內(nèi)存(SRAM)數(shù)據(jù)

 

void DMA_Configuration(void);      //DMA配置函數(shù)

void LCD_Configuration(void);      //LCD配置函數(shù)

void LCD_Proc(uint16_t dispdata);  //LCD子程序函數(shù)

 

uint32_t value=0;  //ADC數(shù)值

 

/*

**功能說(shuō)明:

**將srcBuf數(shù)組中的數(shù)據(jù)通過DMA傳送到dstBuf數(shù)組中,

**srcBuf數(shù)組中的數(shù)據(jù)通過const關(guān)鍵詞存儲(chǔ)到FLASH中,

**dstBuf數(shù)組存儲(chǔ)在SRAM程序運(yùn)行過程中

**傳輸完成后比較兩數(shù)組內(nèi)容,相同則打開LED1和LED1,LCD上循環(huán)顯示dstBuf數(shù)據(jù);

**不同則進(jìn)入死循環(huán),兩指示燈閃爍

*/

int main(void)

{

  LED_Init();

  LCD_Configuration();

  DMA_Configuration();

  DMA_SWTrigCmd(CW_DMACHANNEL1);   //使能通道1軟件觸發(fā)

  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數(shù)據(jù)

      {

        LCD_Proc(dstBuf[i]);

        Delay_ms(500);

      }

  }

  else  //如果不相同

  {

    while(1)  //進(jìn)入while死循環(huán)

    {

      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; //數(shù)據(jù)寬度16bit

  DMA_InitStruct.DMA_SrcInc = DMA_SrcAddress_Increase; //源地址固定

  DMA_InitStruct.DMA_DstInc = DMA_DstAddress_Increase;  //目標(biāo)地址遞增

  DMA_InitStruct.DMA_TransferCnt = DATASIZE;  //數(shù)據(jù)塊數(shù)量

  DMA_InitStruct.DMA_SrcAddress = (uint32_t)&srcBuf[0];  //數(shù)據(jù)源地址 (內(nèi)存)

  DMA_InitStruct.DMA_DstAddress = (uint32_t)&dstBuf[0];   //傳輸目標(biāo)地址 (內(nèi)存)

  DMA_InitStruct.TrigMode = DMA_SWTrig;  //軟件觸發(fā)DMA傳輸

 

  DMA_Init(CW_DMACHANNEL1,&DMA_InitStruct); //DMA通道1

  DMA_Cmd(CW_DMACHANNEL1, ENABLE); //啟動(dòng)DMA通道1進(jìn)行傳輸

}

演示:LCD屏上顯示通過DMA傳輸?shù)膁stBuf的數(shù)據(jù)
84d8e21c06ee1765cf4f14287e94e4733493144165354211_.jpg

從外設(shè)到外設(shè)

BD網(wǎng)盤鏈接:

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

通過硬件觸發(fā)DMA方式實(shí)現(xiàn)外設(shè)(SPI)到外設(shè)(SPI)的DMA傳輸

核心代碼

/*單片機(jī)頭文件*/

#include "main.h"

/*硬件驅(qū)動(dòng)*/

#include "delay.h"

#include "gpio.h"

#include "cw32l052_dma.h"

#include "cw32l052_spi.h"

/*C庫(kù)*/

#include < string.h >

 

//硬件連接

//SPIY_SCK  (PA10) -- SPIX_SCK  (PB13)

//SPIY_MISO (PA11) -- SPIX_MISO (PB14)

//SPIY_MOSI (PA12) -- SPIX_MOSI (PB15)

 

//SPI2相關(guān)定義(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相關(guān)定義(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()

 

//數(shù)組長(zhǎng)度

#define   BUFFERSIZE                 ARRAY_SZ(TxBuffer1)

 

//發(fā)送內(nèi)容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

                      };

//發(fā)送內(nèi)容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];  //接收數(shù)組1

uint8_t RxBuffer2[BUFFERSIZE];  //接收數(shù)組2

uint8_t TxCounter = 0;  //發(fā)送計(jì)數(shù)

uint8_t RxCounter = 0;  //接收計(jì)數(shù)

 

uint8_t TransferStatus1 = 1;  //DMA傳輸狀態(tài)標(biāo)志1

uint8_t TransferStatus2 = 1;  //DMA傳輸狀態(tài)標(biāo)志2

 

void DMA_Configuration(void);      //DMA配置函數(shù)

void SPI_Configuration(void);      //SPI配置函數(shù)

void SPI_GPIO_Configuration(void); //SPI相關(guān)GPIO口配置

 

/*

**功能說(shuō)明:

**主機(jī)SPIY發(fā)送TxBuffer1中的數(shù)據(jù),從機(jī)SPIX通過DMA接收數(shù)據(jù)并存儲(chǔ)到RxBuffer1

**主機(jī)SPIY發(fā)送無(wú)效數(shù)據(jù),啟動(dòng)SPI通信,同時(shí)SPIX從機(jī)通過DMA發(fā)送TxBuffer2中的數(shù)據(jù),SIPY接收數(shù)據(jù)并存儲(chǔ)到RxBuffer2

**單獨(dú)比較TxBuffer1與RxBuffer1、TxBuffer2與RxBuffer2中的內(nèi)容,比較結(jié)果通過LED燈指示

*/

int main(void)

{

  LED_Init();               //初始化LED指示燈

  SPI_GPIO_Configuration(); //配置PI相關(guān)GPIO口

  DMA_Configuration();      //配置DMA傳輸

  SPI_Configuration();      //配置SPI傳輸

  SPI_DMACmd(SPIX, SPI_DMAReq_Rx, ENABLE); //使能SPIX DMA RX

  SPI_NSSInternalSoftwareConfig(SPIX, SPI_NSSInternalSoft_Reset);//位選CS選中從機(jī)SPIX,起始信號(hào)

  while(TxCounter < BUFFERSIZE)

  {

    while(SPI_GetFlagStatus(SPIY,SPI_FLAG_TXE) == RESET);//等待發(fā)送緩沖空(為空后硬件自動(dòng)置1)

    SPI_SendData(SPIY,TxBuffer1[TxCounter++]); //發(fā)送TxBuffer1中的數(shù)據(jù),通過數(shù)據(jù)寄存器DR把數(shù)據(jù)填充到發(fā)送緩沖區(qū)中

  }

  while(DMA_GetFlagStatus(SPIX_RX_DMACHANNEL) != DMA_CHANNEL_STATUS_TRANSCOMPLETE);//等待DMA接收完成

 

  SPI_NSSInternalSoftwareConfig(SPIX, SPI_NSSInternalSoft_Set); //釋放從機(jī)SPIX,結(jié)束信號(hào)

  TransferStatus1 = memcmp(TxBuffer1, RxBuffer1, BUFFERSIZE); //對(duì)比兩數(shù)組數(shù)據(jù)

  if(TransferStatus1==0)  //如果數(shù)據(jù)相同

  {

    LED1_ON();  //LED1指示

  }

  else

  {

    LED1_OFF();

  }

 

  TxCounter = 0;

  SPI_ReceiveData(SPIY);//讀DR以清除RXNE(接收非空)標(biāo)志位

  SPI_DMACmd(SPIX, SPI_DMAReq_Rx, DISABLE);//失能SPIX DMA RX

  SPI_FlushSendBuff(SPIX);//清空發(fā)送緩沖區(qū)和移位寄存器

  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){;} //主機(jī)發(fā)送數(shù)據(jù)以啟動(dòng)SPI通信

    SPI_SendData(SPIY, TxBuffer1[TxCounter++]);

 

    while(SPI_GetFlagStatus(SPIY, SPI_FLAG_RXNE) == RESET){;}

      RxBuffer2[RxCounter++] = SPI_ReceiveData(SPIY);  //獲取接收緩沖區(qū)中的內(nèi)容

  }

  while(SPI_GetFlagStatus(SPIY,SPI_FLAG_BUSY) == SET); //檢查數(shù)據(jù)是否已經(jīng)全部通過SPI發(fā)送完畢

  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時(shí)鐘

    __RCC_GPIOA_CLK_ENABLE();

    __RCC_GPIOB_CLK_ENABLE();

 

    //SPI SCK MOSI MISO 復(fù)用

    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; //主機(jī)模式

  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //數(shù)據(jù)位寬8bit

  SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;  //時(shí)鐘極性

  SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;//時(shí)鐘相位,奇數(shù)邊緣采樣

  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //配置NSS引腳(片選信號(hào)線)的使用模式,軟件控制

  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; //從機(jī)模式

  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; //數(shù)據(jù)寄存器

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

}

審核編輯 黃宇

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • cpu
    cpu
    +關(guān)注

    關(guān)注

    68

    文章

    10776

    瀏覽量

    210480
  • 內(nèi)存
    +關(guān)注

    關(guān)注

    8

    文章

    2949

    瀏覽量

    73738
  • dma
    dma
    +關(guān)注

    關(guān)注

    3

    文章

    555

    瀏覽量

    100231
  • CW32
    +關(guān)注

    關(guān)注

    1

    文章

    173

    瀏覽量

    528
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    CW32L052單片機(jī)支持DMA實(shí)現(xiàn)高速數(shù)據(jù)傳輸

    CW32L052支持DMA(Direct Memory Access),即直接內(nèi)存訪問,無(wú)需CPU干預(yù),實(shí)現(xiàn)高速數(shù)據(jù)傳輸。
    的頭像 發(fā)表于 02-27 11:36 ?916次閱讀

    什么是DMA直接內(nèi)存訪問

    大家好,這是關(guān)于DMA的非?;镜膯栴}。1)什么是DMA直接內(nèi)存訪問)和什么時(shí)候使用?2)它是如何提高CPU性能的?或如何獨(dú)立工作,以節(jié)省
    發(fā)表于 01-25 10:45

    什么是直接內(nèi)存訪問DMA?

    我對(duì)DMA感到困惑。DMA是一種允許微控制器直接訪問另一個(gè)微控制器的存儲(chǔ)器的通信協(xié)議嗎?LED,如果不是,DMA是用來(lái)做什么的?謝謝:
    發(fā)表于 04-01 07:59

    超低功耗家族再添新成員,武漢芯源半導(dǎo)體發(fā)布32位M0+內(nèi)核MCU CW32L052系列產(chǎn)品

    2023年2月,武漢芯源半導(dǎo)體超低功耗家族再添新成員——32位M0+內(nèi)核MCU CW32L052系列芯片。CW32L052 是基于 eFlash 的單芯片低功耗微控制器,集成了主頻高達(dá) 48MHz
    發(fā)表于 02-21 14:02

    CW32L052微控制器數(shù)據(jù)手冊(cè)

    CW32L052 是基于 eFlash 的單芯片低功耗微控制器,集成了主頻高達(dá) 48MHz 的 ARM? Cortex?-M0+ 內(nèi)核、高速嵌入式存儲(chǔ)器(多至 64K 字節(jié) FLASH 和多至 8K
    發(fā)表于 09-14 06:28

    CW32L052微處理器用戶手冊(cè)

    CW32L052 內(nèi)核為 32 位的 ARM? Cortex?-M0+ 微處理器,最大尋址空間為 4GB。芯片內(nèi)置的程序存儲(chǔ)器、數(shù)據(jù)存儲(chǔ)器、各外設(shè)及端口寄存器被統(tǒng)一編址在同一個(gè) 4GB 的線性
    發(fā)表于 09-14 06:08

    CW32L052CxTx PCB封裝庫(kù)

    CW32L052CxTx PCB封裝庫(kù)(PADS)
    發(fā)表于 09-14 08:01

    CW32L052CxTx元件庫(kù)

    CW32L052CxTx元件庫(kù)(PADS)
    發(fā)表于 09-14 08:24

    CW32L052 StartKit軟件包

    CW32L052 StartKit 軟件包
    發(fā)表于 09-15 06:13

    CW32L052RxTx StartKit原理圖分享

    CW32L052RxTx StartKit原理圖
    發(fā)表于 09-15 07:35

    CW32L052R8T6 StartKit用戶手冊(cè)

    R8T6 StartKit 評(píng)估板需要搭配 CW-DAPLINK 調(diào)試器一起使用。CW32L052R8T6 StartKit 評(píng)估板帶有 CW32L052 StartKit 軟件包及 CW32
    發(fā)表于 09-15 06:04

    如何設(shè)置 DMA直接內(nèi)存訪問

    本應(yīng)用筆記解釋了使用 DMAC(直接存儲(chǔ)器訪問控制器)和 DTFR(DMA 觸發(fā)因子寄存器)的示例。
    的頭像 發(fā)表于 06-18 17:10 ?3727次閱讀
    如何設(shè)置 <b class='flag-5'>DMA</b>(<b class='flag-5'>直接</b><b class='flag-5'>內(nèi)存</b><b class='flag-5'>訪問</b>)

    超低功耗家族再添新成員,武漢芯源半導(dǎo)體發(fā)布32位M0+內(nèi)核MCU CW32L052系列產(chǎn)品

    2023年2月,武漢芯源半導(dǎo)體超低功耗家族再添新成員——32位M0+內(nèi)核MCUCW32L052系列芯片。CW32L052是基于eFlash的單芯片低功耗微控制器,集成了主頻高達(dá)48MHz的ARM
    的頭像 發(fā)表于 02-21 14:03 ?942次閱讀
    超低功耗家族再添新成員,武漢芯源半導(dǎo)體發(fā)布32位M0+內(nèi)核MCU <b class='flag-5'>CW32L052</b>系列產(chǎn)品

    STM32L4直接訪問內(nèi)存模塊(DMA)介紹

    電子發(fā)燒友網(wǎng)站提供《STM32L4直接訪問內(nèi)存模塊(DMA)介紹.pdf》資料免費(fèi)下載
    發(fā)表于 08-01 10:15 ?1次下載
    STM32<b class='flag-5'>L</b>4<b class='flag-5'>直接訪問</b><b class='flag-5'>內(nèi)存</b>模塊(<b class='flag-5'>DMA</b>)介紹

    CW32L052 FLASH存儲(chǔ)器

    CW32L052內(nèi)部集成了64KB嵌入式FLASH供用戶使用,可用來(lái)存儲(chǔ)應(yīng)用程序和用戶數(shù)據(jù)。芯片支持對(duì) FLASH 存儲(chǔ)器的讀、擦除和寫操作,支持擦寫保護(hù)和讀保護(hù)。芯片內(nèi)置 FLASH 編程所需的高壓 BOOST 電路,無(wú)須額外提供編程電壓。
    的頭像 發(fā)表于 02-28 17:43 ?662次閱讀
    <b class='flag-5'>CW32L052</b> FLASH存儲(chǔ)器