之前在用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付出...