STM32使用UART DMA实现不定长数据空闲中断

本文使用STM32CubeMX,STM32F103RCT6

1,在Pinout中激活USART1和USART2


2,在Configration 中点击Connectivity-> USART1 设置参数


DMA设置如下


3,在Configration 中点击Connectivity-> USART2 设置参数


DMA设置如下



两个USART波特率并不一致

4,生成初始化代码,

5,在usart.h中修改如下内容

/* USER CODE BEGIN Private defines */

#define RECEIVELEN 128  
#define USART_DMA_SENDING 1//发送未完成  
#define USART_DMA_SENDOVER 0//发送完成  
     
typedef struct  
{  
uint8_t receive_flag:1;//空闲接收标记  
uint8_t dmaSend_flag:1;//发送完成标记  
uint16_t rx_len;//接收长度  
uint8_t usartDMA_rxBuf[RECEIVELEN];//DMA接收缓存  
}USART_RECEIVETYPE;  
   
extern USART_RECEIVETYPE UsartType1,UsartType2;  

void UsartReceive_IDLE(UART_HandleTypeDef *huart);
void Usart1SendData_DMA(uint8_t *pdata, uint16_t Length);
void Usart2SendData_DMA(uint8_t *pdata, uint16_t Length);
     
/* USER CODE END Private defines */

6,在usart.c中修改如下内容

/* USER CODE BEGIN 0 */
USART_RECEIVETYPE UsartType1,UsartType2; 
/* USER CODE END 0 */
/* USER CODE BEGIN 1 */

#ifdef __GNUC__  
  
  /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf 
 set to 'Yes') calls __io_putchar() */  
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)  
#else  
  
  #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)  
#endif /* __GNUC__ */  
      
PUTCHAR_PROTOTYPE  
{  
    HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF);  
    return ch;  
}  
  
//DMA发送函数  
void Usart1SendData_DMA(uint8_t *pdata, uint16_t Length)  
{  
    while(UsartType1.dmaSend_flag == USART_DMA_SENDING);  
    UsartType1.dmaSend_flag = USART_DMA_SENDING;  
    HAL_UART_Transmit_DMA(&huart1, pdata, Length);  
}  

void Usart2SendData_DMA(uint8_t *pdata, uint16_t Length)  
{  
    while(UsartType2.dmaSend_flag == USART_DMA_SENDING);  
    UsartType2.dmaSend_flag = USART_DMA_SENDING;  
    HAL_UART_Transmit_DMA(&huart2, pdata, Length);  
}  
  
//DMA发送完成中断回调函数  
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)  
{  
     __HAL_DMA_DISABLE(huart->hdmatx); 
		if(	huart->Instance == huart1.Instance)
			UsartType1.dmaSend_flag = USART_DMA_SENDOVER;  
		if(	huart->Instance == huart2.Instance)
			UsartType2.dmaSend_flag = USART_DMA_SENDOVER;  
}  
  
//串口接收空闲中断  
void UsartReceive_IDLE(UART_HandleTypeDef *huart)  
{  
    uint32_t temp;  
  
    if((__HAL_UART_GET_FLAG(huart,UART_FLAG_IDLE) != RESET))  
    {   
        __HAL_UART_CLEAR_IDLEFLAG(huart);  
        HAL_UART_DMAStop(huart); 
				if(huart->Instance == huart1.Instance)
				{
					temp = huart1.hdmarx->Instance->CNDTR;  
					UsartType1.rx_len =  RECEIVELEN - temp;   
					UsartType1.receive_flag=1;  
					HAL_UART_Receive_DMA(&huart1,UsartType1.usartDMA_rxBuf,RECEIVELEN);  
				}
				if(huart->Instance == huart2.Instance)
				{
					temp = huart2.hdmarx->Instance->CNDTR;  
					UsartType2.rx_len =  RECEIVELEN - temp;   
					UsartType2.receive_flag=1;  
					HAL_UART_Receive_DMA(&huart2,UsartType2.usartDMA_rxBuf,RECEIVELEN); 
				}
    }  
}  

/* USER CODE END 1 */

7,在stm32f1xx_it.c中修改如下内容

/**
* @brief This function handles USART1 global interrupt.
*/
void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */

     UsartReceive_IDLE(&huart1); 
    
  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */

  /* USER CODE END USART1_IRQn 1 */
}

/**
* @brief This function handles USART2 global interrupt.
*/
void USART2_IRQHandler(void)
{
  /* USER CODE BEGIN USART2_IRQn 0 */
    
      UsartReceive_IDLE(&huart2); 
    
  /* USER CODE END USART2_IRQn 0 */
  HAL_UART_IRQHandler(&huart2);
  /* USER CODE BEGIN USART2_IRQn 1 */

  /* USER CODE END USART2_IRQn 1 */
}

8,在main.c中修改如下内容

  /* USER CODE BEGIN 2 */

    HAL_UART_Receive_DMA(&huart1, UsartType1.usartDMA_rxBuf, RECEIVELEN);
    __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);

    HAL_UART_Receive_DMA(&huart2, UsartType2.usartDMA_rxBuf, RECEIVELEN);
    __HAL_UART_ENABLE_IT(&huart2, UART_IT_IDLE);

  /* USER CODE END 2 */

9,接收判断(空闲时才触发)

       if(UsartType1.receive_flag) {             
            UsartType1.receive_flag = 0;
        }

可通过 UsartType1.rx_len 获取数据长度

10,发送数据

Usart1SendData_DMA(&data,1);
Usart2SendData_DMA(&data,1);











评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值