找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 5727|回復(fù): 0
打印 上一主題 下一主題
收起左側(cè)

STM32學(xué)習(xí)—串口實(shí)驗(yàn)

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:82083 發(fā)表于 2015-6-9 00:28 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
電路如圖所示:
?USB-USART1


?USB-USART1


?USB-USART1


USART1_IRQHandler函數(shù):
void USART1_IRQHandler(void)函數(shù)是串口1的中斷響應(yīng)函數(shù),當(dāng)串口1發(fā)生了相應(yīng)的中斷后,就會(huì)跳到該函數(shù)執(zhí)行。這里設(shè)計(jì)了一個(gè)接收協(xié)議:通過(guò)這個(gè)函數(shù)配合一個(gè)數(shù)組USART_RX_BUF[] ,一個(gè)接收狀態(tài)寄存器 USART_RX_STA(此寄存器其實(shí)就是一個(gè)全局變量,由筆者自行添加。由于它起到類似寄存器的功能,這里暫且稱之為寄存器)實(shí)現(xiàn)對(duì)串口數(shù)據(jù)的接收管理。USART_RX_BUF 的大小由 USART_REC_LEN 定義,也就是一次接收的數(shù)據(jù)最大不能超過(guò) USART_REC_LEN個(gè)字節(jié)。 USART_RX_STA 是一個(gè)接收狀態(tài)寄存器,其各位的定義如表所示:
?接收狀態(tài)寄存器位定義表


設(shè)計(jì)思路如下:
當(dāng)接收到計(jì)算機(jī)發(fā)過(guò)來(lái)的數(shù)據(jù)時(shí),把接收到的數(shù)據(jù)保存在 USART_RX_BUF中,同時(shí)在接收狀態(tài)寄存器(USART_RX_STA)中計(jì)數(shù)接收到的有效數(shù)據(jù)個(gè)數(shù),當(dāng)收到回車(回車的表示由2個(gè)字節(jié)組成:0X0D 和0X0A)的第一個(gè)字節(jié) 0X0D 時(shí),計(jì)數(shù)器將不再增加,等待 0X0A 的到來(lái),而如果 0X0A沒(méi)有來(lái)到?,則認(rèn)為這次接收失敗,重新開(kāi)始下一次接收。如果順利接收到 0X0A ,則標(biāo)記USART_RX_STA 的第15位,這樣完成一次接收,并等待該位被其他程序清除,從而開(kāi)始下一次接收,而如果遲遲沒(méi)有收到 0X0D,那么在接收數(shù)據(jù)超過(guò) USART_REC_LEN 的時(shí)候,則會(huì)丟棄前面的數(shù)據(jù)重新接收。
?USART1_IRQHandle函數(shù)


EN_USART1_RX 和 USART_REC_LEN 都是在 usart.h文件里面定義的,當(dāng)需要使用串口接收的時(shí)候,只要在 usart.h 里面設(shè)置 EN_USART1_RX 為1即可。不使用的時(shí)候,設(shè)置EN_USART1_RX 為0即可,這樣可以省出部分 SRAM 和 FLASH,默認(rèn)是設(shè)置 EN_USART1_RX為1,也就是開(kāi)啟串口接收的。
OS_CRITICAL_METHOD 則是用來(lái)判斷是否使用 uc/OS,如果使用了 uc/OS,則調(diào)用OSIntEnter 和 OSIntExit 函數(shù);如果沒(méi)有使用 uc/OS,則不調(diào)用這兩個(gè)函數(shù)。

uart_init函數(shù):
void uart_init(u32 pclk2,u32bound)函數(shù)是串口1的初始化函數(shù)。該函數(shù)有2個(gè)參數(shù),一個(gè)為pclk2,是系統(tǒng)的時(shí)鐘頻率。第二個(gè)參數(shù)為需要設(shè)置的波特率,例如:9600、115200等。而這個(gè)函數(shù)的重點(diǎn)就是在波特率的設(shè)置,由于STM32 采用了分?jǐn)?shù)波特率,所以 STM32 的串口波特率設(shè)置范圍很寬,而且誤差很小。
STM32 的每個(gè)串口都有一個(gè)自己獨(dú)立的波特率寄存器USART_BRR,通過(guò)設(shè)置該寄存器就可以達(dá)到配置不同波特率的目的。其各位描述如圖所示:
?寄存器USART_BRR各位描述


前面提到 STM32的分?jǐn)?shù)波特率概念,其實(shí)就是在這個(gè)寄存器(USART_BRR)里面體現(xiàn)的。USART_BRR的最低4位(位[3:0])用來(lái)存放小數(shù)部分DIV_Fraction,緊接著的12位(位[15:4])用來(lái)存放整數(shù)部分 DIV_Mantissa,最高16位未使用。
這里簡(jiǎn)單介紹一下波特率的計(jì)算,STM32 的串口波特率計(jì)算公式如下:
?串口波特率計(jì)算公式


上式中,fpclkx 是給串口的時(shí)鐘(PCLK1 用于 USART2、3、4、5,PCLK2 用于USART1);USARTDIV 是一個(gè)無(wú)符號(hào)定點(diǎn)數(shù)。只要得到 USARTDIV 的值,就可以得到串口波特率寄存器USART1->BRR的值,反過(guò)來(lái),得到USART1->BRR的值,也可以推導(dǎo)出USARTDIV 的值。但更關(guān)心的是如何從 USARTDIV的值得到 USART_BRR 的值,因?yàn)橐话阒赖氖遣ㄌ芈屎?PCLKx的時(shí)鐘,要計(jì)算的就是 USART_BRR 的值。
接下來(lái)就可以初始化串口了,需要注意的是,這里初始化串口是按8位數(shù)據(jù)格式,1位停止位,無(wú)奇偶校驗(yàn)位的。具體代碼如下:
?uart_init函數(shù)



串口最基本的設(shè)置就是波特率的設(shè)置。STM32的串口使用起來(lái)還是蠻簡(jiǎn)單的,只要開(kāi)啟了串口時(shí)鐘,并設(shè)置相應(yīng)I/0口的模式,然后配置波特率、數(shù)據(jù)位長(zhǎng)度、奇偶校驗(yàn)位等信息,就可以使用了。下面,就簡(jiǎn)單介紹這個(gè)與串口基本配置直接相關(guān)的寄存器。
①串口時(shí)鐘使能。串口作為 STM32的一個(gè)外設(shè),其時(shí)鐘由外設(shè)時(shí)鐘使能寄存器控制,這里使用的串口1是在 APB2ENR 寄存器的第14位。除了串口1的時(shí)鐘使能在APB2ENR 寄存器,其他串口的時(shí)鐘使能位都在 APB1ENR 寄存器。
②串口復(fù)位。當(dāng)外設(shè)出現(xiàn)異常的時(shí)候可以通過(guò)復(fù)位寄存器里面的對(duì)應(yīng)設(shè)置實(shí)現(xiàn)該外設(shè)的復(fù)位,然后重新配置這個(gè)外設(shè)達(dá)到讓其重新工作的目的。一般在系統(tǒng)剛開(kāi)始配置外設(shè)的時(shí)候,都會(huì)先執(zhí)行復(fù)位該外設(shè)的操作。串口1的復(fù)位是通過(guò)配置APB2RSTR 寄存器的第14位來(lái)實(shí)現(xiàn)的。APB2RSTR 寄存器的各位描述如圖所示:
?APB2RSTR寄存器各位描述


從圖可知串口1的復(fù)位設(shè)置位在 APB2RSTR 的第14位。通過(guò)向該位寫1復(fù)位串口1,寫0結(jié)束復(fù)位。其他串口的復(fù)位在APB1RSTR 里面。
③串口波特率設(shè)置。通過(guò)設(shè)置 USART_BRR就可以達(dá)到配置不同波特率的目的。
④串口控制。STM32 的每個(gè)串口都有3個(gè)控制寄存器USART_CR1~3,串口的很多配置都是通過(guò)這3個(gè)寄存器來(lái)設(shè)置的。這里只要用到 USART_CR1就可以實(shí)現(xiàn)需要的功能了,該寄存器各位描述如圖所示:
?USART_CR寄存器各位描述


該寄存器的高18位沒(méi)有用到,低14位用于串口的功能設(shè)置。UE為串口使能位,通過(guò)該位置1來(lái)使能串口。M為字長(zhǎng)選擇位,當(dāng)該位為0的時(shí)候設(shè)置串口為8個(gè)字長(zhǎng)外加n個(gè)停止位,停止位的個(gè)數(shù)(n)是根據(jù)USART_CR2 的[13:12]位設(shè)置來(lái)決定的,默認(rèn)為0。PCE 為校驗(yàn)使能位,設(shè)置為0,則禁止校驗(yàn),否則使能校驗(yàn)。PS為校驗(yàn)位選擇,設(shè)置為0則為偶校驗(yàn),否則為奇校驗(yàn)。TXIE 為發(fā)送緩沖區(qū)空中斷使能位,設(shè)置該位為1,當(dāng) USART_SR 中的 TC位為1時(shí),將產(chǎn)生串口中斷。RXNEIE 為接收緩沖區(qū)非空中斷使能,設(shè)置該位為1,當(dāng) USART_SR 中的 ORE 或者 RXNE位為1時(shí),將產(chǎn)生串口中斷。TE 為發(fā)送使能位,設(shè)置為1將開(kāi)啟串口的發(fā)送功能。RE 為接收使能位,用法同 TE。
⑤數(shù)據(jù)發(fā)送和接收。STM32 的發(fā)送與接收是通過(guò)數(shù)據(jù)寄存器USART_DR 來(lái)實(shí)現(xiàn)的,這是一個(gè)雙寄存器,包含 TDR 和RDR。當(dāng)向該寄存器寫數(shù)據(jù)的時(shí)候就會(huì)自動(dòng)發(fā)送,當(dāng)收到數(shù)據(jù)的時(shí)候,也是存在該寄存器內(nèi)。該寄存器的各位描述如圖所示:
?USART_DR寄存器各位描述  


可以看出,雖然是一個(gè)32位寄存器,但是只用了低9位(DR[8:0]),其他都保留。
DR[8:0]為串口數(shù)據(jù),包含了發(fā)送或接收的數(shù)據(jù)。由于它是由兩個(gè)寄存器組成的,一個(gè)給發(fā)送用(TDR),一個(gè)給接收用(RDR),因此兼具讀和寫的功能。TDR寄存器提供了內(nèi)部總線和輸出移位寄存器之間的并行接口。RDR 寄存器提供了輸入移位寄存器和內(nèi)部總線之間的并行接口。
當(dāng)使能校驗(yàn)位(USART_CR1中的PCE位被置位)進(jìn)行發(fā)送時(shí),寫到MSB的值(根據(jù)數(shù)據(jù)的長(zhǎng)度不同,MSB是第7位或者第8位)會(huì)被后來(lái)的校驗(yàn)位取代。
⑥串口狀態(tài)。串口的狀態(tài)可以通過(guò)狀態(tài)寄存器 USART_SR讀取。USART_SR 的各位描述如圖所示:
?USART_SR寄存器各位描述


這里關(guān)注即兩個(gè)位,即第5、6位 RXNE 和 TC。
當(dāng) RXNE(讀數(shù)據(jù)寄存器非空)位被置1時(shí),就是提示已經(jīng)有數(shù)據(jù)被接收到了,并且可以讀出來(lái)。這時(shí)候要做的就是盡快讀取 USART_DR,通過(guò)讀USART_DR 可以將該位清零,也可以向該位寫0,直接清除。
當(dāng) TC(發(fā)送完成)位被置位時(shí),表示 USART_DR內(nèi)的數(shù)據(jù)已經(jīng)被發(fā)送完成了。如果設(shè)置了這個(gè)位的中斷,則會(huì)產(chǎn)生中斷。該位也有兩種清零方式:①讀USART_SR,寫 USART_DR。②直接向該位寫零。

串口實(shí)驗(yàn):
重新建立一個(gè)工程,在 HARDWARE 文件夾下新建一個(gè) led文件夾,用來(lái)存放按鍵輸入實(shí)驗(yàn)相關(guān)的代碼。?
?在HARDWARE 下新增 LED 文件夾


然后我們打開(kāi) USER 文件夾下的 USER.uvproj工程,按新建按鈕新建一個(gè)文件,然后保存在 HARDWARE->led 文件夾下面,保存為led.h,在該文件中輸入如下代碼:
?led.h


保存 led.h 代碼,然后我們按同樣的方法新建一個(gè) led.c 文件,也保存在 led 文件夾 下面。在led.c 中輸入如下代碼:
?led.c


我們把 led.c 加入到 HARDWARE 里面,如圖所示:
?將led.c 添加到HARDWARE中


回到主界面,在 USER.c 中輸入如下代碼:

?user.c


?user.c


然后按編譯,編譯工程,得到結(jié)果如圖:

?編譯結(jié)果


軟件實(shí)現(xiàn)功能:
?串口調(diào)試助手收到的信息


?發(fā)送數(shù)據(jù)后收到的信息


該程序僅使能了發(fā)送,并沒(méi)有使能發(fā)送完成中斷。中斷是由接收產(chǎn)生的,接收到了數(shù)據(jù),接收緩沖區(qū)非空產(chǎn)生中斷。

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩

相關(guān)帖子

回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表