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

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

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

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

jf_qE49KoVBr8 ? 來(lái)源:CW32生態(tài)社區(qū) ? 2024-02-27 11:36 ? 次閱讀

概述

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

?外設(shè)和內(nèi)存之間:例如ADC采集數(shù)據(jù)到內(nèi)存,這種傳輸方式常見(jiàn)于需要將外設(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)的整體性能。

框圖

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

DMA功能框圖

特性

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

4條獨(dú)立DMA通道

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

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傳輸模式。

硬件 BULK
BLOCK
軟件 BULK
BLOCK

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傳輸模式下,傳輸過(guò)程不可被打斷。

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通道訪問(wèn)當(dāng)前DMA通道所占用的外設(shè)。

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

要想通過(guò)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í),

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

可以產(chǎn)生DMA請(qǐng)求(DMA request),硬件觸發(fā)啟動(dòng)DMA傳輸,

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

而不支持硬件DMA的外設(shè),只能配置為軟件觸發(fā)啟動(dòng)DMA傳輸

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

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

?DMA中斷

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

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

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

?數(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訪問(wèn)不同的外設(shè)時(shí),數(shù)據(jù)的傳輸可以同時(shí)進(jìn)行;

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

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

通過(guò)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;       //開(kāi)啟跟隨器 
  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);                  //開(kāi)始轉(zhuǎn)換 
} 
 
void ADC_IRQHandler(void) 
{ 
    /* USER CODE BEGIN */ 
  if(ADC_GetITStatus(ADC_IT_EOC) != RESET) 
  { 
      ADC_ClearITPendingBit(ADC_IT_EOC); 
      ADC_SoftwareStartConvCmd(ENABLE);              //開(kāi)始轉(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寫(xiě)1,傳輸數(shù)量為1                        
        DMA_Cmd(CW_DMACHANNEL1, ENABLE);  
    } 
    /* USER CODE END */ 
}

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

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

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

通過(guò)軟件觸發(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 


#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ù)通過(guò)DMA傳送到dstBuf數(shù)組中,
**srcBuf數(shù)組中的數(shù)據(jù)通過(guò)const關(guān)鍵詞存儲(chǔ)到FLASH中,
**dstBuf數(shù)組存儲(chǔ)在SRAM程序運(yùn)行過(guò)程中
**傳輸完成后比較兩數(shù)組內(nèi)容,相同則打開(kā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屏上顯示通過(guò)DMA傳輸?shù)膁stBuf的數(shù)據(jù)

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

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

通過(guò)硬件觸發(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 


//硬件連接
//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通過(guò)DMA接收數(shù)據(jù)并存儲(chǔ)到RxBuffer1
**主機(jī)SPIY發(fā)送無(wú)效數(shù)據(jù),啟動(dòng)SPI通信,同時(shí)SPIX從機(jī)通過(guò)DMA發(fā)送TxBuffer2中的數(shù)據(jù),SIPY接收數(shù)據(jù)并存儲(chǔ)到RxBuffer2
**單獨(dú)比較TxBuffer1與RxBuffer1、TxBuffer2與RxBuffer2中的內(nèi)容,比較結(jié)果通過(guò)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ù),通過(guò)數(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)全部通過(guò)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};
    
    //打開(kāi)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)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 單片機(jī)
    +關(guān)注

    關(guān)注

    6063

    文章

    44915

    瀏覽量

    646864
  • 數(shù)據(jù)傳輸
    +關(guān)注

    關(guān)注

    9

    文章

    2003

    瀏覽量

    65676
  • LCD屏
    +關(guān)注

    關(guān)注

    0

    文章

    126

    瀏覽量

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

    關(guān)注

    3

    文章

    572

    瀏覽量

    102308
  • 推挽輸出
    +關(guān)注

    關(guān)注

    0

    文章

    85

    瀏覽量

    6623

原文標(biāo)題:CW32L052單片機(jī)DMA直接內(nèi)存訪問(wèn)

文章出處:【微信號(hào):武漢芯源半導(dǎo)體,微信公眾號(hào):武漢芯源半導(dǎo)體】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 0人收藏

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

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

    CW32L052支持DMA(Direct Memory Access),即直接內(nèi)存訪問(wèn),無(wú)需CPU干預(yù),實(shí)現(xiàn)高速
    的頭像 發(fā)表于 02-28 16:48 ?1193次閱讀
    <b class='flag-5'>CW32L052</b> <b class='flag-5'>DMA</b>直接內(nèi)存訪問(wèn)

    ADXRS453Z的芯片支持使用STM32單片機(jī)DMA數(shù)據(jù)傳輸功能嗎?

    ADXRS453Z的芯片支持使用STM32單片機(jī)DMA數(shù)據(jù)傳輸功能嗎?如果,不能,考慮到我們的數(shù)據(jù)傳輸還是挺多的,那么常規(guī)的SPI通信方式
    發(fā)表于 12-29 07:47

    單片機(jī)紅外數(shù)據(jù)傳輸

    基于51單片機(jī)的紅外數(shù)據(jù)傳輸系統(tǒng)的設(shè)計(jì)主要任務(wù):寫(xiě)設(shè)計(jì)要求、報(bào)告,設(shè)計(jì)各電路控制模塊、用PROTUS仿真、搭建電路模塊、寫(xiě)出程序控制流程、寫(xiě)出源碼、調(diào)試達(dá)到預(yù)期目標(biāo)。最終目標(biāo):利用單片機(jī)實(shí)現(xiàn)
    發(fā)表于 07-12 23:54

    請(qǐng)問(wèn)ADXRS453Z的芯片支持使用STM32單片機(jī)DMA數(shù)據(jù)傳輸功能嗎?

    ADXRS453Z的芯片支持使用STM32單片機(jī)DMA數(shù)據(jù)傳輸功能嗎?如果,不能,考慮到我們的數(shù)據(jù)傳輸還是挺多的,那么常規(guī)的SPI通信方式
    發(fā)表于 08-10 08:13

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

    的 ARM? Cortex?-M0+ 內(nèi)核、高速嵌入式存儲(chǔ)器(最大64K字節(jié)FLASH、最大8K字節(jié)RAM),支持最多55路I/O接口。CW32L052內(nèi)部框圖外設(shè)包括:1路12位ADC,3路UART
    發(fā)表于 02-21 14:02

    DMA進(jìn)行數(shù)據(jù)傳輸和CPU進(jìn)行數(shù)據(jù)傳輸的疑問(wèn)

    求大佬解答,本人正在學(xué)習(xí)STM32單片機(jī)DMA直接數(shù)據(jù)存儲(chǔ)部分的內(nèi)容 看了DMA簡(jiǎn)介后,也上手過(guò)實(shí)例代碼,但是沒(méi)有實(shí)際的項(xiàng)目經(jīng)驗(yàn),所以有以下疑問(wèn):
    發(fā)表于 05-25 17:18

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

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

    CW32L052 StartKit軟件包

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

    單片機(jī)網(wǎng)絡(luò)數(shù)據(jù)傳輸

    單片機(jī)網(wǎng)絡(luò)數(shù)據(jù)傳輸器是由單片機(jī)以及有關(guān)電子電路組成的,可以通過(guò)互聯(lián)網(wǎng)絡(luò)來(lái)實(shí)現(xiàn)遠(yuǎn)程監(jiān)控的一種傳輸裝置。用戶有了
    發(fā)表于 06-29 18:21 ?2080次閱讀

    TCP/IP協(xié)議單片機(jī)在網(wǎng)絡(luò)通信中的數(shù)據(jù)傳輸技術(shù)

    介紹了嵌入式TCP/IP協(xié)議單片機(jī)在網(wǎng)絡(luò)通信中的數(shù)據(jù)傳輸技術(shù)。將TCP/IP協(xié)議嵌入式單片機(jī)中,借助網(wǎng)卡芯片CS8900實(shí)現(xiàn)單片機(jī)在局域網(wǎng)
    發(fā)表于 04-16 22:04 ?4588次閱讀
    TCP/IP協(xié)議<b class='flag-5'>單片機(jī)</b>在網(wǎng)絡(luò)通信中的<b class='flag-5'>數(shù)據(jù)傳輸</b>技術(shù)

    DMA數(shù)據(jù)傳輸(源代碼分享)

    手頭項(xiàng)目也需要加入DMA數(shù)據(jù)傳輸,以最大限度地提升CPU效率,于是測(cè)試了一下XMEGA的DMA模塊,把一塊內(nèi)存中的數(shù)據(jù)DMA
    的頭像 發(fā)表于 04-27 09:22 ?9557次閱讀

    DMA數(shù)據(jù)傳輸在SPEAR300實(shí)現(xiàn)高速串口驅(qū)動(dòng)設(shè)計(jì)

    DMA數(shù)據(jù)傳輸無(wú)需CPU的參與,是一種更加高效的數(shù)據(jù)傳輸方式。現(xiàn)有的DMA數(shù)據(jù)傳輸方案都是基于DMA
    發(fā)表于 04-04 12:23 ?1769次閱讀
    <b class='flag-5'>DMA</b><b class='flag-5'>數(shù)據(jù)傳輸</b>在SPEAR300<b class='flag-5'>實(shí)現(xiàn)</b><b class='flag-5'>高速</b>串口驅(qū)動(dòng)設(shè)計(jì)

    AT89C52單片機(jī)與PC機(jī)之間的無(wú)線數(shù)據(jù)傳輸設(shè)計(jì)

    和專(zhuān)用無(wú)線傳輸芯片實(shí)現(xiàn)簡(jiǎn)單的短距離無(wú)線傳輸方案,硬件部分包括單片機(jī)端和PC機(jī)端,實(shí)現(xiàn)
    發(fā)表于 08-16 17:36 ?5646次閱讀
    AT89C52<b class='flag-5'>單片機(jī)</b>與PC<b class='flag-5'>機(jī)</b>之間的無(wú)線<b class='flag-5'>數(shù)據(jù)傳輸</b>設(shè)計(jì)

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

    ?Cortex?-M0+內(nèi)核、高速嵌入式存儲(chǔ)器(最大64K字節(jié)FLASH、最大8K字節(jié)RAM),支持最多55路I/O接口。CW32L052內(nèi)部框圖外設(shè)包括:1路12位ADC,3路UART(支持
    的頭像 發(fā)表于 02-21 14:03 ?1282次閱讀
    超低功耗家族再添新成員,武漢芯源半導(dǎo)體發(fā)布32位M0+內(nèi)核MCU <b class='flag-5'>CW32L052</b>系列產(chǎn)品

    CW32L052 FLASH存儲(chǔ)器

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

    電子發(fā)燒友

    中國(guó)電子工程師最喜歡的網(wǎng)站

    • 2931785位工程師會(huì)員交流學(xué)習(xí)
    • 獲取您個(gè)性化的科技前沿技術(shù)信息
    • 參加活動(dòng)獲取豐厚的禮品