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);











  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
使用STM32的串口空闲中断DMA可以实现接收不定数据的功能,具体步骤如下: 1. 配置串口和DMA 首先需要配置串口和DMA,使其能够正常工作。具体配置方法可以参考STM32的官方文档或者其他相关资料。 2. 配置接收数组和接收计数器 在代码中定义一个接收数组和一个接收计数器,用于存储接收到的数据和记录接收到的数据度。 3. 配置空闲中断空闲中断中判断接收数据是否完成,如果完成则将接收到的数据发送出去。具体实现方法如下: ```c void HAL_UART_IDLECallback(UART_HandleTypeDef *huart) { if(huart->Instance == USART1) { uint32_t tmp_flag = 0; uint32_t temp; tmp_flag = __HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE); //获取空闲中断标志 if((tmp_flag != RESET)) //判断是否是空闲中断 { __HAL_UART_CLEAR_IDLEFLAG(&huart1); //清除空闲中断标志 HAL_UART_DMAStop(&huart1); //停止DMA传输 temp = huart1.hdmarx->Instance->CNDTR; //获取DMA缓存区剩余数据uart1_rx_len = UART_RCV_BUF_SIZE - temp; //计算接收到的数据度 HAL_UART_Transmit(&huart1, uart1_rx_buf, uart1_rx_len, 0xffff); //将接收到的数据发送出去 HAL_UART_Receive_DMA(&huart1, uart1_rx_buf, UART_RCV_BUF_SIZE); //重新开启DMA传输 } } } ``` 4. 启动DMA传输 在代码中启动DMA传输,将串口接收到的数据存储到接收数组中。具体实现方法如下: ```c HAL_UART_Receive_DMA(&huart1, uart1_rx_buf, UART_RCV_BUF_SIZE); ``` 以上就是使用STM32的串口空闲中断DMA实现接收不定数据的方法。如果您有任何问题,请随时提出。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值