2009-09-18 12:26 AM
SPI1 and DMA
2011-05-17 04:08 AM
Hello all!
I have a buffer SPI1_Buffer_Tx[] that I want transfer in SPI1 by using DMA and then transfer it into an external device. Buffer SPI1_Buffer_Rx[] receive data using DMA. SPI work in full-duplex mode. But i can only do the transfer when i active the DMA_Cmd in the first time (DMA and SPI do it automtically). I like transfer data one more times, but no circular. I like trigger transfer by software. void DMA1_Channel2_IRQHandler(void) { if(DMA_GetITStatus(DMA1_IT_TC2)) { DMA_ClearITPendingBit(DMA1_IT_TC2); GPIO_SetBits(GPIO_CS, GPIO_Pin_CS); } } void SPI1_DMA1_Init (void) { SPI_InitTypeDef SPI_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; DMA_InitTypeDef DMA_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); // Enable SPI1 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // Enable GPIO clocks RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); // DMA GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); // Configure SPI1 pins: SCK, MISO and MOSI GPIO_InitStructure.GPIO_Pin = GPIO_Pin_CS; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIO_CS, &GPIO_InitStructure); // Configure I/O for Chip select GPIO_SetBits(GPIO_CS, GPIO_Pin_CS); SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_Init(SPI1, &SPI_InitStructure); // SPI1 configuration DMA_DeInit(DMA1_Channel2); // DMA1 Channel2 configuration DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)SPI1_DR_Address; DMA_InitStructure.DMA_MemoryBaseAddr = (u32)SPI1_Buffer_Rx; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = SPI1_BufferSize; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel2, &DMA_InitStructure); DMA_DeInit(DMA1_Channel3); // DMA1 Channel3 configuration DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)SPI1_DR_Address; DMA_InitStructure.DMA_MemoryBaseAddr = (u32)SPI1_Buffer_Tx; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_Priority = DMA_Priority_Low; DMA_Init(DMA1_Channel3, &DMA_InitStructure); DMA_ITConfig(DMA1_Channel2, DMA_IT_TC, ENABLE); // Enable Channel2 Transfer complete interrupt NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); // Configure none bit for preemption priority NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel2_IRQChannel; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 10; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); // Enable the DMA1 Channel 2 Interrupt SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE); // Enable SPI1 DMA Tx request SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Rx, ENABLE); // Enable SPI1 DMA Rx request SPI_Cmd(SPI1, ENABLE); // Enable SPI1 GPIO_ResetBits(GPIO_CS, GPIO_Pin_CS); DMA_Cmd(DMA1_Channel2, ENABLE); // Enable DMA1 channel2 DMA_Cmd(DMA1_Channel3, ENABLE); // Enable DMA1 channel3 } void SPI_Send_Packet () { \\ ??? } What must by written in ''SPI_Send_Packet()'' function for send SPI1_Buffer_Tx[] buffer? Can me anybody help, please? Thanks2011-05-17 04:08 AM
Hi,
Try this void SPI_Send_Packet () { // disable the dma1 channel3 (spi1 tx) DMA_Cmd(DMA1_Channel3,DISABLE); // reset the counter DMA1_Channel3->CNTR = SPI1_BufferSize; // restart DMA DMA_Cmd(DMA1_Channel3,ENABLE); }2011-05-17 04:08 AM
Dear use this it is working.
i had tested and found ok. { GPIO_SetBits(GPIOC, GPIO_Pin_12); DMA_Cmd(DMA1_Channel3, DISABLE); DMA_Cmd(DMA1_Channel2, DISABLE); DMA1_Channel2->CNDTR = 3; DMA1_Channel3->CNDTR = 3; GPIO_ResetBits(GPIOC, GPIO_Pin_12); //CS (chip Select) DMA_Cmd(DMA1_Channel2, ENABLE); //Enable DMA1 channel2 (SPI1 Rx) DMA_Cmd(DMA1_Channel3, ENABLE); //Enable DMA1 channel3 (SPI1 Tx) while(!DMA_GetFlagStatus(DMA1_FLAG_TC2));//Check transfer completed while(!DMA_GetFlagStatus(DMA1_FLAG_TC3));//Check transfer completed }