STM32 DMA+IDLE实现不定长数据接收

STM32 DMA+IDLE

1.步骤

1.打开STM32cubemx,我的版本号是4.27.0,新建工程,选择芯片,例如STM32F103R8T6
2.左侧使能串口1,sys那里选择serial wire,否则导致后面无法下载程序,配置时钟树,使能串口中断
3.在configuration页面配置DMA,如下所示
在这里插入图片描述
4.点击生成代码,在keil打开,在HAL_UART_IRQHandler(&huart1);前面添加 UsartReceive_IDLE(&huart1);此函数实现如下:

void UsartReceive_IDLE(UART_HandleTypeDef *huart)//IDLE接收数据
{
    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->CNDTR;
        UsartType.RX1_Size =  RX_LEN - temp;
        UsartType.RX_flag=1;
        HAL_UART_Receive_DMA(&huart1,(uint8_t *)UsartType.RX1_pData,RX_LEN);
    }

}

在主程序前面使能DMA接收,使能串口idle中断

#define  RX1_LEN   300
typedef struct
{
    uint8_t  RX1_flag;
    uint16_t RX1_Size;
    uint8_t  RX1_pData[RX1_LEN];
} USART1_RECEIVETYPE;

void  DMA4_START()//开启DMA
{
    HAL_UART_Receive_DMA(&huart1, (uint8_t *) Usart1Type.RX1_pData, RX1_LEN);
    __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);
}

main里面轮询flag就行,数据分析判断,清除flag

int main(void)
{
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_DMA_Init();
    MX_USART1_UART_Init();
    /* USER CODE BEGIN 2 */
    DMA1_START();//开启DMA
    /* USER CODE END 2 */
    /* Infinite loop */
    /* USER CODE BEGIN WHILE */
    while (1)
    {
        /* USER CODE END WHILE */
        /* USER CODE BEGIN 3 */
        if(Usart1Type.RX1_flag == 1)
        {
         //数据处理
         Usart1Type.RX1_flag = 0;	// clean flag
        Usart1Type.RX1_Size = 0;
        memset(Usart1Type.RX1_pData, 0, sizeof(Usart1Type.RX1_pData));
        }
  
    }
    /* USER CODE END 3 */
}

或者在中断清标志
在这里插入图片描述
回调处理
在这里插入图片描述

2.单独DMA方式

void UART4_IRQHandler(void)
{
    uint8_t data = 0;
    data = data;
    if(USART_GetITStatus(LoraUSARTx, USART_IT_RXNE) == SET)
    {
        USART_ClearITPendingBit(LoraUSARTx, USART_IT_RXNE);
        if(Lora_RecvData.Rx_over == 0)
            Lora_RecvData.RxBuf[Lora_RecvData.Rx_count++] = LoraUSARTx->DR;
    }
    if(USART_GetITStatus(LoraUSARTx, USART_IT_IDLE) == SET)
    {
        data = LoraUSARTx->SR;
        data = LoraUSARTx->DR;
        
        Lora_RecvData.Rx_over = 1; //接收完成,主程序查询此flag
    }
}

参考以下文章:
http://www.firebbs.cn/thread-24555-1-1.html
http://www.firebbs.cn/thread-23695-1-1.html
http://www.waveshare.net/study/article-644-1.html

2.空闲时间

在这里插入图片描述
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值