• STM32F4寄存器串口DMA汇总


    1.初始化

    //RCC
      RCC->APB1ENR|=1<<20;  	//使能串口5时钟 
      RCC->APB1ENR|=1<<19;  	//使能串口4时钟 
      RCC->APB1ENR|=1<<18;  	//使能串口3时钟 
      RCC->APB1ENR|=1<<17;  	//使能串口2时钟 
      RCC->APB2ENR|=1<<4;           //使能串口1时钟
      RCC->APB2ENR|=1<<5;           //使能串口6时钟
      RCC->AHB1ENR|=1<<21;//DMA1时钟使能  
      RCC->AHB1ENR|=1<<22;//DMA2时钟使能
    
    //GPIO
    //串口6
      GPIO_AF_Set(GPIOG,9,8);	
      GPIO_AF_Set(GPIOG,14,8);	
      GPIO_Set(GPIOG,PIN9|PIN14,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_50M,GPIO_PUPD_PD);//复用功能
    
    //UART4
        DMA1_Stream2->PAR=(uint32_t)&(UART4->DR);        //DMA外设地址           多重ADC->CDR
        DMA1_Stream2->CR=0;        //先全部复位CR寄存器值
        DMA1_Stream2->NDTR=50;       //传输数据项个数
        DMA1_Stream2->M0AR= (uint32_t)_rece_data1;            //DMA 存储器0地址
        DMA1_Stream2->CR|=4<<25;     //通道选择4
        DMA1_Stream2->CR|=0<<23;     //存储器单次传输
        DMA1_Stream2->CR|=0<<21;     //外设单次传输
        DMA1_Stream2->CR|=1<<16;     //中等优先级        2:高  3:非常高
        DMA1_Stream2->CR|=0<<13;     //存储器数据大小为8位     0:8位    1:16位  2:32位
        DMA1_Stream2->CR|=0<<11;     //外设数据大小为8位       0:8位    1:16位  2:32位
        DMA1_Stream2->CR|=1<<10;     //存储器地址递增
        DMA1_Stream2->CR|=0<<9;      //外设地址固定
        DMA1_Stream2->CR|=0<<8;     //普通模式
        DMA1_Stream2->CR|=0<<6;     //0:外设到存储器   1:存储器到外设   2:存储器到存储器
        DMA1_Stream2->CR|=1<<4;      //开启传输完成中断 	
        DMA1_Stream2->CR|=1<<0;      //开启DMA传输    
        
        MY_NVIC_Init(3,0,DMA1_Stream2_IRQn,4);	//抢占1,子优先级3,组2	
        MY_NVIC_Init(2,0,UART4_IRQn,4);	//抢占1,子优先级3,组2	
        //波特率为
        temp=(float)(42000000)/(_baud*16);//得到USARTDIV@OVER8=0
        mantissa=(u16)(temp);                 //得到整数部分
        fraction=(u16)((temp-mantissa)*16); //得到小数部分@OVER8=0
        mantissa<<=4;
        mantissa+=fraction;  
        
        UART4->CR1 = 0;
        UART4->CR3 = 0;
        //波特率设置
        UART4->BRR=mantissa;     //波特率设置
        UART4->CR1&=~(1<<15);     //设置OVER8=0
        UART4->CR1|=1<<4;      //空闲中断
        UART4->CR1|=1<<3;      //串口发送使能
        UART4->CR1|=1<<2;      //串口接收使能        
        UART4->CR3|=1<<6;      //开启DMA输出
        //使能
        UART4->CR1|=1<<13;      //串口使能
    
    //UART5
        //接收
        DMA1_Stream0->PAR=(uint32_t)&(UART5->DR);        //DMA外设地址           多重ADC->CDR
        DMA1_Stream0->CR=0;        //先全部复位CR寄存器值
        DMA1_Stream0->M0AR= (uint32_t)_rece_data2;            //DMA 存储器0地址
        DMA1_Stream0->NDTR=50;       //传输数据项个数
        DMA1_Stream0->CR|=4<<25;     //通道选择4
        DMA1_Stream0->CR|=0<<23;     //存储器单次传输
        DMA1_Stream0->CR|=0<<21;     //外设单次传输
        DMA1_Stream0->CR|=1<<16;     //中等优先级        2:高  3:非常高
        DMA1_Stream0->CR|=0<<13;     //存储器数据大小为8位     0:8位    1:16位  2:32位
        DMA1_Stream0->CR|=0<<11;     //外设数据大小为8位       0:8位    1:16位  2:32位
        DMA1_Stream0->CR|=1<<10;     //存储器地址递增
        DMA1_Stream0->CR|=0<<9;      //外设地址固定
        DMA1_Stream0->CR|=0<<8;     //普通模式
        DMA1_Stream0->CR|=0<<6;     //0:外设到存储器   1:存储器到外设   2:存储器到存储器
        DMA1_Stream0->CR|=1<<4;      //开启传输完成中断 
        DMA1_Stream0->CR|=1<<0;      //开启DMA传输 
        MY_NVIC_Init(4,0,DMA1_Stream0_IRQn,4);	//抢占1,子优先级3,组2
        MY_NVIC_Init(3,0,UART5_IRQn,4);	//抢占1,子优先级3,组2
    
        //发送
      DMA1_Stream7->M0AR= (uint32_t)uart5_send;            //DMA 存储器0地址 
      DMA1_Stream7->NDTR=0;       //传输数据项个数
      DMA1_Stream7->PAR=(uint32_t)&(UART5->DR);        //DMA外设地址           多重ADC->CDR
      DMA1_Stream7->CR=0;        //先全部复位CR寄存器值
      DMA1_Stream7->CR|=4<<25;     //通道选择4
      DMA1_Stream7->CR|=0<<23;     //存储器单次传输
      DMA1_Stream7->CR|=0<<21;     //外设单次传输
      DMA1_Stream7->CR|=3<<16;     //中等优先级        2:高  3:非常高
      DMA1_Stream7->CR|=0<<13;     //存储器数据大小为8位     0:8位    1:16位  2:32位
      DMA1_Stream7->CR|=0<<11;     //外设数据大小为8位       0:8位    1:16位  2:32位
      DMA1_Stream7->CR|=1<<10;     //存储器地址递增
      DMA1_Stream7->CR|=0<<9;      //外设地址固定
      DMA1_Stream7->CR|=0<<8;     //普通模式
      DMA1_Stream7->CR|=1<<6;     //0:外设到存储器   1:存储器到外设   2:存储器到存储器 
    
        //波特率为
        temp=(float)(42000000)/(_baud*16);//得到USARTDIV@OVER8=0
        mantissa=(u16)(temp);                 //得到整数部分
        fraction=(u16)((temp-mantissa)*16); //得到小数部分@OVER8=0
        mantissa<<=4;
        mantissa+=fraction; 
        UART5->CR1 = 0;
        UART5->CR3 = 0;
        //波特率设置
        UART5->BRR=mantissa;     //波特率设置
        UART5->CR1&=~(1<<15);     //设置OVER8=0
        UART5->CR1|=1<<4;      //空闲中断
        UART5->CR1|=1<<3;      //串口发送使能
        UART5->CR1|=1<<2;      //串口接收使能    
        UART5->CR3|=1<<6;      //开启DMA接收
        UART5->CR3|=1<<7;      //开启DMA发送
        //使能
        UART5->CR1|=1<<13;      //串口使能
    
    //USART6
    DMA2_Stream1->PAR=(uint32_t)&(USART6->DR);        //DMA外设地址           多重ADC->CDR
        DMA2_Stream1->CR=0;        //先全部复位CR寄存器值
        DMA2_Stream1->M0AR= (uint32_t)_rece_data3;            //DMA 存储器0地址
        DMA2_Stream1->NDTR=50;       //传输数据项个数
        DMA2_Stream1->CR|=5<<25;     //通道选择5
        DMA2_Stream1->CR|=0<<23;     //存储器单次传输
        DMA2_Stream1->CR|=0<<21;     //外设单次传输
        DMA2_Stream1->CR|=1<<16;     //中等优先级        2:高  3:非常高
        DMA2_Stream1->CR|=0<<13;     //存储器数据大小为8位     0:8位    1:16位  2:32位
        DMA2_Stream1->CR|=0<<11;     //外设数据大小为8位       0:8位    1:16位  2:32位
        DMA2_Stream1->CR|=1<<10;     //存储器地址递增
        DMA2_Stream1->CR|=0<<9;      //外设地址固定
        DMA2_Stream1->CR|=0<<8;     //普通模式
        DMA2_Stream1->CR|=0<<6;     //0:外设到存储器   1:存储器到外设   2:存储器到存储器
        DMA2_Stream1->CR|=1<<4;      //开启传输完成中断 
        DMA2_Stream1->CR|=1<<0;      //开启DMA传输    
        MY_NVIC_Init(5,0,DMA2_Stream1_IRQn,4);	//抢占1,子优先级3,组2
        MY_NVIC_Init(4,0,USART6_IRQn,4);	//抢占1,子优先级3,组2
        //波特率为
        temp=(float)(84000000)/(_baud*16);//得到USARTDIV@OVER8=0
        mantissa=(u16)(temp);                 //得到整数部分
        fraction=(u16)((temp-mantissa)*16); //得到小数部分@OVER8=0
        mantissa<<=4;
        mantissa+=fraction;  
        USART6->CR1 = 0;
        USART6->CR3 = 0;
        //波特率设置
        USART6->BRR=mantissa;     //波特率设置
        USART6->CR1&=~(1<<15);     //设置OVER8=0
        USART6->CR1|=1<<4;      //空闲中断
        USART6->CR1|=1<<3;      //串口发送使能
        USART6->CR1|=1<<2;      //串口接收使能    
        USART6->CR3|=1<<6;      //开启DMA输出
        //使能
        USART6->CR1|=1<<13;      //串口使能
    
    //USART1
    DMA2_Stream2->PAR=(uint32_t)&(USART1->DR);        //DMA外设地址           多重ADC->CDR
        DMA2_Stream2->CR=0;        //先全部复位CR寄存器值
        DMA2_Stream2->M0AR= (uint32_t)_rece_data4;            //DMA 存储器0地址
        DMA2_Stream2->NDTR=50;       //传输数据项个数
        DMA2_Stream2->CR|=4<<25;     //通道选择4
        DMA2_Stream2->CR|=0<<23;     //存储器单次传输
        DMA2_Stream2->CR|=0<<21;     //外设单次传输
        DMA2_Stream2->CR|=1<<16;     //中等优先级        2:高  3:非常高
        DMA2_Stream2->CR|=0<<13;     //存储器数据大小为8位     0:8位    1:16位  2:32位
        DMA2_Stream2->CR|=0<<11;     //外设数据大小为8位       0:8位    1:16位  2:32位
        DMA2_Stream2->CR|=1<<10;     //存储器地址递增
        DMA2_Stream2->CR|=0<<9;      //外设地址固定
        DMA2_Stream2->CR|=0<<8;     //普通模式
        DMA2_Stream2->CR|=0<<6;     //0:外设到存储器   1:存储器到外设   2:存储器到存储器
        DMA2_Stream2->CR|=1<<4;      //开启传输完成中断 
        DMA2_Stream2->CR|=1<<0;      //开启DMA传输    
        MY_NVIC_Init(6,0,DMA2_Stream2_IRQn,4);	//抢占1,子优先级3,组2
        MY_NVIC_Init(5,0,USART1_IRQn,4);	//抢占1,子优先级3,组2
        //波特率为
        temp=(float)(84000000)/(_baud*16);//得到USARTDIV@OVER8=0
        mantissa=(u16)(temp);                 //得到整数部分
        fraction=(u16)((temp-mantissa)*16); //得到小数部分@OVER8=0
        mantissa<<=4;
        mantissa+=fraction;  
        USART1->CR1 = 0;
        USART1->CR3 = 0;
        //波特率设置
        USART1->BRR=mantissa;     //波特率设置
        USART1->CR1&=~(1<<15);     //设置OVER8=0
        USART1->CR1|=1<<4;      //空闲中断
        USART1->CR1|=1<<3;      //串口发送使能
        USART1->CR1|=1<<2;      //串口接收使能    
        USART1->CR3|=1<<6;      //开启DMA输出
        //使能
        USART1->CR1|=1<<13;      //串口使能
    

    2.串口空闲中断接收

    void UART4_IRQHandler(void)
    { 
      if( ( UART4->SR&(1<<4) ) >> 4 == 1  )  //发生空闲中断
      {
        DMA1_Stream2->CR &= ~(1<<0);      //关闭DMA传输  会发生DMA完成中断 
        UART4->CR1 &= ~(1<<2);  //接收关闭   
        UART4->SR;
        UART4->DR;
      }
    }
    void DMA1_Stream2_IRQHandler(void)
    {
      u8 num = 0;
      if( ( DMA1->LISR&(1<<21) ) >> 21 == 1  )  //完成中断
      {
        DMA1_Stream2->CR &= ~(1<<0);      //关闭DMA传输  
          num = 50 - DMA1_Stream2 ->NDTR; //获取读到的字节数
          if( usart1_nux == 0 )    //互斥量,未使用数据,可进行更改
          {
            for( u8 i =0; i<num; i++ )
            {
              _rece_temp1[i] = _rece_data1[i]; 
            }
          }
          usart1_num = num;
          
          DMA1_Stream2->NDTR = 50; //重新填充
        DMA1->LIFCR |= 1<<21;   //清除完成中断标志位
        DMA1_Stream2->CR |= 1<<0;      //开启DMA传输 
        UART4->CR1 |= 1<<2;  //接收开启  
      }
    }
    
    
    void UART5_IRQHandler(void)
    {
      
      if( ( UART5->SR&(1<<4) ) >> 4 == 1  )  //发生空闲中断
      {
        DMA1_Stream0->CR &= ~(1<<0);      //关闭DMA传输 
        UART5->CR1 &= ~(1<<2);  //接收关闭    
        UART5->SR;
        UART5->DR;
      }
    }
    void DMA1_Stream0_IRQHandler(void)
    {
      u8 num = 0;
      
      num = 50 - DMA1_Stream0 ->NDTR; //获取读到的字节数
      if( usart2_nux == 0 )
      {
         for( u8 i =0; i<num; i++ )
         {
            _rece_temp2[i] = _rece_data2[i];
         }
      }
      usart2_num = num;
      DMA1_Stream0->NDTR = 50; //重新填充
      DMA1->LIFCR |= 1<<5;
      DMA1_Stream0->CR |= 1<<0;      //开启DMA传输
      UART5->CR1 |= 1<<2;  //接收开启
    }
    
    void USART6_IRQHandler(void)
    { 
      if( ( USART6->SR&(1<<4) ) >> 4 == 1  )  //发生空闲中断
      {
        DMA2_Stream1->CR &= ~(1<<0);      //关闭DMA传输 
        USART6->CR1 &= ~(1<<2);  //接收关闭    
        USART6->SR;
        USART6->DR;
      }
    }
    void DMA2_Stream1_IRQHandler(void)
    {
      u8 num = 0;
      
          num = 50 - DMA2_Stream1 ->NDTR; //获取读到的字节数
          if( usart3_nux == 0 )
          {
            for( u8 i =0; i<num; i++ )
            {
              _rece_temp3[i] = _rece_data3[i];
            }
          }
          usart3_num = num;
          
          DMA2_Stream1->NDTR = 50; //重新填充
        DMA2->LIFCR |= 1<<11; 
        DMA2_Stream1->CR |= 1<<0;      //开启DMA传输
        USART6->CR1 |= 1<<2;  //接收开启
      }
    }
    
    void USART1_IRQHandler(void)
    {  
      if( ( USART1->SR&(1<<4) ) >> 4 == 1  )  //发生空闲中断
      {
        DMA2_Stream2->CR &= ~(1<<0);      //关闭DMA传输,此时会发生DMA完成中断 
        USART1->CR1 &= ~(1<<2);  //接收关闭 
        USART1->SR;
        USART1->DR;
      }
    }
    void DMA2_Stream2_IRQHandler(void)
    {
      u8 num = 0;
          num = 50 - DMA2_Stream2 ->NDTR; //获取读到的字节数
          if( usart4_nux == 0 )
          {
            for( u8 i =0; i<num; i++ )
            {
              _rece_temp4[i] = _rece_data4[i];
            }
          }
          usart4_num = num;
          DMA2_Stream2->NDTR = 50; //重新填充
        DMA2->LIFCR |= 1<<21; 
        DMA2_Stream2->CR |= 1<<0;      //开启DMA传输 
        USART1->CR1 |= 1<<2;  //接收开启
    }
    
    
    //接收函数
    u8 USART_RECE(u8 _sum, u8 *_rece)
    {
      u8 temp = 0;
        if(_sum >50)
        {
          _sum = 50;
        } 
        if( usart4_num == 0 )
        {
          return 0;
        }
        else
        {
          usart4_nux = 1;  //互斥量,占用数据
          for( u8 i=0; i<_sum; i++ )
          {
            *_rece = _rece_temp4[i];
            if( i+1 > usart4_num ) //请求读数据量超过接收数据量,后面置0
            {
              *_rece = 0;
            }
            _rece++;
          }
          temp = usart4_num;  
          usart4_nux = 0;  //释放互斥量
          usart4_num = 0;
        } 
      return temp;  //返回接收到的数据个数
    }
    
    

    3.串口DMA发送

    //发送函数
    void UART5_SEND(u8 _sum, const u8 *_send){
      static uint8_t send_flag = 0;
      u8 *pBuf = NULL;
      pBuf = uart5_send;
      if( _sum > 50 )
      {
        _sum = 50;
      }
      for( u8 i=0; i<_sum; i++ )
      {
        *pBuf++ = *_send++;
      }
      if( send_flag == 0 )  //未进行过发送,直接发
      {
        DMA1_Stream7->NDTR=_sum;         //数据传输量      
        DMA1_Stream7->CR|=1<<0;                      //开启DMA传输  
        send_flag = 1;
      }
      else  //等待发送完成后,再进行发送
      {
        if((DMA1->HISR & (1<<27)) >> 27==1)  //DMA1_Steam7传输完成标志
        {  
          DMA1_Stream7->CR&=~(1<<0); //关闭DMA
          while((DMA1_Stream7->CR & (uint32_t)DMA_SxCR_EN) != 0);  //确保DMA可以被设置 
          DMA1->HIFCR|=1<<27;//清除DMA1_Steam7传输完成标志,不清的话第二次不能发送
          DMA1_Stream7->NDTR=_sum;         //数据传输量      
          DMA1_Stream7->CR|=1<<0;                      //开启DMA传输        
        } 
      }
    }
    
  • 相关阅读:
    DMN 决策逻辑与决策依赖之间的联系
    DMN 决策依赖DRG和DRD
    DMN 决策模型标记 介绍
    DMN 决策模型和标记 Decision Model And Notation
    RuleML 例子
    RuleML 例子
    RuleML 例子
    RuleML入门(下)
    RuleML 入门(上)
    osg 线框模式,点模式切换
  • 原文地址:https://www.cnblogs.com/penuel/p/13225978.html
Copyright © 2020-2023  润新知