概述
CW32L052支持DMA(Direct Memory Access),即直接內(nèi)存訪問,無需CPU干預(yù),實現(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)存之間:例如在兩個不同的數(shù)組之間傳輸數(shù)據(jù),或者在不同的內(nèi)存塊之間進(jìn)行數(shù)據(jù)拷貝。
?外設(shè)和外設(shè)之間:例如從一個SPI主/從機傳輸數(shù)據(jù)到另一個SPI從/主機。
使用DMA能夠有效減輕CPU的負(fù)擔(dān),特別是在大量數(shù)據(jù)需要高效傳輸?shù)那闆r下,可以提高系統(tǒng)的整體性能。
框圖
DMA功能框圖
特性
使用DMA,最核心的就是配置要傳輸?shù)臄?shù)據(jù),包括數(shù)據(jù)從哪里來,要到哪里去,傳輸?shù)臄?shù)據(jù)的單位是什么,要傳多少數(shù)據(jù),是一次傳輸還是連續(xù)傳輸?shù)鹊取?/p>
4條獨立DMA通道:
4個DMA通道的優(yōu)先級和通道號綁定,通道號越小優(yōu)先級越高,通道號越大優(yōu)先級越低。
4種傳輸模式:
硬件觸發(fā)BULK傳輸模式、硬件觸發(fā)BLOCK傳輸模式、軟件觸發(fā)BULK傳輸模式和軟件觸發(fā)BLOCK傳輸模式。
硬件 | BULK |
BLOCK | |
軟件 | BULK |
BLOCK |
BULK傳輸模式:
適用于小數(shù)據(jù)塊的傳輸,通常涉及大量的數(shù)據(jù)點,但每個數(shù)據(jù)點的大小較小。
與BLOCK模式不同,BULK模式下DMA會更頻繁地啟動新的傳輸,因為每個數(shù)據(jù)點通常被視為單獨的傳輸單元,所以DMA控制器需要在每個數(shù)據(jù)點傳輸完成后需要重新配置或者啟動DMA。在BULK傳輸模式下,傳輸過程不可被打斷。
BLOCK傳輸模式:
適用于大數(shù)據(jù)塊的高速傳輸,通常用于需要連續(xù)傳輸大量數(shù)據(jù)的情況。BLOCK模式下,DMA會將數(shù)據(jù)分成較大的塊,并在傳輸時以這些塊為單位進(jìn)行操作。DMA控制器在一次配置后,連續(xù)傳輸多個數(shù)據(jù)塊,而無需額外的干預(yù)或重新配置。每傳輸完成1個數(shù)據(jù)塊后就要進(jìn)行一次傳輸優(yōu)先級的仲裁,允許CPU或者更高優(yōu)先級的DMA通道訪問當(dāng)前DMA通道所占用的外設(shè)。
?硬件觸發(fā)和軟件觸發(fā):
要想通過DMA來傳輸數(shù)據(jù),必須先給DMA控制器發(fā)送DMA請求。部分外設(shè)支持硬件觸發(fā)啟動DMA傳輸,如FLASH存儲器、UART串口、TIM定時器、ADC數(shù)模轉(zhuǎn)換器等被配置為DMA通道的觸發(fā)源時,
可以產(chǎn)生DMA請求(DMA request),硬件觸發(fā)啟動DMA傳輸,
而不支持硬件DMA的外設(shè),只能配置為軟件觸發(fā)啟動DMA傳輸。
雖然每個通道可以接收多個外設(shè)的請求,但是同一時間只能接收一個,不能同時接收多個。
?DMA中斷
DMA通道在傳輸工程中可產(chǎn)生2個中斷標(biāo)志:傳輸錯誤中斷標(biāo)志和傳輸完成中斷標(biāo)志
不同 DMA 通道的中斷各自獨立,通過中斷標(biāo)志寄存器 DMA_ISR 可以獲取各通道的中斷標(biāo)志。標(biāo)志對應(yīng)多個可能的產(chǎn)生原因,具體產(chǎn)生原因需查詢 DMA_CSRy.STATUS 狀態(tài)位,如下表所示
?數(shù)據(jù)寬度:
數(shù)據(jù)位寬可以設(shè)置為8bit、16bit和32bit,DMA通道的源地址和目的地址的位寬必須完全一致
?數(shù)據(jù)塊數(shù)量:
傳輸?shù)臄?shù)據(jù)塊數(shù)量可以設(shè)置為1 ~ 65535
?數(shù)據(jù)傳輸優(yōu)先級
當(dāng)CPU和DMA訪問不同的外設(shè)時,數(shù)據(jù)的傳輸可以同時進(jìn)行;
當(dāng)CPU和DMA同時訪問同一個外設(shè)時,CPU的優(yōu)先級高于DMA。
從外設(shè)到內(nèi)存
通過ADC轉(zhuǎn)換完成標(biāo)志觸發(fā)(硬件觸發(fā))DMA方式實現(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ù) /* **功能說明: **ADC采集數(shù)據(jù)觸發(fā)DMA,將采集到的數(shù)據(jù)(1.2V內(nèi)核電壓基準(zhǔn)源)存儲在內(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個ADC時鐘周期 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é)果右對齊 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); //啟動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
從內(nèi)存到內(nèi)存
通過軟件觸發(fā)DMA方式實現(xiàn)內(nèi)存(FLASH)到內(nèi)存(SRAM)的DMA傳輸
核心代碼:
//單片機頭文件 #include "main.h" #include "cw32l052_lcd.h" #include "cw32l052_dma.h" //硬件外設(shè) #include "delay.h" #include "gpio.h" //C庫 #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ù)值 /* **功能說明: **將srcBuf數(shù)組中的數(shù)據(jù)通過DMA傳送到dstBuf數(shù)組中, **srcBuf數(shù)組中的數(shù)據(jù)通過const關(guān)鍵詞存儲到FLASH中, **dstBuf數(shù)組存儲在SRAM程序運行過程中 **傳輸完成后比較兩數(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); //啟動DMA通道1進(jìn)行傳輸 }
演示:LCD屏上顯示通過DMA傳輸?shù)膁stBuf的數(shù)據(jù)
從外設(shè)到外設(shè)
通過硬件觸發(fā)DMA方式實現(xiàn)外設(shè)(SPI)到外設(shè)(SPI)的DMA傳輸
核心代碼:
/*單片機頭文件*/ #include "main.h" /*硬件驅(qū)動*/ #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() //數(shù)組長度 #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ā)送計數(shù) uint8_t RxCounter = 0; //接收計數(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口配置 /* **功能說明: **主機SPIY發(fā)送TxBuffer1中的數(shù)據(jù),從機SPIX通過DMA接收數(shù)據(jù)并存儲到RxBuffer1 **主機SPIY發(fā)送無效數(shù)據(jù),啟動SPI通信,同時SPIX從機通過DMA發(fā)送TxBuffer2中的數(shù)據(jù),SIPY接收數(shù)據(jù)并存儲到RxBuffer2 **單獨比較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選中從機SPIX,起始信號 while(TxCounter < BUFFERSIZE) { while(SPI_GetFlagStatus(SPIY,SPI_FLAG_TXE) == RESET);//等待發(fā)送緩沖空(為空后硬件自動置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); //釋放從機SPIX,結(jié)束信號 TransferStatus1 = memcmp(TxBuffer1, RxBuffer1, BUFFERSIZE); //對比兩數(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){;} //主機發(fā)送數(shù)據(jù)以啟動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時鐘 __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; //主機模式 SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //數(shù)據(jù)位寬8bit SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //時鐘極性 SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;//時鐘相位,奇數(shù)邊緣采樣 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; //數(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); }
審核編輯:劉清
-
單片機
+關(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
+關(guān)注
關(guān)注
3文章
572瀏覽量
102308 -
推挽輸出
+關(guān)注
關(guān)注
0文章
85瀏覽量
6623
原文標(biāo)題:CW32L052單片機DMA直接內(nèi)存訪問
文章出處:【微信號:武漢芯源半導(dǎo)體,微信公眾號:武漢芯源半導(dǎo)體】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
ADXRS453Z的芯片支持使用STM32單片機的DMA數(shù)據(jù)傳輸功能嗎?
單片機紅外數(shù)據(jù)傳輸
請問ADXRS453Z的芯片支持使用STM32單片機的DMA數(shù)據(jù)傳輸功能嗎?
超低功耗家族再添新成員,武漢芯源半導(dǎo)體發(fā)布32位M0+內(nèi)核MCU CW32L052系列產(chǎn)品
DMA進(jìn)行數(shù)據(jù)傳輸和CPU進(jìn)行數(shù)據(jù)傳輸的疑問
CW32L052微控制器數(shù)據(jù)手冊
單片機網(wǎng)絡(luò)數(shù)據(jù)傳輸器
TCP/IP協(xié)議單片機在網(wǎng)絡(luò)通信中的數(shù)據(jù)傳輸技術(shù)

DMA數(shù)據(jù)傳輸(源代碼分享)
DMA數(shù)據(jù)傳輸在SPEAR300實現(xiàn)高速串口驅(qū)動設(shè)計

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

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

CW32L052 FLASH存儲器

評論