STM32的SPI采用DMA方式傳輸測(cè)試
主機(jī):WIN7
本文引用地址:http://www.ex-cimer.com/article/201611/318288.htm開(kāi)發(fā)環(huán)境:MDK4.23
MCU:STM32F103CBT6
說(shuō)明:
參考鏈接:http://www.openedv.com/posts/list/3159.htm
SPI傳輸數(shù)據(jù)分為連續(xù)傳輸和非連續(xù)傳輸.
連續(xù)傳輸時(shí)序圖:
非連續(xù)傳輸時(shí)序圖:
非連續(xù)傳輸模式可以參考上篇文章:http://blog.csdn.net/jdh99/article/details/7598573
官方pdf關(guān)于連續(xù)和非連續(xù)傳輸?shù)恼f(shuō)明:
當(dāng)在主模式下發(fā)送數(shù)據(jù)時(shí),如果軟件足夠快,能夠在檢測(cè)到每次TXE的上升沿(或TXE中斷),并立即在正在進(jìn)行的傳輸結(jié)束之前寫入SPI_DR寄存器,則能夠?qū)崿F(xiàn)連續(xù)的通信;此時(shí),在每個(gè)數(shù)據(jù)項(xiàng)的傳輸之間的SPI時(shí)鐘保持連續(xù),同時(shí)BSY位不會(huì)被清除。
簡(jiǎn)而言之,就是要及時(shí)監(jiān)測(cè)TXE.在SPI在1M以上波特率傳輸時(shí),傳輸一位時(shí)間為1us,導(dǎo)致軟件不能及時(shí)判斷,此時(shí)可以用dma的方式來(lái)進(jìn)行SPI傳輸.
源代碼:
配置:
#define buffersize 512#define SPI1_DR_Addr ( (u32)0x4001300C )extern uint8_t SPI1_TX_Buff[buffersize];extern uint8_t SPI1_RX_Buff[buffersize];
void SPI1_DMA_Configuration( void ){RCC->AHBENR |= 1<<0 ; //DMA1時(shí)鐘使能/*------------------配置SPI1_RX_DMA通道Channel2---------------------*/DMA1_Channel2->CCR &= ~( 1<<14 ) ; //非存儲(chǔ)器到存儲(chǔ)器模式DMA1_Channel2->CCR |= 2<<12 ; //通道優(yōu)先級(jí)高DMA1_Channel2->CCR &= ~( 3<<10 ) ; //存儲(chǔ)器數(shù)據(jù)寬度8bitDMA1_Channel2->CCR &= ~( 3<<8 ) ; //外設(shè)數(shù)據(jù)寬度8bitDMA1_Channel2->CCR |= 1<<7 ; //存儲(chǔ)器地址增量模式DMA1_Channel2->CCR &= ~( 1<<6 ) ; //不執(zhí)行外設(shè)地址增量模式DMA1_Channel2->CCR &= ~( 1<<5 ) ; //執(zhí)行循環(huán)操作DMA1_Channel2->CCR &= ~( 1<<4 ) ; //從外設(shè)讀DMA1_Channel2->CNDTR &= 0x0000 ; //傳輸數(shù)量寄存器清零DMA1_Channel2->CNDTR = buffersize ; //傳輸數(shù)量設(shè)置為buffersize個(gè)DMA1_Channel2->CPAR = SPI1_DR_Addr ; //設(shè)置外設(shè)地址,注意PSIZEDMA1_Channel2->CMAR = (u32)SPI1_RX_Buff ; //設(shè)置DMA存儲(chǔ)器地址,注意MSIZE/*------------------配置SPI1_TX_DMA通道Channel3---------------------*/DMA1_Channel3->CCR &= ~( 1<<14 ) ; //非存儲(chǔ)器到存儲(chǔ)器模式DMA1_Channel3->CCR |= 0<<12 ; //通道優(yōu)先級(jí)最低DMA1_Channel3->CCR &= ~( 3<<10 ) ; //存儲(chǔ)器數(shù)據(jù)寬度8bitDMA1_Channel3->CCR &= ~( 3<<8 ) ; //外設(shè)數(shù)據(jù)寬度8bitDMA1_Channel3->CCR |= 1<<7 ; //存儲(chǔ)器地址增量模式DMA1_Channel3->CCR &= ~( 1<<6 ) ; //不執(zhí)行外設(shè)地址增量模式DMA1_Channel3->CCR &= ~( 1<<5 ) ; //不執(zhí)行循環(huán)操作DMA1_Channel3->CCR |= 1<<4 ; //從存儲(chǔ)器讀DMA1_Channel3->CNDTR &= 0x0000 ; //傳輸數(shù)量寄存器清零DMA1_Channel3->CNDTR = buffersize ; //傳輸數(shù)量設(shè)置為buffersize個(gè)DMA1_Channel3->CPAR = SPI1_DR_Addr ; //設(shè)置外設(shè)地址,注意PSIZEDMA1_Channel3->CMAR = (uint32_t)SPI1_TX_Buff ; //設(shè)置DMA存儲(chǔ)器地址,注意MSIZE }
接收與發(fā)送:
void SPI1_ReceiveSendByte( u16 num ){DMA1_Channel2->CNDTR = 0x0000 ; //傳輸數(shù)量寄存器清零DMA1_Channel2->CNDTR = num ; //傳輸數(shù)量設(shè)置為buffersize個(gè)DMA1_Channel3->CNDTR = 0x0000 ; //傳輸數(shù)量寄存器清零DMA1_Channel3->CNDTR = num ; //傳輸數(shù)量設(shè)置為buffersize個(gè)DMA1->IFCR = 0xF0 ; //清除通道2的標(biāo)志位DMA1->IFCR = 0xF00 ; //清除通道3的標(biāo)志位SPI1->DR ; //接送前讀一次SPI1->DR,保證接收緩沖區(qū)為空while( ( SPI1->SR & 0x02 ) == 0 );DMA1_Channel3->CCR |= 1 << 0 ; //開(kāi)啟DMA通道3DMA1_Channel2->CCR |= 1 << 0 ; //開(kāi)啟DMA通道2 while( ( DMA1->ISR & 0x20 ) == 0 );DMA1_Channel3->CCR &= ~( 1 << 0 ) ; //關(guān)閉DMA通道3DMA1_Channel2->CCR &= ~( 1 << 0 ) ; //關(guān)閉DMA通道2}
//SPI發(fā)送一個(gè)字節(jié)static uint8 SPI_SendByte(uint8 Data){#ifndef SPI_DMA// Loop while DR register in not empltywhile( SPI_I2S_GetFlagStatus( SPI1, SPI_I2S_FLAG_TXE ) == RESET ) ;// Send byte through the SPI1 peripheralSPI_I2S_SendData( SPI1, Data ) ;// Wait to receive a bytewhile( SPI_I2S_GetFlagStatus( SPI1, SPI_I2S_FLAG_RXNE ) == RESET ) ;// Return the byte read from the SPI busreturn SPI_I2S_ReceiveData( SPI1 ) ;#elseSPI1_TX_Buff[0] = Data;SPI1_ReceiveSendByte(1);return (SPI1_RX_Buff[0]);#endif}//SPI讀取Len字節(jié)void SPI_ReadBytes( uint8 Addr, NtrxBufferPtr Buffer, uint8 Len ){#ifndef SPI_DMAif( ( Len > 0x80 ) || ( Len == 0 ) )Len = 1 ;SPI_SendByte( Len ) ;SPI_SendByte( Addr ) ;while( Len-- ){*Buffer = SPI_SendByte( 0xFF ) ;Buffer ++ ;}#elseuint8 i = 0;if( ( Len > 0x80 ) || ( Len == 0 ) )Len = 1 ;SPI1_TX_Buff[0] = Len;SPI1_TX_Buff[1] = Addr;SPI1_ReceiveSendByte(Len + 2);for (i = 0;i < Len;i++){*Buffer++ = SPI1_RX_Buff[i + 2]; }#endif}
評(píng)論