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, ENABLE);		/* 使能串口发送请求 */
		delay_ms(2 * 1000);
	}
}

 

这样只需要改变 bufferData 的内容后再调用 USART_DMACmd(USART, USART_DMAReq_Tx, DISABLE) 就能多次发送数据了

 

 

 

你可能感兴趣的:(STM32)