STM32 HAL DMA串列埠接收不定長度實現

2021-10-02 02:14:56 字數 1982 閱讀 4727

1.使用stm32cube 直接先配置串列埠1的基礎資訊。

2.然後配置dma傳輸

3.就是啟動了,在串列埠初始化之後預設是沒有開啟串列埠dma接收的。所以增加幾行**如下圖所示

4.寫串列埠1中斷函式:

這個函式就是實現不等長的精髓所在了。這裡用到了類似環形佇列的方法,至於什麼是環形佇列這個不知道童鞋自行google了。

void usart1_irqhandler(void)

hal_uart_irqhandler(&systemuart);

}首先將中斷函式寫出來,如上所示了。這時候幀中斷的時候會進這個中斷,資料用dma接收。

第二步建立對應變數

#define uart1_dma_data_len 100//資料最大長度

static uart_handletypedef systemuart;

dma_handletypedef hdma_usart1_rx;

static uint8_t _uartdmadatabuffer[uart1_dma_data_len]; //緩衝區就是初始化的時候用到的

static int dmadatatail = 0;       //將dma資料傳輸buffer 虛擬成乙個佇列緩衝區

static int dmadatahead = 0;

static int dmadatalenght = 0;

第三步實現類似環形佇列功能

void usart1_irqhandler(void)

hal_uart_irqhandler(&systemuart);

}注意裡面 hdma_usart1_rx.instance->ndtr的ndtr不同的型號可能不同可以在dma的結構體裡找到對應的名字,如下圖所示

這個ndtr的值是從uart1_dma_data_len開始遞減的,因為啟動dma的時候設定了傳輸長度為uart1_dma_data_len

所以我們接收到當前的資料下標就是uart1_dma_data_len - hdma_usart1_rx.instance->ndtr這個。這個其實就是當前接收到資料的結束下標。有了資料結束下標,我們還需要資料起始下標,以及資料長度。

①資料起始下標: 等於上一次的dmadatatail 所以每次處理完資料都有dmadatahead = dmadatatail;

②資料長度:這個利用環形佇列求長度的做法:

dmadatalenght = (dmadatatail - dmadatahead+uart1_dma_data_len) % uart1_dma_data_len;

現在我們有了資料起始下標 資料長度那麼我們就可以訪問我們的資料了。當然方法也和環形佇列差不多

完成的中斷函式就是這樣的。可以接收什麼返回什麼了,要想自己處理可以在這裡增加緩衝區或者呼叫處理函式了。

void usart1_irqhandler(void)

printf("\r\n");

dmadatahead = dmadatatail;

}hal_uart_irqhandler(&systemuart);

}最後來張測試結果圖分別是一頓亂操作發不同的資料長度和資料

最後注意一點的就是這個程式如果你一下子發超過100個位元組那估計就不行了。因為超了緩衝區長度資料被覆蓋了,當然增加長度就可以解決了。

STM32CubeMX串列埠 DMA接收不定長資料

void mx usart1 uart init void hal uart enable it huart1,uart it idle 使能空閒中斷 hal uart receive dma huart1,rxdmabuf 1,rxbuf 1 size 啟動dma接收 該函式在usart.c檔案下...

STM32串列埠接收策略

如果我們需要接收乙個序列協議,怎麼做呢?先放到緩衝區然後再檢查標誌位是一種思路。道理簡單,關鍵要看怎麼設計。這裡介紹的方法是巧妙利用定時器,與串列埠中斷進行耦合,得到一種魯棒的接收方法。具體 開啟定時器與串列埠中斷 首先用示波器檢視完整幀所需要的時間,並且設定為timmax。定時器以適當的中斷頻率開...

STM32串列埠中斷方式接收

經過除錯在stm32f101cbt6中實現通訊。注意還要配乙個ttl轉usb介面,才能進行通訊。實現字串回發 include stm32f10x it.h include stm32f10x conf.h void rcc configuration void 時鐘配置 void usart con...