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

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

3天內不再提示

CW32L052單片機支持DMA實(shí)現高速數據傳輸

武漢芯源半導體 ? 來(lái)源:CW32生態(tài)社區 ? 2024-02-27 11:36 ? 次閱讀

概述

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

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

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

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

使用DMA能夠有效減輕CPU的負擔,特別是在大量數據需要高效傳輸的情況下,可以提高系統的整體性能。

框圖

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

DMA功能框圖

特性

使用DMA,最核心的就是配置要傳輸的數據,包括數據從哪里來(lái),要到哪里去,傳輸的數據的單位是什么,要傳多少數據,是一次傳輸還是連續傳輸等等。

4條獨立DMA通道

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

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

4種傳輸模式:

硬件觸發(fā)BULK傳輸模式、硬件觸發(fā)BLOCK傳輸模式、軟件觸發(fā)BULK傳輸模式和軟件觸發(fā)BLOCK傳輸模式。

硬件 BULK
BLOCK
軟件 BULK
BLOCK

BULK傳輸模式:

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

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

BLOCK傳輸模式:

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

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

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

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

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

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

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

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

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

?DMA中斷

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

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

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

?數據寬度:

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

?數據塊數量:

傳輸的數據塊數量可以設置為1 ~ 65535

?數據傳輸優(yōu)先級

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

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

從外設到內存

通過(guò)ADC轉換完成標志觸發(fā)(硬件觸發(fā))DMA方式實(shí)現外設到內存的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子程序函數 
 
/* 
**功能說(shuō)明:
**ADC采集數據觸發(fā)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個(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;           //內置溫度傳感器失能 
  ADC_InitStruct.ADC_DMASOCEn = ADC_DMASOCEnable;   //ADC轉換完成觸發(fā)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);                  //開(kāi)始轉換 
} 
 
void ADC_IRQHandler(void) 
{ 
    /* USER CODE BEGIN */ 
  if(ADC_GetITStatus(ADC_IT_EOC) != RESET) 
  { 
      ADC_ClearITPendingBit(ADC_IT_EOC); 
      ADC_SoftwareStartConvCmd(ENABLE);              //開(kāi)始轉換 
  } 
    /* 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;  //硬件觸發(fā)DMA傳輸 
  DMA_InitStruct.HardTrigSource = DMA_HardTrig_ADC_SINGLETRANSCOM;  //硬件觸發(fā)源: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); //啟動(dòng)DMA通道1進(jìn)行傳輸 
} 
 
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寫(xiě)1,傳輸數量為1                        
        DMA_Cmd(CW_DMACHANNEL1, ENABLE);  
    } 
    /* USER CODE END */ 
}

演示:ADC轉換結果為1580左右,換算成電壓:1580/4096*3.3=1.27V

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

從內存到內存

通過(guò)軟件觸發(fā)DMA方式實(shí)現內存(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數值


/*
**功能說(shuō)明:
**將srcBuf數組中的數據通過(guò)DMA傳送到dstBuf數組中,
**srcBuf數組中的數據通過(guò)const關(guān)鍵詞存儲到FLASH中,
**dstBuf數組存儲在SRAM程序運行過(guò)程中
**傳輸完成后比較兩數組內容,相同則打開(kāi)LED1和LED1,LCD上循環(huán)顯示dstBuf數據;
**不同則進(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數據
      {
        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; //數據寬度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;  //軟件觸發(fā)DMA傳輸


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

演示:LCD屏上顯示通過(guò)DMA傳輸的dstBuf的數據

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

從外設到外設

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

核心代碼:

/*單片機頭文件*/
#include "main.h"
/*硬件驅動(dòng)*/
#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相關(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()


//數組長(cháng)度
#define   BUFFERSIZE                 ARRAY_SZ(TxBuffer1)


//發(fā)送內容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ā)送內容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;  //發(fā)送計數
uint8_t RxCounter = 0;  //接收計數
  
uint8_t TransferStatus1 = 1;  //DMA傳輸狀態(tài)標志1
uint8_t TransferStatus2 = 1;  //DMA傳輸狀態(tài)標志2
                      
void DMA_Configuration(void);      //DMA配置函數
void SPI_Configuration(void);      //SPI配置函數
void SPI_GPIO_Configuration(void); //SPI相關(guān)GPIO口配置
  
/*
**功能說(shuō)明:
**主機SPIY發(fā)送TxBuffer1中的數據,從機SPIX通過(guò)DMA接收數據并存儲到RxBuffer1
**主機SPIY發(fā)送無(wú)效數據,啟動(dòng)SPI通信,同時(shí)SPIX從機通過(guò)DMA發(fā)送TxBuffer2中的數據,SIPY接收數據并存儲到RxBuffer2
**單獨比較TxBuffer1與RxBuffer1、TxBuffer2與RxBuffer2中的內容,比較結果通過(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選中從機SPIX,起始信號
  while(TxCounter < BUFFERSIZE)
  {
    while(SPI_GetFlagStatus(SPIY,SPI_FLAG_TXE) == RESET);//等待發(fā)送緩沖空(為空后硬件自動(dòng)置1)
    SPI_SendData(SPIY,TxBuffer1[TxCounter++]); //發(fā)送TxBuffer1中的數據,通過(guò)數據寄存器DR把數據填充到發(fā)送緩沖區中
  }
  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);//清空發(fā)送緩沖區和移位寄存器
  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){;} //主機發(fā)送數據以啟動(dòng)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); //檢查數據是否已經(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 復用
    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; //雙線(xiàn)全雙工模式
  SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //主機模式
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //數據位寬8bit
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;  //時(shí)鐘極性
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;//時(shí)鐘相位,奇數邊緣采樣
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //配置NSS引腳(片選信號線(xiàn))的使用模式,軟件控制
  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);
}




審核編輯:劉清

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

    關(guān)注

    6008

    文章

    44105

    瀏覽量

    623588
  • 數據傳輸
    +關(guān)注

    關(guān)注

    9

    文章

    1593

    瀏覽量

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

    關(guān)注

    0

    文章

    118

    瀏覽量

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

    關(guān)注

    3

    文章

    540

    瀏覽量

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

    關(guān)注

    0

    文章

    38

    瀏覽量

    6475

原文標題:CW32L052單片機DMA直接內存訪(fǎng)問(wèn)

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

收藏 人收藏

    評論

    相關(guān)推薦

    CW32L052 DMA直接內存訪(fǎng)問(wèn)

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

    ADXRS453Z的芯片支持使用STM32單片機DMA數據傳輸功能嗎?

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

    單片機紅外數據傳輸

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

    【OK210申請】無(wú)線(xiàn)數據傳輸模塊設計

    單片機的接口電路。(3) 編寫(xiě)控制無(wú)線(xiàn)數據傳輸器件進(jìn)行數據。目標:(1) 單片機系統:通過(guò)串口傳輸向上位
    發(fā)表于 07-24 10:39

    請問(wèn)ADXRS453Z的芯片支持使用STM32單片機DMA數據傳輸功能嗎?

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

    請問(wèn)能通過(guò)DMA方式實(shí)現GPRS數據傳輸嗎?

    GPRS在實(shí)現發(fā)送數據的過(guò)程中相對來(lái)說(shuō)時(shí)間有些長(cháng),不想耽誤單片機采集傳感器數據信息的過(guò)程。我可否能用DMA的方式
    發(fā)表于 05-21 00:42

    基于單片機和GPRS模塊的嵌入式無(wú)線(xiàn)數據傳輸終端的實(shí)現方案

    本文給出了一種基于單片機和GPRS模塊的嵌入式無(wú)線(xiàn)數據傳輸終端的實(shí)現方案。以單片機應用系統為中心的小型GPRS通信系統成本低、設計周期短、便攜性好,尤其適用于遠程控制和
    發(fā)表于 01-04 06:53

    怎么實(shí)現基于FPGA的具有流量控制機制的高速串行數據傳輸系統設計?

    本文介紹了基于Xilinx Virtex-6 FPGA的高速串行數據傳輸系統的設計與實(shí)現,系統包含AXI DMA和GTX串行收發(fā)器,系統增加了流量控制機制來(lái)保證
    發(fā)表于 05-25 06:45

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

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

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

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

    CW32L052微控制器數據手冊

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

    CW32L052 StartKit軟件包

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

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

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

    DMA數據傳輸在SPEAR300實(shí)現高速串口驅動(dòng)設計

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

    CW32L052 FLASH存儲器

    CW32L052內部集成了64KB嵌入式FLASH供用戶(hù)使用,可用來(lái)存儲應用程序和用戶(hù)數據。芯片支持對 FLASH 存儲器的讀、擦除和寫(xiě)操作,支持擦寫(xiě)保護和讀保護。芯片內置 FLASH
    的頭像 發(fā)表于 02-28 17:43 ?513次閱讀
    <b class='flag-5'>CW32L052</b> FLASH存儲器
    亚洲欧美日韩精品久久_久久精品AⅤ无码中文_日本中文字幕有码在线播放_亚洲视频高清不卡在线观看