STM32採用SPI DMA方式進行數據通信

[本文屬原創,轉載請附上原文出處鏈接。]

調試STM32 SPI 通過DMA方式主從機通信,主機時鐘和mosi信號波形都正常,出現從機接收數據出錯的問題。這是因為DMA是直接內存讀取數據,如果是主從機上電開始接收數據,數據接收不會出錯。如果從機延遲接收數據或者說與主機時鐘不同步會造成數據錯位。如果誰有更好的辦法控制DMA傳輸開關,可以一起交流學習。
這裡只列舉主機程序,
使能RCC時鐘:

使能RCC時鐘:
/*******************************************************************************
* Function Name : RCC_Configuration
* Description : RCC clock init
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void RCC_Configuration(void)
{
 /*DMA2 clock enable*/
 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE); 
 /*SPI3 clock enable*/
 RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC
 |RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOE|RCC_APB2Periph_AFIO, ENABLE );
 RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE); 
}

GPIO配置:

/* Configure SPI3 pins: SCK and MOSI */ 
 GPIO_PinRemapConfig(GPIO_Remap_SPI3,ENABLE); 
 GPIO_InitStructure.GPIO_Pin = SPI_PIN_SCK| SPI_PIN_MOSI;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 GPIO_Init(SPI_MASTER_GPIO, &GPIO_InitStructure);
	
 /* Configure SPI3 pins: MISO */
 GPIO_InitStructure.GPIO_Pin = SPI_PIN_MISO;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 GPIO_Init(SPI_MASTER_GPIO, &GPIO_InitStructure);

 GPIO_InitStructure.GPIO_Pin = SPI_PIN_CS; //SPI CS
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 GPIO_Init(SPI_MASTER_GPIO, &GPIO_InitStructure);

SPI初始化:

SPI_Cmd(SPI_MASTER, DISABLE); 
 /* SPI MASTER configuration */
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; 
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; 
SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b; 
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; 
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; 
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; 
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8; 
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; 
SPI_InitStructure.SPI_CRCPolynomial = 7; 
SPI_Init(SPI_MASTER, &SPI_InitStructure); 
 /* Enable DMA2 Channel2*/ 
 DMA_Cmd(DMA2_Channel2, ENABLE);
 SPI_I2S_DMACmd(SPI_MASTER, SPI_I2S_DMAReq_Tx, ENABLE);
 /* Enable SPI MASTER*/
 SPI_Cmd(SPI_MASTER, ENABLE); 
 //GPIO_ResetBits(SPI_MASTER_GPIO,SPI_PIN_CS);
 // SPI_ReadWriteByte(0xff); 

dma初始化設置,根據數據手冊選擇通道數:


STM32採用SPI DMA方式進行數據通信


STM32採用SPI DMA方式進行數據通信

void DMA2_Configuration(void)
{
DMA_InitTypeDef DMA_InitStructure;
DMA_DeInit(DMA2_Channel2);
DMA_InitStructure.DMA_PeripheralBaseAddr =(u32)&SPI3->DR;
DMA_InitStructure.DMA_MemoryBaseAddr = (u32)SPI3_TX_Buf;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; 
DMA_InitStructure.DMA_BufferSize = 4;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; 
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; 
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA2_Channel2, &DMA_InitStructure);

DMA_ITConfig(DMA2_Channel2, DMA_IT_TC, ENABLE);

DMA_Cmd(DMA2_Channel2,ENABLE);
}

從機的設置跟主機一樣,區別在於GPIO的輸入輸出模式,DMA的接收數據通道,需要注意的是主從機共地,不然也會造成數據錯誤。還有可能造成從機數據錯誤的原因是時鐘的電平較低,一般都是3.3V左右,這是由硬件造成的。從機的時鐘不能高於主機時鐘,一般由主機提供時鐘信號。


分享到:


相關文章: