STM32串口收發數據的DMA配置過程

DMA,全稱Direct Memory Access,即直接存儲器訪問, DMA 傳輸方式無需 CPU 干預,通過硬件爲 RAM 和 I/O 設備開闢一條直接傳送數據的通路,能大大提高CPU的運行效率。

下面介紹stm32單片機的USART和DMA的配置過程:

step1:STM32串口配置
使用串口初始化函數來配置:

void usart_init(void)
{
  //第一步:GPIO複用端口設置
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA時鐘
    //PA9複用爲串口1發送引腳
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;           
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;    //複用推輓輸出
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    //PA2複用爲串口1接收引腳
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;   //浮空輸入
    GPIO_Init(GPIOA, &GPIO_InitStructure);

//第二步:串口參數設置
    USART_InitStructure.USART_BaudRate = 115200;   //串口波特率,也可以設爲其他規定數
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字長爲8位數據格式
    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); //初始化串口1
    USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE); //使能串口1的DMA接收,這一點注意
    USART_Cmd(USART1, ENABLE);            //串口1使能
}  

需要說明一下:程序中用的GPIO端口,不同的芯片,端口編號可能會不同,我們要根據實際情況進行調整。

step2:申請串口接收數據的存儲區域

存儲接收數據的內存必須在DMA配置前定義好。

#define USART_RBUFF_SIZE   100
char Usart_Rx_Buff[USART_RBUFF_SIZE];   //串口接收緩衝

step3:DMA配置

void USARTx_DMA_Config(void)
{
    DMA_InitTypeDef DMA_InitStructure;
	
    // 開啓DMA時鐘
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
    // 設置DMA源地址:串口數據寄存器地址*/
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)USART_DR_ADDRESS;  //這個地址是串口數據寄存器的絕對地址,用戶可進行宏定義
    // 內存地址(要傳輸的變量的指針)
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Usart_Rx_Buff;
    // 方向:從內存到外設	
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
    // 傳輸大小	
    DMA_InitStructure.DMA_BufferSize = USART_RBUFF_SIZE;
    // 外設地址不增	    
    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模式,一次或者循環模式
    //DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;	
    // 優先級:中	
    DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; 
    // 禁止內存到內存的傳輸
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
    // 配置DMA通道		   
    DMA_Init(USART_RX_DMA_CHANNEL, &DMA_InitStructure);		
    // 清除DMA所有標誌
    DMA_ClearFlag(DMA1_FLAG_GL5);
    DMA_ITConfig(USART_RX_DMA_CHANNEL, DMA_IT_TE, ENABLE);
    // 使能DMA
    DMA_Cmd (USART_RX_DMA_CHANNEL,ENABLE);
}

step4:經過DMA接收數據並讀取數據的程序
DMA使能後,就能在定義的數組Usart_Rx_Buff[USART_RBUFF_SIZE]中讀到接收的數據了。
如果想在讀取完畢後,清空DMA,則可以使用如下代碼:

void DMA_Retrive_Rx_Data(void) 
{
   // 關閉DMA ,防止干擾
   DMA_Cmd(USART_RX_DMA_CHANNEL, DISABLE);      
   // 清DMA標誌位
   DMA_ClearFlag( DMA1_FLAG_GL5 );          
   //  重新賦值計數值,必須大於等於最大可能接收到的數據幀數目
   USART_RX_DMA_CHANNEL->CNDTR = USART_RBUFF_SIZE;    
   //如果必要,清空數組
   memset(Usart_Rx_Buff,0,USART_RBUFF_SIZE);   
   //重新使能DMA,接收數據   
   DMA_Cmd(USART_RX_DMA_CHANNEL, ENABLE);       
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章