STM32 USART DMA 多次發送數據

最近因爲公司項目需要,希望使用 USART 通過 DMA 多次發送數據,因爲每次發送數據的內容都不一樣,所以不能採用 DMA 的循環模式,只能通過 DMA 正常模式、USART 多次請求的方式來實現,下面附上 DMA 的配置代碼

#define USART 				USART3	
#define DMA_CLK				RCC_AHB1Periph_DMA1
#define DMA_STREAM			DMA1_Stream3
#define DMA_CHANNEL			DMA_Channel_4
#define BUFFER_SIZE			12

注意:
	本文中使用的是 STM32F405 系列單片機,串口使用的 USART3 (DMA 數據流和通道參考《STM32F4xx中文參考手冊》9.3.3 功能選擇 進行選擇),請讀者參照自身情況修改。

uint8_t bufferData[BUFFER_SIZE] = {'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!'};

/* 配置 DMA1_Stream3 中斷*/
static void NVIC_Config(void)
{
	NVIC_InitTypeDef NVIC_InitStructure;

	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
	NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream3_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
}

/* 配置 DMA1 */
void DMA_Config(void)
{
	DMA_InitTypeDef DMA_InitStructure;
	RCC_AHB1PeriphClockCmd(DMA_CLK, ENABLE);

	DMA_DeInit(DMA_STREAM);		/* 復位通道 DMA_STREAM(DMA1_Stream3) */
	while(DMA_GetCmdStatus(DMA_STREAM)); /* 等待通道 DMA_STREAM(DMA1_Stream3)復位完成 */

	DMA_InitStructure.DMA_Channel = DMA_CHANNEL;
	DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) (&USART->DR);		/* 外設基址爲串口的 DR 寄存器地址 */
	DMA_InitStructure.DMA_Memory0BaseAddr = (uint32) srcData;
	DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;		/* 設置傳輸模式爲從存儲器到外設模式 */
	DMA_InitStructure.DMA_BufferSize = (uint32_t) BUFFER_SIZE;
	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_Prioriry_High;
	DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
	DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
	DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
	DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;

	DMA_Init(DMA_STREAM, &DMA_InitStructure);

	DMA_Cmd(DMA_STREAM, ENABLE);
	NVIC_Config();
	DMA_ITConfig(DMA_STREAM, DMA_IT_TC, ENABLE);	/* 使能 DMA_STREAM 傳輸完成中斷 */

	while(!DMA_GetCmdStatus(DMA_STREAM));	/* 等待 DMA_STREAM 初始化完成*/
}

/* DMA_STREAM 傳輸完成中斷服務函數 */
void DMA1_Stream3_IRQHandler(void)
{
	if(DMA_GetITStatus(DMA_STREAM, DMA_IT_TCIF3))	/* 獲取 DMA_STREAM 傳輸完成中斷標誌 */
	{
		USART_DMACmd(USART, USART_DMAReq_Tx, DISABLE);		/* 失能串口發送請求 */
		DMA_Cmd(DMA_STREAM, DISABLE);		/* 失能 DMA_STREAM */
		DMA_ClearITPendingBit(DMA_STREAM, DMA_IT_TCIF3);	/* 清除 DMA_STREAM 傳輸完成中斷標誌位,否則程序會無限陷入中斷 */
		DMA_Cmd(DMA_STREAM, ENABLE);	/* 重新使能 DMA_STREAM */
	}
}

/* 延時函數 */
void delay_ms(uint16_t time)
{
	uint16_t count;
	while(time--)
	{
		count = 12000;
		count--;
	}
}

/* main 函數 */
int main(void)
{
	USART_Config();		/* 該函數省略,有興趣的朋友可以看我上一篇文章的配置方式 */
	DMA_Config();

	while(1)
	{
		printf("\r\n");
		USART_DMACmd(USART, USART_DMAReq_Tx, DISABLE);		/* 使能串口發送請求 */
		delay_ms(2 * 1000);
	}
}

這樣只需要改變 bufferData 的內容後再調用 USART_DMACmd(USART, USART_DMAReq_Tx, DISABLE) 就能多次發送數據了



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