打印
[STM32F4]

求助串口DMA发送,只能发送一次

[复制链接]
2855|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
gowow|  楼主 | 2016-10-14 14:15 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
设置成发送10个字节,延时1秒发送一次。
串口助手上只能看到首次发送的10字节,后面就没了。但是中断还是大概1秒进一次,求看看哪里有什么问题

  void DMA1_Stream4_IRQHandler(void)
  {
    if (DMA_GetFlagStatus(DMA1_Stream4, DMA_FLAG_TCIF4) != RESET)
    {
      DMA_ClearFlag(DMA1_Stream4, DMA_FLAG_TCIF4);
    }
  }

static u8 memory_addr[] ="0123456789";
static void UART4_init(u32 bps)
{
  USART_InitTypeDef USART_InitStructure;
  GPIO_InitTypeDef GPIO_InitStructure;
  DMA_InitTypeDef DMA_InitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;

  //uart config
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4, ENABLE);
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

  GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_UART4);

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  GPIO_Init(GPIOC, &GPIO_InitStructure);

  GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_UART4);
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_1;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  USART_InitStructure.USART_BaudRate = bps;
  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(UART4, &USART_InitStructure);

  //dma config
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
    DMA_Cmd(DMA1_Stream4, DISABLE);
    DMA_DeInit(DMA1_Stream4);

    DMA_InitStructure.DMA_Channel = DMA_Channel_4;
    DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&(UART4->DR));
    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)memory_addr;
    DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
    DMA_InitStructure.DMA_BufferSize = (uint32_t)10;
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
    DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
    DMA_Init(DMA1_Stream4, &DMA_InitStructure);

    DMA_ClearFlag(DMA1_Stream4, DMA_FLAG_TCIF4);
    DMA_ITConfig(DMA1_Stream4, DMA_IT_TC, ENABLE);

    NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream4_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    DMA_Cmd(DMA1_Stream4, DISABLE);  


  USART_DMACmd(UART4, USART_DMAReq_Tx, ENABLE);
  //USART_DMACmd(UART4, USART_DMAReq_Rx, ENABLE);
  USART_Cmd(UART4, ENABLE);

  while(1)
  {
    //dma send
    DMA1_Stream4->M0AR = (u32)memory_addr;
    DMA1_Stream4->NDTR = 10;
                DMA_Cmd(DMA1_Stream4, ENABLE);
   
    OSTimeDly(1000);
  }

  
}
沙发
gowow|  楼主 | 2016-10-14 15:36 | 只看该作者
把这**中的改成UART4,也只能发送一次,难道是UART4里有什么配错了吗?
http://blog.csdn.net/jdh99/article/details/43307121

使用特权

评论回复
板凳
gowow|  楼主 | 2016-10-14 15:37 | 只看该作者
/*********************************************************************
*                                                        初始化串口
**********************************************************************/
static u8 mem_addr[] ="0123456789";
void init_uart(void)
{
        //定义中断结构体
        NVIC_InitTypeDef NVIC_InitStructure ;
        //定义IO初始化结构体
        GPIO_InitTypeDef GPIO_InitStructure;
        //定义串口结构体  
        USART_InitTypeDef USART_InitStructure;
        //定义DMA结构体
        DMA_InitTypeDef DMA_InitStructure;

        //打开串口对应的外设时钟  
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4, ENABLE);
         
        //串口发DMA配置  
        //启动DMA时钟
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
        //DMA发送中断设置
        NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream4_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
        //DMA通道配置
        DMA_DeInit(DMA1_Stream4);
        DMA_InitStructure.DMA_Channel = DMA_Channel_4;
        //外设地址
        DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&UART4->DR);
        //内存地址
        DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)mem_addr;
        //dma传输方向
        DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
        //设置DMA在传输时缓冲区的长度
        DMA_InitStructure.DMA_BufferSize = 10;
        //设置DMA的外设递增模式,一个外设
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
        //设置DMA的内存递增模式
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
        //外设数据字长
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
        //内存数据字长
        DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte;
        //设置DMA的传输模式
        DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
        //设置DMA的优先级别
        DMA_InitStructure.DMA_Priority = DMA_Priority_High;
       
        //指定如果FIFO模式或直接模式将用于指定的流 : 不使能FIFO模式  
        DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;   
        //指定了FIFO阈值水平
        DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;        
        //指定的Burst转移配置内存传输
        DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;      
        //指定的Burst转移配置外围转移 */  
        DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;

        //配置DMA1的通道         
        DMA_Init(DMA1_Stream4, &DMA_InitStructure);  
        //使能中断
        DMA_ITConfig(DMA1_Stream4,DMA_IT_TC,ENABLE);   

       
    //初始化串口参数  
    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_InitStructure.USART_BaudRate = 115200;
        //初始化串口
    USART_Init(UART4,&USART_InitStructure);  
       
        //中断配置
        USART_ITConfig(UART4,USART_IT_TC,DISABLE);
        USART_ITConfig(UART4,USART_IT_RXNE,DISABLE);
        USART_ITConfig(UART4,USART_IT_IDLE,ENABLE);  

        //配置中断  
        //NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3);
    NVIC_InitStructure.NVIC_IRQChannel = UART4_IRQn;               //通道设置为串口中断  
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;       //中断占先等级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;              //中断响应优先级
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                 //打开中断  
    NVIC_Init(&NVIC_InitStructure);   
        
        //采用DMA方式发送
        USART_DMACmd(UART4,USART_DMAReq_Tx,ENABLE);

        //中断配置
        USART_ITConfig(UART4,USART_IT_TC,DISABLE);
        USART_ITConfig(UART4,USART_IT_RXNE,DISABLE);
        USART_ITConfig(UART4,USART_IT_TXE,DISABLE);
        USART_ITConfig(UART4,USART_IT_IDLE,ENABLE);  
    //启动串口  
    USART_Cmd(UART4, ENABLE);   

    //设置IO口时钟      

  //uart config
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4, ENABLE);
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

  GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_UART4);

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  GPIO_Init(GPIOC, &GPIO_InitStructure);

  GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_UART4);
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_1;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
   



  while (1)
  {
          //设置传输数据长度
          DMA_SetCurrDataCounter(DMA1_Stream4, 10);
          //打开DMA,开始发送
           DMA_Cmd(DMA1_Stream4,ENABLE);

    OSTimeDly(2000);
  }
   
}

/*********************************************************************
*                                                        GSM模块:DMA发送中断处理函数
**********************************************************************/

void DMA1_Stream4_IRQHandler(void)
{
        if(DMA_GetITStatus(DMA1_Stream4,DMA_IT_TCIF4) != RESET)
        {
                //清除标志位
                DMA_ClearFlag(DMA1_Stream4,DMA_FLAG_TCIF4);
                //关闭DMA
                DMA_Cmd(DMA1_Stream4,DISABLE);
                //打开发送完成中断,发送最后两个字节
                USART_ITConfig(UART4,USART_IT_TC,ENABLE);
        }
}
   
/*********************************************************************
*                                                        GSM模块:串口中断处理函数
**********************************************************************/

void UART4_IRQHandler(void)
{
        if(USART_GetITStatus(UART4, USART_IT_TC) != RESET)
    {
                //关闭发送完成中断
                USART_ITConfig(UART4,USART_IT_TC,DISABLE);
    }
}

使用特权

评论回复
地板
gowow|  楼主 | 2016-10-14 15:45 | 只看该作者
这里有这个问题的解释,但是上面的代码已经加了UART4的发送中断,还是一样有问题。难道还需要加接收中断吗? 接收和发送没关系啊

http://blog.csdn.net/qcopter/article/details/52511558
stm32 usart在DMA模式下只能发送一次

问题描述:使用STM32 cube生成usart2 DMA direct mode(不使用FIFO,normal模式,STM32f407)配置代码,usart2可以使用阻塞方式发送,使用DMA发送则只能发送第一次,复位后还只能发送一次。

  单步调试发现DMA方式下的发送在发送第一次之后,husart->State 标志变为 HAL_USART_STATE_BUSY就再也不变了。比较直接的解决思路就是在DMA发送中断中给这个标志修改为HAL_USART_STATE_READY,修改之后还是不好用(我认为是可以通过修改多个相关寄存器解决的,但是个人倾向于不深入了解其寄存器,而是用封装度更高的HAL系列函数)。

  读stm32f4xx_hal_usart.c(V1.5.0)文件的前面关于如何使用HAL函数的部分并与配置代码比较并没有发现问题,但是看stm32f1xx_hal_usart.c(V1.0.0)在同样的位置多了如下文字:

              (+++) Configure the USARTx interrupt priority and enable the NVIC USART IRQ handle
     (used for last byte sending completion detection in DMA non circular mode)

  翻看STM32F4系列早于1.5.0的文件都没有这句,可能是官方的疏忽或者是个人理解不到位,总之增加了USART2中断之后(cube生成的),usart DMA发送是完全正常了。

使用特权

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

本版积分规则

43

主题

121

帖子

0

粉丝