關於串列埠開啟DMA進行收發的配置

2021-08-11 10:07:44 字數 3473 閱讀 2409

之前在用stm32進行開發的時候,有用到485進行資料的採集。因為資料量相對較大,所以開啟了dma通道。這邊就對485串列埠配置和dma的配置以及後續相關的收發操作進行一點總結。首先我485接的是板子上的串列埠一。根據手冊可以看出這邊使用的是dma1的通道4和通道5,接下來就是相關的配置。ps:用庫函式進行的開發

//一些定義

#define rx_len 1024

u8 real_recv_len ;//串列埠實際接收的資料長度

os_sem tx_sem;  //傳送的訊號量

串列埠配置:

/*開啟串列埠1 gpio扣 dma相關的時鐘*/

rcc_apb2periphclockcmd(rcc_apb2periph_usart1, enable);

rcc_apb2periphclockcmd(rcc_apb2periph_gpioa | rcc_apb2periph_afio, enable);//開啟gpioa的重對映功能

rcc_ahbperiphclockcmd(rcc_ahbperiph_dma1, enable);

/*配置rx tx的io口功能*/

//pa10  rx

gpio_initstructure.gpio_pin = gpio_pin_10;

gpio_initstructure.gpio_mode = gpio_mode_in_floating;

gpio_init(gpioa, &gpio_initstructure);

//pa9  tx

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);

//uart1

usart_initstructure.usart_baudrate = 9600;//9600;

usart_initstructure.usart_wordlength = usart_wordlength_8b;

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_tx;  //先不使能接收 到相應task中使能

usart_init(usart1, &usart_initstructure);

usart_clearflag(usart1, usart_flag_tc);

usart_dmacmd(usart1, usart_dmareq_tx,enable);

usart_dmacmd(usart1, usart_dmareq_rx, enable);

usart_itconfig(usart1,usart_it_idle,enable);

//dma1_ch4  usart1 tx

dma_initstructure.dma_peripheralbaseaddr = (u32)&usart1->dr; //目標位址

dma_initstructure.dma_dir = dma_dir_peripheraldst; //方向

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_peripheraldatasize_byte; //記憶體位元組為單位

dma_initstructure.dma_mode = dma_mode_normal; //

dma_initstructure.dma_priority = dma_priority_high;

dma_initstructure.dma_m2m = dma_m2m_disable; //非記憶體到記憶體

dma_init(dma1_channel4, &dma_initstructure);

dma_itconfig(dma1_channel4, dma_it_tc, enable);

dma_initstructure.dma_dir = dma_dir_peripheralsrc; //方向

dma_init(dma1_channel5, &dma_initstructure);

usart_cmd(usart1, enable);

接下來是中斷函式的配置和進行資料的收發操作

首先定義dma使能的巨集定義

#define dma1_ch4_en()  dma1_channel4->ccr |= dma_ccr1_en  //開dma

#define dma1_ch5_en()  dma1_channel5->ccr |= dma_ccr1_en;//開dma

#define dma1_ch4_dis() dma1_channel4->ccr &= (u16)(~dma_ccr1_en)  //關dma

#define dma1_ch5_dis() dma1_channel5->ccr &= (u16)(~dma_ccr1_en);  //關dma

接下來是中斷函式的完成

void usart1_irqhandler()

//下面是dma的中斷函式

void dma1_channel4_irqhandler()

//下面傳送函式

static int usart1_send(u8* buf, u8 lenth)

dma1_channel4->cmar = (u32)buf;

dma1_channel4->***tr = lenth;

usart1_rx_en(); 

dma1_ch4_en();  //傳送

return 0;

}//下面是通道一的接收初始化和使能失效函式的封裝

//使能接收

static void usart1_rx_en()

//關閉接收

static void usart1_rx_dis()

//接收初始化

void lcd_rx1_init()

經過測試是可以正常使用的,其中大部分參考的是零死角玩轉stm32這本書,書寫的很好,很多例子很受用。

串列埠通訊DMA中斷

這是以前學32的時候寫的,那時候學了32之後感覺32真是太強大了,比51強的沒影。關於dma網上有許多的資料,親們搜搜,這裡只貼 了,其實我也想詳詳細細地敘述一番,但是自己本身打字就慢,還有好多事情要做!是我親自都在板子上測試過的,當然貼上 複製過去可能也不會盡如人意,知識這東西總是有許多道不清說不...

LL庫串列埠 DMA

由於工作中測試發現串列埠傳輸資料延時有點大,傳輸35個位元組,115200,理論值應該在3ms左右,然而實際測試卻有40ms,所以首先想到會不會是hal庫執行效率低得原因,所以採用ll庫,但是ll庫的資料少之又少啊!自己做個記錄。使用cubemx可以直接生產ll庫的 我的工程裡是hal庫和ll庫混用...

串列埠 DMA接受不定長資料

工作中經常會遇到串列埠通訊,並對互動的資料進行處理。經常用到的是通過不停的產生串列埠接收中斷,然後對資料做處理。這樣做的弊端就是,不停的會產生串列埠接受中斷。中斷請求不但使cpu停下來,而且要cpu執行中斷服務程式為中斷請求服務,這個請求包括了對斷點和現場的處理以及cpu與外設的傳送,所以cpu付出...