STM32串列埠通訊(基於緩衝區)

2021-10-05 21:39:14 字數 4093 閱讀 8618

一、串列埠的初始化和中斷設定

1、初始化gpio:

根據手冊的8.1.11節,我們可以找到下表:

在全雙工的模式下,傳送引腳需要設定為推挽復用輸出,接收引腳則設定為浮空輸入或帶上拉的輸入。因為一般不用同步和流量控制的方式,所以ck、rst、cts引腳不作配置。當然啦,在使用stm32外設的時候不要忘記開啟外設時鐘(gpio和usart的rcc)。

1. usart_flag_rxne—接受資料暫存器非空標誌位(receive data register not empty flag)

當rdr移位暫存器中的資料被轉移到usart_dr暫存器中,該位被硬體置位 (表示接受到乙個位元組) 。如果usart_cr1暫存器中的rxneie為1,則產生中斷。對usart_dr的讀操作可以將該位清零。rxne位也可以通過寫入0來清除,只有在多快取通訊中才推薦這種清除程式。

0:資料沒有收到;

1:收到資料,可以讀出。

2. usart_flag_txe —傳送資料暫存器空標誌位(transmit data register empty flag)

當tdr暫存器中的資料被硬體轉移到移位暫存器的時候,該位被硬體置位 (表示傳送資料暫存器為空,可以繼續寫入資料。注:此時並不確定資料是否傳送完成) 。如果usart_cr1暫存器中的txeie為1,則產生中斷。對usart_dr的寫操作,將該位清零。

0:資料還沒有被轉移到移位暫存器;

1:資料已經被轉移到移位暫存器。

3. usart_flag_tc

— 傳送完成標誌位(transmission complete flag)

包含有資料的一幀傳送完成後,並且txe=1時,由硬體將該位置』1』 (表示一幀資料傳送完成,可以繼續傳送下一幀)。如果usart_cr1中的tcie為』1』,則產生中斷。由軟體序列清除該位(先讀usart_sr,然後寫入usart_dr)。tc位也可以通過寫入』0』來清除,只有在多快取通訊中才推薦這種清除程式。

0:傳送還未完成;

1:傳送完成。

gpio_inittypedef gpio_initstructure;

//開啟串列埠和gpio的時鐘

rcc_apb2periphclockcmd(rcc_apb2periph_usart1 | rcc_apb2periph_gpioa, enable);

//配置傳送引腳

gpio_initstructure.gpio_pin = gpio_pin_9;

//傳送引腳設定為推挽復用

gpio_initstructure.gpio_mode = gpio_mode_af_pp;

gpio_initstructure.gpio_speed = gpio_speed_50mhz;

gpio_init(gpioa, &gpio_initstructure);

//配置接收引腳

gpio_initstructure.gpio_pin = gpio_pin_10;

//接收引腳設定為浮空輸入

gpio_initstructure.gpio_mode = gpio_mode_in_floating;

gpio_init(gpioa, &gpio_initstructure);

2、配置串列埠引數

有專門用於初始化串列埠的庫函式(usart_init)和對應的結構體(usart_inittypedef),好像每個外設都有這樣的配套,具體內容可參看《stm32f10***韌體庫_3.xx.pdf》。

usart_inittypedef usart_initstructure;

//波特率

usart_initstructure.usart_baudrate = 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_rx | usart_mode_tx;

//初始化串列埠1

usart_init(usart1, &usart_initstructure);

3、中斷配置

在使用stm32的中斷前,要對nvic中斷控制器進行配置,設定中斷的優先順序。

//配置中斷優先順序

nvic_initstructure.nvic_irqchannel = usart1_irqn;

nvic_initstructure.nvic_irqchannelpreemptionpriority = 1;

nvic_initstructure.nvic_irqchannelsubpriority = 1;

nvic_initstructure.nvic_irqchannelcmd = enable;

nvic_init(&nvic_initstructure);

4、使能串列埠及串列埠中斷

注意1:初始化時不要隨意開啟txe中斷!只要tx-dr暫存器為空,tx和txe標誌都會馬上被置位而立即會產生中斷(參考《stm32中文參考手冊》的25.3.2節),即使中斷標誌被清除,也會被重新置位。因此,我採用的是tc中斷而不是採用txe中斷。

注意2:不要採用在乙個中斷配置函式中同時開啟兩個中斷!例如:usart_itconfig(usart1, usart_it_tc | usart_it_rxne, enable);    咋眼一看,明明只開啟tc中斷和rx中斷,然而卻會同時把txe中斷也開啟。

//串列埠1使能

usart_cmd(usart1, enable);

//清除接收中斷標記

usart_clearitpendingbit(usart1, usart_it_rxne);

//清除傳送完成中斷標記

usart_clearitpendingbit(usart1, usart_it_tc);

//開啟串列埠1傳送完中斷

usart_itconfig(usart1, usart_it_tc, enable);

//開啟串列埠1接收中斷        兩個中斷不能在乙個函式中同時開啟!!!太坑了t_t

usart_itconfig(usart1, usart_it_rxne, enable);

————————————————

這樣,串列埠1配置好了。但**一執行就會發現不妥!為什麼每次初始化完成就馬上進入中斷了呢???遇到這種現象千萬不要大驚小怪,我很淡(dan)定(teng)地做了個實驗,發現處理器復位後,串列埠的sr暫存器中的tc標誌會被置位。而根《stm32中文參考手冊》25.3.2節,在串列埠使能後會自動傳送乙個空閒幀,傳送完畢後tc也會置位,所以初始化將導致串列埠初始化完畢後馬上進入tc中斷。為了避免這種情況,可以在串列埠使能後等待空閒幀傳送完畢,再開啟tc中斷。

具體看下面完整的初始化**:

————————————————

//配置串列埠1

void usart1_config()

傳送資料原理:把要傳送的資料全部加入到緩衝區中,讓處理器開始傳送。乙個資料傳送結束後,即會產生tc中斷,此時在中斷服務程式中傳送下乙個資料。像吃飯看電視,在夾菜(發資料)的時候才要把注意力放到菜盤子上,嚼飯的時候(資料傳送中)可以看電視,在開始傳送資料到資料傳送完畢觸發中斷的這段時間裡,處理器可以去做別的事情。

接收資料原理:當乙個資料接收完畢後,將資料立存入緩衝區而不處理,並在未處理資料的計數器上加1。等到處理器空閒,再從緩衝區讀取這些資料做並處理(不在中斷函式中)。

STM32串列埠環形緩衝區

目錄 1 概述 2 1 概述 1.1 本篇實現串列埠驅動,實現printf函式的重定向,實現串列埠的中斷接受和傳送,效仿modbus協議中的3.5t超時機制,判斷是否接受完畢 1.2 如果串列埠僅僅是實現乙個控制台,列印一些debug資料,使用printf函式 串列埠傳送資料忙等待 如果是需要用串列...

stm32串列埠通訊

通訊方式 1 同步通訊 帶時鐘同步訊號傳輸 spi,iic等 2 非同步通訊 不帶時鐘用途訊號 usrt,單匯流排 stm32串列埠引腳表 串口號 rxd txd 1 pa10 pa9 2 pa3pa2 3 pb11 pb10 4 pc11 pc10 5 pd2pc12 通訊過程 接收過程 由rx入...

STM32串列埠通訊

1.常用的串列埠相關暫存器 1 usart sr狀態暫存器,對應的庫函式 flagstatus usart getflagstatus usart typedef usartx,uint16 t usart flag 2 usart dr資料暫存器,對應的庫函式 void usart senddat...