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傳輸        
    } 
  }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM