今天写完stm32f4的串口DMA发送测试代码,需建立环形队列

来源:互联网 发布:淘宝购物津贴什么意思 编辑:程序博客网 时间:2024/06/13 04:11

一 环形队列的建立


volatile typedef struct                     //队列结构体定义
{
uint8_t Rx_Buffer[UART_BUF_LEN ];
uint32_t rx_in_ptr;
uint32_t rx_out_ptr;
uint32_t rx_len;
}uart_buffer;


    uint16_t Init_Uart_Buf(uart_buffer* Buf)    //队列初始化
{
  Buf->rx_in_ptr=Buf->rx_out_ptr=0;
return SUCCESS;
}


uint32_t Uart_Buf_Len(uart_buffer* Buf)   //计算buf长度
{
uint32_t len;   
len= (Buf->rx_in_ptr - Buf->rx_out_ptr + UART_BUF_LEN)%UART_BUF_LEN;
 return len;
}


uint16_t In_Uart_Buf(uart_buffer* Buf , uint8_t c)    //往buf写入一字节数据
{
  if((Buf->rx_in_ptr+1) % UART_BUF_LEN==Buf->rx_out_ptr) 
{
ECHO_STR_N("buffer in ptr touch the out ptr");
return ERROR;
}
  Buf->Rx_Buffer[Buf->rx_in_ptr]=c;
Buf->rx_in_ptr= (( Buf->rx_in_ptr+1)%UART_BUF_LEN);
return SUCCESS;

}


uint8_t Out_Uart_Buf(uart_buffer* Buf )     //buf读取一字节数据
{
uint8_t ch;
   if((Buf->rx_out_ptr % UART_BUF_LEN)==Buf->rx_in_ptr) return ERROR;
ch = Buf->Rx_Buffer[Buf->rx_out_ptr];
Buf->rx_out_ptr= ( Buf->rx_out_ptr+1)%UART_BUF_LEN;
   return ch;
}


 二, DMA初始化

void UART_DMA_TxConfig(void)                                       //DMA的初始化,省略串口初始化
{
NVIC_InitTypeDef NVIC_InitStructure;
//DMA_InitTypeDef UARTDMA_InitStructure;

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE);                 


  DMA_ClearFlag(UART_TX_DMA_STREAM, UART_TX_DMA_FLAG_FEIF | UART_TX_DMA_FLAG_DMEIF | UART_TX_DMA_FLAG_TEIF | UART_TX_DMA_FLAG_HTIF | UART_RX_DMA_FLAG_TCIF);
                                                                                                             

  /* DMA2 Stream3  or Stream6 disable */
  DMA_Cmd(UART_TX_DMA_STREAM, DISABLE);                                                     


  /* DMA2 Stream3  or Stream6 Config */
  DMA_DeInit(UART_TX_DMA_STREAM);




  UARTDMA_InitStructure.DMA_Channel = UART_TX_DMA_CHANNEL;
  UARTDMA_InitStructure.DMA_PeripheralBaseAddr = ( uint32_t)(&(USART2->DR)) ;
  UARTDMA_InitStructure.DMA_Memory0BaseAddr =   (uint32_t)Uart_Tx_Arr.Rx_Buffer[Uart_Tx_Arr.rx_out_ptr]; //        &Test_Buffer;
  UARTDMA_InitStructure.DMA_DIR =  DMA_DIR_MemoryToPeripheral;
  UARTDMA_InitStructure.DMA_BufferSize = 1; // Uart_Buf_Len(&Uart_Tx_Arr);
  UARTDMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  UARTDMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  UARTDMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte ;
  UARTDMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte ;
  UARTDMA_InitStructure.DMA_Mode = DMA_Mode_Normal   ;
  UARTDMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
  UARTDMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
  UARTDMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
  UARTDMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single ;
  UARTDMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
  DMA_Init(UART_TX_DMA_STREAM, &UARTDMA_InitStructure);


       NVIC_InitStructure.NVIC_IRQChannel = UART_TX_DMA_IRQn ;                                                //中断分组
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 7;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

  DMA_ITConfig(UART_TX_DMA_STREAM, DMA_IT_TC, ENABLE);                                           //DMA中断时能


  /* DMA2 Stream3  or Stream6 enable */
USART_DMACmd(USART2, USART_DMAReq_Tx , ENABLE);                                       //串口DMA开启
 
  DMA_Cmd(UART_TX_DMA_STREAM, ENABLE);                                                                     //DMA开启
    
}


三 buf.c里的数据发送函数,将Buf里的count个字节发往队列缓冲,用DMA方式

uint16_t UART_Tx_Str (char* Buf,uint32_t count) 
{
        uint32_t len=0,i=0;
uint16_t DMA_State=0;   //设置一个局部DMA传输标志,0表示上次DMA传输完成,1表示上次DMA正在工作,既DMA传输结束中断未发生

 
if (Uart_Buf_Len(&Uart_Tx_Arr)!=0)                //通过读取队列buf长度判断是否DMA传输完成,如果buf不为空,表明DMA未结束传输,不需要主动开启DMA,中断中会自动                                                                                           // 开启
{DMA_State=1;}

 __disable_irq();  //为了避免写buf数据时被DMA中断打断,关闭全局中断
for (i=0;i<count;i++)
{
In_Uart_Buf(&Uart_Tx_Arr,*(Buf+i));                                              //往缓冲区写数据,可以写过队列0地址 ,
}

if (DMA_State==0)  //如果上次DMA传输已经结束,本次需要开启DMA,
{
if(Uart_Tx_Arr.rx_out_ptr>Uart_Tx_Arr.rx_in_ptr)//  !!!!重点   如果out指针大于in指针,队列0地址被截断,DMA需要分段传输,由于DMA地址只会自加
{   //
  
   DMA_Cmd(UART_TX_DMA_STREAM,DISABLE);   //                  
 
    DMA_LENGTH=UART_BUF_LEN-Uart_Tx_Arr.rx_out_ptr;                      //第一段传输,ut指针到队列0地址,第二段传输在DMA中断函数中自动更新
    UARTDMA_InitStructure.DMA_BufferSize = DMA_LENGTH; //              
    UARTDMA_InitStructure.DMA_Memory0BaseAddr  = (uint32_t)(&Uart_Tx_Arr.Rx_Buffer[Uart_Tx_Arr.rx_out_ptr]);
    DMA_Init(UART_TX_DMA_STREAM, &UARTDMA_InitStructure);

     DMA_Cmd(UART_TX_DMA_STREAM,ENABLE);
}else{
   
   DMA_Cmd(UART_TX_DMA_STREAM,DISABLE);   //¹Ø±ÕDMA ¡£ÖØÐÂÅäÖõØÖ·Êý¾Ý
 
    DMA_LENGTH=Uart_Buf_Len(&Uart_Tx_Arr);
    UARTDMA_InitStructure.DMA_BufferSize = DMA_LENGTH; //ÖØÔØsize
    UARTDMA_InitStructure.DMA_Memory0BaseAddr  = (uint32_t)(&Uart_Tx_Arr.Rx_Buffer[Uart_Tx_Arr.rx_out_ptr]);
    DMA_Init(UART_TX_DMA_STREAM, &UARTDMA_InitStructure);

    DMA_Cmd(UART_TX_DMA_STREAM,ENABLE);
    }
 
 
}
//DMA_ITConfig(UART_TX_DMA_STREAM, DMA_IT_TC, ENABLE);
  __enable_irq();  // 开全局中断
     return UART_OK;
}

四 DMA发送结束中断

void DMA1_Stream6_IRQHandler () 
{
if(DMA_GetITStatus(UART_TX_DMA_STREAM  , DMA_IT_TCIF6)) 
{
DMA_ClearITPendingBit(UART_TX_DMA_STREAM , DMA_IT_TCIF6);  //清中断标志

Uart_Tx_Arr.rx_out_ptr=(Uart_Tx_Arr.rx_out_ptr+DMA_LENGTH)%UART_BUF_LEN;         更新out指针, 
DMA_LENGTH=0;

 if (Uart_Buf_Len(&Uart_Tx_Arr)!=0)   // 更新out指针后如果buf还有数据,则开启DMA,继续下次传输,如果为空,说明已无数据
{
if(Uart_Tx_Arr.rx_out_ptr>Uart_Tx_Arr.rx_in_ptr)//参考buf.c
{
  
   DMA_Cmd(UART_TX_DMA_STREAM,DISABLE);   //
 
DMA_LENGTH=UART_BUF_LEN-Uart_Tx_Arr.rx_out_ptr;
UARTDMA_InitStructure.DMA_BufferSize = DMA_LENGTH; 
UARTDMA_InitStructure.DMA_Memory0BaseAddr  = (uint32_t)(&Uart_Tx_Arr.Rx_Buffer[Uart_Tx_Arr.rx_out_ptr]);
DMA_Init(UART_TX_DMA_STREAM, &UARTDMA_InitStructure);

DMA_Cmd(UART_TX_DMA_STREAM,ENABLE);
}else{
   
   DMA_Cmd(UART_TX_DMA_STREAM,DISABLE);   //
 
DMA_LENGTH=Uart_Buf_Len(&Uart_Tx_Arr);
UARTDMA_InitStructure.DMA_BufferSize = DMA_LENGTH; //ÖØÔØsize
UARTDMA_InitStructure.DMA_Memory0BaseAddr  = (uint32_t)(&Uart_Tx_Arr.Rx_Buffer[Uart_Tx_Arr.rx_out_ptr]);
DMA_Init(UART_TX_DMA_STREAM, &UARTDMA_InitStructure);

DMA_Cmd(UART_TX_DMA_STREAM,ENABLE);


    }

}




  }
}






 





0 0
原创粉丝点击