打印
[其他ST产品]

STM32CubeMX 串口空闲中断加DMA 实现不定长度收发数据

[复制链接]
188|19
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
kzlzqi|  楼主 | 2023-9-20 15:04 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
这里教程是选择的STM32F407。STM32F103也测试过。

1.首先选择串口,选择异步通信。


2.添加DMA


3.打开中断


4.生成代码,生成代码选择了每个外设单独使用.c/.h


5.我使用的是Keil5。打开工程,首先注释掉dma.c里的DMA接收中断,因为不需要DMA接收中断,DMA发送中断是需要的。(dma.c)


void MX_DMA_Init(void) 
{
  /* DMA controller clock enable */
  __HAL_RCC_DMA2_CLK_ENABLE();

  /* DMA interrupt init */
  /* DMA2_Stream0_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 2, 0);
  HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
  /* DMA2_Stream2_IRQn interrupt configuration */
//  HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, 0, 0);
//  HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn);
  /* DMA2_Stream7_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA2_Stream7_IRQn, 1, 0);
  HAL_NVIC_EnableIRQ(DMA2_Stream7_IRQn);

}


使用特权

评论回复
沙发
kzlzqi|  楼主 | 2023-9-20 16:00 | 只看该作者
6.在usart.h文件里定义串口接收数据类型我是如下定义的(usart.h)

使用特权

评论回复
板凳
kzlzqi|  楼主 | 2023-9-20 16:02 | 只看该作者
/* USER CODE BEGIN Private defines */
#define RECEIVELEN 1024
#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;


/* USER CODE END Private defines */

使用特权

评论回复
地板
kzlzqi|  楼主 | 2023-9-20 16:02 | 只看该作者
7.然后在usart.c里需要添加空闲中断处理函数,以及DMA发送函数等。(usart.c)
首先定义串口数据类型:
/* USER CODE BEGIN 0 */

USART_RECEIVETYPE UsartType1;

/* USER CODE END 0 */

使用特权

评论回复
5
kzlzqi|  楼主 | 2023-9-20 16:02 | 只看该作者
然后定义空闲中断处理函数和DMA发送函数
/* 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);
}

//DMA发送完成中断回调函数
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
         __HAL_DMA_DISABLE(huart->hdmatx);
        UsartType1.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(&huart1);
                HAL_UART_DMAStop(&huart1);
                temp = huart1.hdmarx->Instance->NDTR;
                UsartType1.rx_len =  RECEIVELEN - temp;
                UsartType1.receive_flag=1;
                HAL_UART_Receive_DMA(&huart1,UsartType1.usartDMA_rxBuf,RECEIVELEN);
        }
}

/* USER CODE END 1 */

使用特权

评论回复
6
kzlzqi|  楼主 | 2023-9-20 16:06 | 只看该作者
</pre><p></p><pre>

使用特权

评论回复
7
kzlzqi|  楼主 | 2023-9-20 16:06 | 只看该作者
8.在中断文件里添加(当然,上面的空闲中断处理函数需要声明)(stm32f4xxit.c)

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 */
}

使用特权

评论回复
8
kzlzqi|  楼主 | 2023-9-20 16:06 | 只看该作者
9.主函数里,打开空闲中断,初始化DMA接收
/* USER CODE BEGIN 2 */
        HAL_UART_Receive_DMA(&huart1, UsartType1.usartDMA_rxBuf, RECEIVELEN);
        __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);
  /* USER CODE END 2 */

使用特权

评论回复
9
kzlzqi|  楼主 | 2023-9-20 16:06 | 只看该作者
10.然后就可以在while(1)里处理数据了
/* Infinite loop */
  /* USER CODE BEGIN WHILE */
       
  while (1)
  {
                if(UsartType1.receive_flag)//如果产生了空闲中断
                {
                        UsartType1.receive_flag=0;//清零标记
                        Usart1SendData_DMA(UsartType1.usartDMA_rxBuf,UsartType1.rx_len);//串口打印收到的数据。
                }
  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */
               
  }
  /* USER CODE END 3 */

使用特权

评论回复
10
AloneKaven| | 2023-9-20 21:53 | 只看该作者
空闲中断是怎么用的啊

使用特权

评论回复
11
中国龙芯CDX| | 2024-4-28 18:11 | 只看该作者
初始化DMA有哪些注意事项呢?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

71

主题

488

帖子

2

粉丝