stm32使用spi1在slave 模式下 dma 讀取數據

初始化 spi1 ,要外部 片選了 pa4 才能進行通信,

pMem=OSMemGet(OSMemC2B,&err);是 ucos2 的函數,就是獲得一片內存,可以直接指定一個數組 代替

void InitSpi1DmaRec(void)
{
	INT8U err,*pMem,*pTmp;
	SPI_InitTypeDef SPI_InitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;	 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 |GPIO_Pin_5 | GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	//GPIO_SetBits(GPIOA, GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7);
	SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
	SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;	   
	SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;	 
	SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;				//空閒時鐘爲高電平		 
	SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;			//第二個跳變開始採樣
	SPI_InitStructure.SPI_NSS = SPI_NSS_Hard;
	SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2; 
	SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_LSB;	   
	SPI_InitStructure.SPI_CRCPolynomial = 7;
	SPI_Init(SPI1, &SPI_InitStructure);
	//SPI_Cmd(SPI1,ENABLE);									//啓動接收

	SPI_Cmd(SPI1, ENABLE);	
	Dma_Rx_Init(DMA1_Channel2,(INT32U)&SPI1->DR,0);
	SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Rx, ENABLE);

	pMem=OSMemGet(OSMemC2B,&err);
	DmaGetData(DMA1_Channel2, pMem, 256, &pTmp);
}

在PA4 的外部中斷中 獲取數據,並傳遞消息,DmaGetData 是讀取dma 數據,並寫入下一個 內存塊進去

void EXTI4_IRQHandler(void)
{
	INT8U *pMem,*pRet,err;
	INT32U msg,len;
	OSIntEnter();
	pMem=OSMemGet(OSMemC2B,&err);
	if(err==OS_ERR_NONE)
	{
		len=DmaGetData(DMA1_Channel2, pMem, 256, &pRet);	
		msg=(((INT32U)pRet-(INT32U)OSMemBufC2B)/sizeof(OSMemBufC2B[0]))+(len<<8);
		OSQPost(OSQTm1629,(void*)msg);
	}
	CplLed(0);
	EXTI_ClearITPendingBit(EXTI_Line4);  //清除EXTI0線路掛起位
	OSIntExit();
}

 

dma 的操作函數

/*
	USART_DMACmd(USARTX,USART_DMAReq_Tx,ENABLE);
	DmaSendData(DMA1_Channel4,(INT8U*)tmpStr,sizeof(tmpStr));
*/
/*---- D M A _   I N I T ----
【功能】:****
【參數】:****
【返回】:****
【說明】:如果採用ucos的話,初始化要放在 	OSInit() 之後,因爲採用信號量
--------------作者:盧傑西   2009年10月4日 星期日20:30:13--------------------------------*/
//USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);
void Dma_Tx_Init(DMA_Channel_TypeDef* chn,u32 dstAddr,u8 bInt)
{
	DMA_InitTypeDef    DMA_InitStructure;
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);								//啓動DMA時鐘
	/* DMA1 Channel7 configuration ----------------------------------------------*/
	DMA_DeInit(chn);
	DMA_InitStructure.DMA_PeripheralBaseAddr = dstAddr;								//(u32)USART2_DR_Address;	//外設地址
	DMA_InitStructure.DMA_MemoryBaseAddr = (u32)0;										//內存地址,發送時候
	DMA_InitStructure.DMA_DIR =DMA_DIR_PeripheralDST;									// DMA_DIR_PeripheralSRC;								//
	DMA_InitStructure.DMA_BufferSize = 0;
	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(chn, &DMA_InitStructure);	

	/*
	#define DMA1_Channel1_BASE    (AHBPERIPH_BASE + 0x0008)
	#define DMA1_Channel2_BASE    (AHBPERIPH_BASE + 0x001C)
	#define DMA1_Channel3_BASE    (AHBPERIPH_BASE + 0x0030)
	#define DMA1_Channel4_BASE    (AHBPERIPH_BASE + 0x0044)
	#define DMA1_Channel5_BASE    (AHBPERIPH_BASE + 0x0058)
	#define DMA1_Channel6_BASE    (AHBPERIPH_BASE + 0x006C)
	#define DMA1_Channel7_BASE    (AHBPERIPH_BASE + 0x0080)
	*/

	if(bInt)
	{
		NVIC_InitTypeDef NVIC_InitStructure;
		/* Enable the USART1 Interrupt */
		NVIC_InitStructure.NVIC_IRQChannel =DMA1_Channel1_IRQChannel+((u32)chn-(u32)DMA1_Channel1)/0x14;; //DMAChannel7_IRQChannel;
		NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = IRQPreemptionPriority;
		NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
		NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
		NVIC_Init(&NVIC_InitStructure);
		DMA_ITConfig(chn,DMA_IT_TC,ENABLE);
	}
}

void Dma_Rx_Init(DMA_Channel_TypeDef* chn,u32 srcAddr,u8 bInt)
{
	DMA_InitTypeDef    DMA_InitStructure;
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);								//啓動DMA時鐘
	/* DMA1 Channel7 configuration ----------------------------------------------*/
	DMA_DeInit(chn);
	DMA_InitStructure.DMA_PeripheralBaseAddr = srcAddr;									//(u32)USART2_DR_Address;	//外設地址
	DMA_InitStructure.DMA_MemoryBaseAddr = (u32)0;										//內存地址,發送時候
	DMA_InitStructure.DMA_DIR =DMA_DIR_PeripheralSRC;									// DMA_DIR_PeripheralSRC;								//
	DMA_InitStructure.DMA_BufferSize = 0;
	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(chn, &DMA_InitStructure);
	if(bInt)
	{
		NVIC_InitTypeDef NVIC_InitStructure;
		/* Enable the USART1 Interrupt */
		NVIC_InitStructure.NVIC_IRQChannel =DMA1_Channel1_IRQChannel+((u32)chn-(u32)DMA1_Channel1)/0x14;; //DMAChannel7_IRQChannel;
		NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = IRQPreemptionPriority;
		NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
		NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
		NVIC_Init(&NVIC_InitStructure);
		DMA_ITConfig(chn,DMA_IT_TC,ENABLE);
	}	
}

void DmaSendData(DMA_Channel_TypeDef* pDmaChnl,INT8U* pSrc,INT32U len)
{
	DMA_Cmd(pDmaChnl,DISABLE);				//停止使能 才能修改計數器
	pDmaChnl->CNDTR=len;
	pDmaChnl->CMAR=(INT32U)pSrc;
	DMA_Cmd(pDmaChnl,ENABLE);				//啓動發送	
}

INT8U DmaGetData(DMA_Channel_TypeDef* pDmaChnl,INT8U *pDst,INT32U max,INT8U **ppDat)
{
	INT8U cnt=0;
	DMA_Cmd(pDmaChnl,DISABLE);												//停止使能 才能修改計數器
	DMA_ClearFlag(DMA_IT_TC<<(((u32)pDmaChnl-(u32)DMA1_Channel1)/5));		//清除傳輸完成標識 
	*ppDat=(INT8U*)pDmaChnl->CMAR;
	cnt=max-pDmaChnl->CNDTR;
	pDmaChnl->CMAR=(INT32U)pDst;
	pDmaChnl->CNDTR=max;
	DMA_Cmd(pDmaChnl,ENABLE);													//啓動接收
	return cnt;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章