2-串口DMA发送、接收

usart.c

UART_HandleTypeDef husartx;					//串口句柄
DMA_HandleTypeDef hdma_usartx_tx;	        //DMA发送句柄
DMA_HandleTypeDef hdma_usartx_rx;           //DMA接收句柄

void all_usart_init(void)
{
	husartx.Instance = USART1;
	husartx.Init.BaudRate = 115200;
	husartx.Init.WordLength = UART_WORDLENGTH_8B;
	husartx.Init.StopBits = UART_STOPBITS_1;
	husartx.Init.Parity = UART_PARITY_NONE;
	husartx.Init.Mode = UART_MODE_TX_RX;
	husartx.Init.HwFlowCtl = UART_HWCONTROL_NONE;
	husartx.Init.OverSampling = UART_OVERSAMPLING_16;
	HAL_UART_Init(&husartx);

	HAL_NVIC_SetPriority(USART1_IRQn, 1, 0);
	HAL_NVIC_EnableIRQ(USART1_IRQn);
	
	__HAL_UART_ENABLE_IT(&husartx, UART_IT_IDLE); 			  //开启总线空闲中断,用于DMA接收
	HAL_UART_Receive_DMA(&husartx,array.lcd_rx_buff, 50);	  //开启DMA传输(函数内部开启DMA),为第一次接收数据做准备,否则第一帧数据接收不到。此函数应放在DMA初始化和中断配置之后,否则程序卡死。
}

void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{
  GPIO_InitTypeDef GPIO_InitStruct;
  if(huart->Instance==USART1)
  {
    __HAL_RCC_GPIOA_CLK_ENABLE();
	__HAL_RCC_USART1_CLK_ENABLE();
	__HAL_RCC_DMA1_CLK_ENABLE();
  
    GPIO_InitStruct.Pin = GPIO_PIN_9;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
	  
	hdma_usartx_tx.Instance = DMA1_Channel4;						//DMA发送通道配置
    hdma_usartx_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_usartx_tx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_usartx_tx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_usartx_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_usartx_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_usartx_tx.Init.Mode = DMA_NORMAL;
    hdma_usartx_tx.Init.Priority = DMA_PRIORITY_HIGH;
    HAL_DMA_Init(&hdma_usartx_tx);
	__HAL_LINKDMA(&husartx,hdmatx,hdma_usartx_tx);
	
	hdma_usartx_rx.Instance = DMA1_Channel5;						//DMA接收通道配置
    hdma_usartx_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_usartx_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_usartx_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_usartx_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_usartx_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_usartx_rx.Init.Mode = DMA_NORMAL;
    hdma_usartx_rx.Init.Priority = DMA_PRIORITY_HIGH;
    HAL_DMA_Init(&hdma_usartx_rx);
	__HAL_LINKDMA(&husartx,hdmarx,hdma_usartx_rx);	
  }
}

void USART1_IRQHandler(void)
{
	if((__HAL_UART_GET_FLAG(&husartx,UART_FLAG_IDLE)!= RESET))		//串口1总线空闲中断判断
	{
		__HAL_UART_CLEAR_IDLEFLAG(&husartx);						//清除总线空闲中断标志位,内部读取DR/SR寄存器
		flag.lcd_rx=1;
		HAL_UART_DMAStop(&husartx);									//关闭DMA,用于数据长度计算
		
		lcd_rx_length = 50 - __HAL_DMA_GET_COUNTER(&hdma_usartx_rx);  //传输数据长度 = 接收数组总长度 - 未传输数据长度
		
		HAL_UART_Receive_DMA(&husartx,array.lcd_rx_buff, 50);		//重新开启DMA传输
	}
}

void lcd_dma_send(uint8_t *data,uint8_t len)
{
	HAL_UART_Transmit_DMA(&husartx,data,len);
	while(1)
	{
		if ( __HAL_DMA_GET_FLAG(&hdma_usartx_tx, DMA_FLAG_TC4))  	//等待DMA1_CH4传输完成,无此步骤DMA只能发送一次,串口进入busy状态,无法再次发送
		{
			__HAL_DMA_CLEAR_FLAG(&hdma_usartx_tx, DMA_FLAG_TC4);	//清除传输完成标志位
			HAL_UART_DMAStop(&husartx);             				//传输完成后关闭DMA发送传输
			HAL_UART_Receive_DMA(&husartx,array.lcd_rx_buff, 50);  //发送完一帧数据后,再接收数据,会因为上述关闭DMA而导致第一帧数据接收不到,只能从第二帧开始才能正确接收。因此,需要在传输完成关闭DMA后,重新开启DMA接收,这样第一帧数据才能正确接收
			break;
		}		
	}
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值