硬汉嵌入式论坛

 找回密码
 立即注册
查看: 3198|回复: 7
收起左侧

[有问必答] stm32f407 为什么USART1+DMA方式通信时,主程序中记录的【发送次数】 大于 串口发送完成中断中记录的中断次数呢?

[复制链接]

13

主题

56

回帖

95

积分

初级会员

积分
95
发表于 2018-9-21 13:47:23 | 显示全部楼层 |阅读模式
硬汉:

   STM32F407的USART1采用DMA方式通信,使能了USART1的总线空闲中断(USART_IT_IDLE),使能了USART1的发送完成中断(USART_IT_TC),禁止了DMA的发送完成中断,禁止了DMA的接收完成中断。

   1、主程序中使用DMA方式发送,500毫秒发送一次,发送时增加一个计数器(USART1_MODBUS_send_count),发送一次,USART1_MODBUS_send_count+1.
   2、USART1的发送完成中断(USART_IT_TC)中增加一个计数器(__DEBUG_USART1_IT_TC),进一次发送完成中断,计数器__DEBUG_USART1_IT_TC+1.
   3、经过长时间(3个多小时)运行观察,发送次数(USART1_MODBUS_send_count)不等于 __DEBUG_USART1_IT_TC。
             发送次数 = 35671

             USART1发送完成中断次数=35659
   4、为什么会出现发送次数不等于USART1发送完成中断次数呢?

   5、难道是我的程序有问题吗?

无标题.png

评分

参与人数 1金币 +100 收起 理由
eric2013 + 100 7楼问题已经解决,给力

查看全部评分

我是新手,请多多关照。
回复

使用道具 举报

13

主题

56

回帖

95

积分

初级会员

积分
95
 楼主| 发表于 2018-9-21 13:55:04 | 显示全部楼层
以下是程序代码:


void USART1_Configuration(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
   
    USART_DeInit(USART1);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);        //for USART1 and USART6
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
        
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);         

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_Init(GPIOA, &GPIO_InitStructure);   

    USART_InitStructure.USART_BaudRate = 9600;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No ;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(USART1, &USART_InitStructure);
    USART_Cmd(USART1, ENABLE);

    USART_ClearFlag(USART1, USART_FLAG_TC); //清除发送完成标志   
    while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);  
    USART_ClearFlag(USART1, USART_FLAG_TC);    //清除发送完成标志

    USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);  
    USART_ITConfig(USART1, USART_IT_TXE, DISABLE);   
    USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);  
    USART_ITConfig(USART1, USART_IT_TC, ENABLE);   
   
    USART_DMACmd(USART1 ,   USART_DMAReq_Tx,ENABLE);  
    USART_DMACmd(USART1 ,   USART_DMAReq_Rx,ENABLE);
   
}



void USART1_IRQHandler(void)
{
    uint16_t ch;

   
    if (USART_GetITStatus(USART1,USART_IT_IDLE) != RESET)
    {        
        USART_ClearITPendingBit(USART1 , USART_IT_IDLE);
        ch =  USART_ReceiveData(USART1);
        
        __DEBUG_USART1_IT_IDLE++;
      
        DMA_Cmd(DMA2_Stream5, DISABLE);
        DMA_ClearFlag(DMA2_Stream5, DMA_FLAG_TCIF5);
        ch = USART1_DMA_RX_BUFFER_MAX_LENGTH - DMA_GetCurrDataCounter(DMA2_Stream5);
        if (ch > 0)
        {
            MB_USART1.Outtime_mark = TRUE;
            MB_USART1.receCount = ch;
            memcpy(MB_USART1.mscomm_buffer , USART1_DMA_RX_Buffer , MB_USART1.receCount);
        }

        DMA_SetCurrDataCounter(DMA2_Stream5 , USART1_DMA_RX_BUFFER_MAX_LENGTH);
        DMA_Cmd(DMA2_Stream5, ENABLE);
    }
   

    if (USART_GetITStatus(USART1,USART_IT_TC)!= RESET)
    {
        USART_ClearITPendingBit(USART1, USART_IT_TC);
        
        __DEBUG_USART1_IT_TC++;

        DMA_Cmd(DMA2_Stream7 , DISABLE);        
        DMA_ClearFlag(DMA2_Stream7, DMA_FLAG_TCIF7);            
        DMA_SetCurrDataCounter(DMA2_Stream7 , 0);
        GPIO_USART1_RS485_RECIVE_enable();
    }
}




void USART1_DMA_Tx_Config(void)
{
    DMA_InitTypeDef  DMA_InitStructure;
   
   
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 , ENABLE);                    //DMA2时钟使能
    DMA_DeInit(DMA2_Stream7);
    while (DMA_GetCmdStatus(DMA2_Stream7) != DISABLE);                        //等待DMA可配置
    DMA_InitStructure.DMA_Channel = DMA_Channel_4;                             //DMA通道配置
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR;        //DMA外设地址
    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)USART1_DMA_TX_Buffer;    //发送缓存指针
    DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;                    //DMA传输方向:内存--->外设
    DMA_InitStructure.DMA_BufferSize = USART1_DMA_TX_BUFFER_MAX_LENGTH;        //数据传输字节数量
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;        //外设非增量模式
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                    //存储器增量模式
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;    //外设数据长度:8位
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;            //存储器数据长度:8位
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                            //使用普通模式
    DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;                    //中等优先级 DMA_Priority_High
    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         
    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;                //存储器突发单次传输
    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;        //外设突发单次传输
    DMA_Init(DMA2_Stream7, &DMA_InitStructure);                                //初始化DMA Stream   
    DMA_Cmd(DMA2_Stream7, DISABLE);                                         //开启DMA传输
        DMA_ClearITPendingBit(DMA2_Stream7, DMA_IT_TCIF7);                      //清标志   
}



void USART1_DMA_Rx_Config(void)
{
    DMA_InitTypeDef  DMA_InitStructure;

   
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 , ENABLE);                    //DMA2时钟使能
    DMA_DeInit(DMA2_Stream5);
    while (DMA_GetCmdStatus(DMA2_Stream5) != DISABLE);                        //等待DMA可配置  
    DMA_InitStructure.DMA_Channel = DMA_Channel_4;                          //通道选择
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR;        //DMA外设地址
    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)USART1_DMA_RX_Buffer;    //接收缓存指针
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory ;                //DMA传输方向:外设到存储器模式:外设--->内存
    DMA_InitStructure.DMA_BufferSize = USART1_DMA_RX_BUFFER_MAX_LENGTH;        //缓冲大小
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;        //外设非增量模式
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                    //存储器增量模式
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;    //外设数据长度:8位
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;            //存储器数据长度:8位
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                            //使用普通模式
    DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;                    //中等优先级 DMA_Priority_VeryHigh
    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         
    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;                //存储器突发单次传输
    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;        //外设突发单次传输
    DMA_Init(DMA2_Stream5 , &DMA_InitStructure);                            //初始化DMA_Stream5   
    DMA_Cmd(DMA2_Stream5, ENABLE);                                          //开启DMA传输
    DMA_ClearITPendingBit(DMA2_Stream5, DMA_IT_TCIF5);                      //清标志   

}


void USART1_DMA_Begin_Send(uint8_t *send_buffer , uint16_t nSendCount)
{   
        USART1_MODBUS_send_count++;

    GPIO_USART1_RS485_SEND_enable();
    __NOP();
    __NOP();
    __NOP();
    __NOP();
    __NOP();
    __NOP();
    __NOP();
    __NOP();
    __NOP();
    __NOP();        
    if (nSendCount < USART1_DMA_TX_BUFFER_MAX_LENGTH)
    {
        memcpy(USART1_DMA_TX_Buffer , send_buffer , nSendCount);
        DMA_Cmd(DMA2_Stream7 , DISABLE);                    //关闭DMA传输
        while (DMA_GetCmdStatus(DMA2_Stream7) != DISABLE);    //确保DMA可以被设置
        DMA_SetCurrDataCounter(DMA2_Stream7 , nSendCount);  //数据传输量
        DMA_Cmd(DMA2_Stream7 , ENABLE);                       //开启DMA传输
    }
}


void NVIC_Configuration(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;
   
   
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//嵌套优先级分组为 4 , 注:SysTick的优先级默认=15

   
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;     
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);        
}


我是新手,请多多关照。
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107527
QQ
发表于 2018-9-22 01:15:27 | 显示全部楼层
帮顶下,帮楼主看了下,没发现什么问题。
回复

使用道具 举报

13

主题

56

回帖

95

积分

初级会员

积分
95
 楼主| 发表于 2018-10-16 14:24:40 | 显示全部楼层
喔,忘啦,当前是在RS485总线上测试的结果,  同样的程序我放到RS232总线上测试就没有问题,

  我在:

     1、主程序发送前,将RS485切换为发送模式
     2、在【串口发送完成】中断中,将RS485切换为接收模式。

   上述2点应该没有问题的呀!
我是新手,请多多关照。
回复

使用道具 举报

13

主题

56

回帖

95

积分

初级会员

积分
95
 楼主| 发表于 2018-10-16 14:26:30 | 显示全部楼层
而且主程序发送前,将RS485切换为发送模式的时候执行了很多延时操作,才启动DMA发送的呀!

void USART1_DMA_Begin_Send(uint8_t *send_buffer , uint16_t nSendCount)
{   
        USART1_MODBUS_send_count++;

    GPIO_USART1_RS485_SEND_enable();
    __NOP();
    __NOP();
    __NOP();
    __NOP();
    __NOP();
    __NOP();
    __NOP();
    __NOP();
    __NOP();
    __NOP();        
    if (nSendCount < USART1_DMA_TX_BUFFER_MAX_LENGTH)
    {
        memcpy(USART1_DMA_TX_Buffer , send_buffer , nSendCount);
        DMA_Cmd(DMA2_Stream7 , DISABLE);                    //关闭DMA传输
        while (DMA_GetCmdStatus(DMA2_Stream7) != DISABLE);    //确保DMA可以被设置
        DMA_SetCurrDataCounter(DMA2_Stream7 , nSendCount);  //数据传输量
        DMA_Cmd(DMA2_Stream7 , ENABLE);                       //开启DMA传输
    }
}
我是新手,请多多关照。
回复

使用道具 举报

13

主题

56

回帖

95

积分

初级会员

积分
95
 楼主| 发表于 2018-10-17 16:30:22 | 显示全部楼层
关于485总线使用USART+DMA进行通信,我已经完美解决啦!

发现如下3个问题。
  (1)、串口总线空闲中断发现1个问题
              问题1:
                       把: DMA_ClearFlag(DMA2_Stream5 , DMA_FLAG_TCIF5);
                       修改为:
  DMA_ClearFlag(DMA2_Stream5 , DMA_FLAG_TCIF5 | DMA_FLAG_FEIF5 | DMA_FLAG_DMEIF5 | DMA_FLAG_TEIF5 | DMA_FLAG_HTIF5);

  (2)、串口发送完成中断发现2个问题
              
              问题2:把 DMA_Cmd(DMA2_Stream7 , DISABLE); 这条语句屏蔽。
              问题3: DMA_ClearFlag(DMA2_Stream7 , DMA_FLAG_TCIF5);
                       修改为:
  DMA_ClearFlag(DMA2_Stream7 , DMA_FLAG_TCIF7 | DMA_FLAG_FEIF7 | DMA_FLAG_DMEIF7 | DMA_FLAG_TEIF7 | DMA_FLAG_HTIF7);
回复

使用道具 举报

13

主题

56

回帖

95

积分

初级会员

积分
95
 楼主| 发表于 2018-10-17 16:33:48 | 显示全部楼层
解决后,完整的代码如下:

  void USART1_DMA_Tx_Config(void)
{
        DMA_InitTypeDef  DMA_InitStructure;
       
       
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 , ENABLE);                                        //DMA2时钟使能
        DMA_DeInit(DMA2_Stream7);
        while (DMA_GetCmdStatus(DMA2_Stream7) != DISABLE);                                                //等待DMA可配置
        DMA_InitStructure.DMA_Channel = DMA_Channel_4;                                                         //DMA通道配置
        DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR;                //DMA外设地址
        DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)USART1_DMA_TX_Buffer;        //发送缓存指针
        DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;                                        //DMA传输方向:内存--->外设
        DMA_InitStructure.DMA_BufferSize = USART1_DMA_TX_BUFFER_MAX_LENGTH;                //数据传输字节数量
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;                //外设非增量模式
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                                        //存储器增量模式
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;        //外设数据长度:8位
        DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;                        //存储器数据长度:8位
        DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                                                        //使用普通模式
        DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;                                        //中等优先级 DMA_Priority_High
        DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         
        DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
        DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;                                //存储器突发单次传输
        DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;                //外设突发单次传输
        DMA_Init(DMA2_Stream7, &DMA_InitStructure);                                                                //初始化DMA Stream
        DMA_Cmd(DMA2_Stream7, DISABLE);                                                                                 //开启DMA传输
}



void USART1_DMA_Begin_Send(uint8_t *send_buffer , uint16_t nSendCount)
{       
        GPIO_USART1_RS485_SEND_enable();
       
        if (nSendCount < USART1_DMA_TX_BUFFER_MAX_LENGTH)
        {
                memcpy(USART1_DMA_TX_Buffer , send_buffer , nSendCount);
                DMA_Cmd(DMA2_Stream7 , DISABLE);                    //关闭DMA传输
                while (DMA_GetCmdStatus(DMA2_Stream7) != DISABLE);        //确保DMA可以被设置
                DMA_SetCurrDataCounter(DMA2_Stream7 , nSendCount);  //数据传输量
                DMA_Cmd(DMA2_Stream7 , ENABLE);                               //开启DMA传输
        }
}



void USART1_DMA_Rx_Config(void)
{
        DMA_InitTypeDef  DMA_InitStructure;

       
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 , ENABLE);                                        //DMA2时钟使能
        DMA_DeInit(DMA2_Stream5);
        while (DMA_GetCmdStatus(DMA2_Stream5) != DISABLE);                                                //等待DMA可配置  
        DMA_InitStructure.DMA_Channel = DMA_Channel_4;                                                  //通道选择
        DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR;                //DMA外设地址
        DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)USART1_DMA_RX_Buffer;        //接收缓存指针
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory ;                                //DMA传输方向:外设到存储器模式:外设--->内存
        DMA_InitStructure.DMA_BufferSize = USART1_DMA_RX_BUFFER_MAX_LENGTH;                //缓冲大小
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;                //外设非增量模式
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                                        //存储器增量模式
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;        //外设数据长度:8位
        DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;                        //存储器数据长度:8位
        DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                                                        //使用普通模式
        DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;                                        //中等优先级 DMA_Priority_VeryHigh
        DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         
        DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
        DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;                                //存储器突发单次传输
        DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;                //外设突发单次传输
        DMA_Init(DMA2_Stream5 , &DMA_InitStructure);                                                        //初始化DMA_Stream5       
        DMA_Cmd(DMA2_Stream5, ENABLE);                                                                                  //开启DMA传输
}


void USART1_Configuration(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;
        USART_InitTypeDef USART_InitStructure;
       
        USART_DeInit(USART1);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);                //for USART1 and USART6
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
               
        GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);
        GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);            

        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);

        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
        GPIO_Init(GPIOA, &GPIO_InitStructure);       

        USART_InitStructure.USART_BaudRate = 9600;
        USART_InitStructure.USART_WordLength = USART_WordLength_8b;
        USART_InitStructure.USART_StopBits = USART_StopBits_1;
        USART_InitStructure.USART_Parity = USART_Parity_No ;
        USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
        USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
        USART_Init(USART1, &USART_InitStructure);
        USART_Cmd(USART1, ENABLE);


        USART_ClearFlag(USART1, USART_FLAG_TC); //清除发送完成标志       
        while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);        //等待空闲帧发送完成后再清零发送完成标志
        USART_ClearFlag(USART1, USART_FLAG_TC);        //清除发送完成标志


    USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);                                //禁止USART1接收不为空中断
        USART_ITConfig(USART1, USART_IT_TXE, DISABLE);                                //禁止USART1发送空中断
        USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);                                //开启USART1空闲中断
        USART_ITConfig(USART1, USART_IT_TC, ENABLE);                                //使能USART1传输完成中断
       
        USART_DMACmd(USART1 ,   USART_DMAReq_Tx,ENABLE);                          //使能串口的DMA发送
        USART_DMACmd(USART1 ,   USART_DMAReq_Rx,ENABLE);                          //使能串口的DMA接收
       
}




void USART1_IRQHandler(void)
{
        uint16_t ch;

       
        if (USART_GetITStatus(USART1,USART_IT_IDLE) != RESET)
        {               
                USART_ClearITPendingBit(USART1 , USART_IT_IDLE);       
//必须先清除总线空闲中断标识,然后读一下数据寄存器,DMA接收才会正确(先读SR,然后读DR才能清除空闲中断标识)注意:这句必须要,否则不能够清除中断标志位。
                ch =  USART_ReceiveData(USART1);
//必须先清除总线空闲中断标识,然后读一下数据寄存器,DMA接收才会正确(先读SR,然后读DR才能清除空闲中断标识)注意:这句必须要,否则不能够清除中断标志位。
               
                #ifdef __DEBUG_stm32f407__
                        __DEBUG_USART1_IT_IDLE++;
                #endif
               
                DMA_Cmd(DMA2_Stream5 , DISABLE);                         //关闭DMA,防止处理其间有数据
                DMA_ClearFlag(DMA2_Stream5 , DMA_FLAG_TCIF5 | DMA_FLAG_FEIF5 | DMA_FLAG_DMEIF5 | DMA_FLAG_TEIF5 | DMA_FLAG_HTIF5);//清零标志位
                ch = USART1_DMA_RX_BUFFER_MAX_LENGTH - DMA_GetCurrDataCounter(DMA2_Stream5);
                if (ch > 0)
                {
                        MB_USART1.Outtime_mark = TRUE;
                        MB_USART1.receCount = ch;
                        memcpy(MB_USART1.mscomm_buffer , USART1_DMA_RX_Buffer , MB_USART1.receCount);
                }
               
                DMA_SetCurrDataCounter(DMA2_Stream5 , USART1_DMA_RX_BUFFER_MAX_LENGTH);
                DMA_Cmd(DMA2_Stream5, ENABLE);
        }
       
        else if (USART_GetITStatus(USART1,USART_IT_TC)!= RESET)
        {
                USART_ClearITPendingBit(USART1, USART_IT_TC);
               
                #ifdef __DEBUG_stm32f407__
                        __DEBUG_USART1_IT_TC++;
                #endif
               
                //DMA_Cmd(DMA2_Stream7 , DISABLE);
                DMA_ClearFlag(DMA2_Stream7 , DMA_FLAG_TCIF7 | DMA_FLAG_FEIF7 | DMA_FLAG_DMEIF7 | DMA_FLAG_TEIF7 | DMA_FLAG_HTIF7);//清零标志位
                DMA_SetCurrDataCounter(DMA2_Stream7 , 0);        //清除数据长度
                GPIO_USART1_RS485_RECIVE_enable();
        }
       
}


回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107527
QQ
发表于 2018-10-18 11:01:16 | 显示全部楼层
ba_wang_mao 发表于 2018-10-17 16:33
解决后,完整的代码如下:

  void USART1_DMA_Tx_Config(void)

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-6-5 00:40 , Processed in 0.262081 second(s), 29 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表