BD網(wǎng)盤鏈接:
https://pan.baidu.com/s/10WHNgB_cicTP1SbdcI4AkQ?pwd=l1et
提取碼:l1et
概述
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)的整體性能。
框圖
特性
使用DMA,最核心的就是配置要傳輸?shù)臄?shù)據(jù),包括數(shù)據(jù)從哪里來(lái),要到哪里去,傳輸?shù)臄?shù)據(jù)的單位是什么,要傳多少數(shù)據(jù),是一次傳輸還是連續(xù)傳輸?shù)鹊取?/p>
4 條獨(dú)立DMA通道 :
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傳輸模式 :
適用于小數(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í),
可以產(chǎn)生DMA請(qǐng)求(DMA request),硬件觸發(fā)啟動(dòng)DMA傳輸,
而不支持硬件DMA的外設(shè),只能配置為 軟件觸發(fā)啟動(dòng)DMA傳輸 。
雖然每個(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)位,如下表所示
? 數(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)存
BD網(wǎng)盤鏈接:
https://pan.baidu.com/s/1RlVVPt72fJrnBBUEHf3iJQ?pwd=oklw
提取碼:oklw
通過(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寫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)存
BD網(wǎng)盤鏈接:
https://pan.baidu.com/s/1ScCk-UqHBjJA5PxwSqMhkg?pwd=4701
提取碼:4701
通過(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 < 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ù)通過(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ù)
從外設(shè)到外設(shè)
BD網(wǎng)盤鏈接:
https://pan.baidu.com/s/1fSyMPAapft2a_Vy_d3F9vw?pwd=dw6x
提取碼:dw6x
通過(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 < 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通過(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);
}
審核編輯 黃宇
-
cpu
+關(guān)注
關(guān)注
68文章
10854瀏覽量
211576 -
內(nèi)存
+關(guān)注
關(guān)注
8文章
3019瀏覽量
74003 -
dma
+關(guān)注
關(guān)注
3文章
560瀏覽量
100544 -
CW32
+關(guān)注
關(guān)注
1文章
203瀏覽量
626
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論