15.1實驗內容
通過本實驗主要學習以下內容:
15.2實驗原理
15.2.1串口簡介
串口,從廣義上看,指所有串行通信接口,比如RS232、RS422、RS485、SPI、IIC等。串行通訊是指僅用一根接收線和一根發(fā)送線就能將數據以位進行傳輸的通訊方式。和串行通訊相對應的是并行通訊,并行通信指一個傳輸接口可以傳輸8個bit即一個byte(有時甚至更多),雖然串行通信比并行通信慢,但是串口可以在僅僅使用兩根線的情況下就能實現數據的傳輸。
對于GD32F303來說,串口一般特指USART(通用同步異步收發(fā)器 )和UART(通用異步收發(fā)器 )。USART/UART提供了一個靈活方便的串行數據交換接口,數據幀可以通過全雙工或半雙工,同步或異步的方式進行傳輸。紅楓派開發(fā)板搭載的GD32F303ZET6總共擁有5個串口,(USART+UART) 對于一般應用來說足夠使用了。
15.2.2串口通信幀介紹
GD32F303的串口通信只需要3條線組成,分別為TX(發(fā)送線)、RX(接收線)和GND,對于兩個通信結點,TX和RX需要交叉連接,如下示例:
下面來介紹下串口數據幀組成。
以下為一個標準的串口通信幀:
一個串口幀由空閑、起始位、數據位、校驗位以及停止位組成,傳輸的數據地位在前,高位再后。
空閑:串口TX或RX數據線上沒有傳輸任何數據時,則該線處于為空閑狀態(tài)。空閑是TX和RX都是處于高電平。
起始位:占一個bit時間,標志數據起始,由一個邏輯0(低電平)的數據位表示。當發(fā)送方開始發(fā)送一幀數據時,起始位會最先發(fā)送,而對于接收方來說,檢測到起始位后,即使自己的接收時鐘與發(fā)送方的數據同步。
數據位:數據位緊跟在起始位之后,是通信中的真正有效信息。數據位的位數可以由通信雙方共同約定,對于GD32F303來說,數據位一般只有8位。
校驗位:校驗位占一bit時間,GD32F303可以設置校驗位為:奇校驗、偶校驗或無校驗。校驗位是為了保證通信的可靠性,如果是奇校驗,需要保證傳輸的數據總共有奇數個邏輯高位,如果是偶校驗,需要保證傳輸的數據總共有偶數個邏輯高位。以傳輸傳輸數據A:0x01000001為例,如果設置了奇校驗,則需要在校驗位傳輸“1”,如果是偶檢驗,則傳輸“0”。奇偶校驗是由硬件處理的,當設置好校驗位后,硬件會自動根據需要傳輸的數據自動插入校驗位。
注意:GD32F303的數據位可設置為8bit和9bit兩種方式,當設置了奇校驗或偶校驗,一定要將數據位設置為9bit;而設置了無校驗時,需要將數據位設置為8bit。 |
停止位:它是一幀數據的結束標志,可以是1bit、1.5bit、2bit個邏輯“1”。
15.2.3串口波特率
波特率是串口通信中一個非常重要的參數,串口通信傳輸雙方必須要設置一樣的串口波特率,否則通訊就會出錯。波特率可以認為是比特率,即每秒傳輸的位數。一般波特率可以是9600、19200、115200等等,如果設置波特率為9600,設置通信幀為1bit起始位+8bit數據幀+無校驗+1bit停止位,那么每秒鐘最多可以傳輸9600bit/10bit = 960個字節(jié)。
現在重點介紹下GD32F303串口接收器的工作原理。GD32F303串口接收器采用的是16倍過采樣,即發(fā)送方發(fā)送數據后,GD32F303串口接受器都會將每個bit采樣16次:
在默認情況下,接收器通過獲取三個采樣點的值來估計該位的值。如果在3個采樣點中有2個或3個為0,該數據位被視為0,否則為1。如果3個采樣點中有一個采樣點的值與其他兩個不同,不管是起始位,數據位,奇偶校驗位或者停止位,都將產生噪聲錯誤(NERR)。
15.2.4GD32F303串口設置步驟
串口設置的一般步驟為:
- GPIO時鐘開啟、串口時鐘開啟
- GPIO設置,一般發(fā)送IO需要設置為AF模式,接受IO設置為in-floating模式
- 串口復位
- 串口參數配置,主要為波特率、數據位長度、校驗位設置、停止位長度
- 依據是否需要使用中斷或DMA進行中斷配置或DMA配置
- 使能串口
- 編寫中斷處理函數
15.3硬件設計
紅楓派開發(fā)板設計了一個USB轉UART功能,通過USB TypeC線將電腦和開發(fā)板連接起來,就可以進行電腦和開發(fā)板之間的串口通訊了。
15.4代碼解析
15.4.1在driver_uart.c中定義了串口初始化函數driver_uart_init。
C void driver_uart_init(typdef_uart_struct *uartx) { rcu_periph_clock_enable(uartx->rcu_uart_x); usart_deinit(uartx->uart_x); driver_gpio_general_init(uartx->uart_rx_gpio); driver_gpio_general_init(uartx->uart_tx_gpio); if(uartx->uart_mode_rx==MODE_DMA) { if(uartx->uart_rx_dma!=NULL) { driver_dma_com_init(uartx->uart_rx_dma,(uint32_t)&USART_DATA(uartx->uart_x),NULL,DMA_Width_8BIT,DMA_PERIPHERAL_TO_MEMORY); usart_interrupt_enable(uartx->uart_x,USART_INT_IDLE); } } if(uartx->uart_mode_tx==MODE_DMA) { if(uartx->uart_tx_dma!=NULL) { driver_dma_com_init(uartx->uart_tx_dma,(uint32_t)&USART_DATA(uartx->uart_x),NULL,DMA_Width_8BIT,DMA_MEMORY_TO_PERIPHERAL); } } usart_baudrate_set(uartx->uart_x, uartx->baudrate); usart_receive_config(uartx->uart_x, USART_RECEIVE_ENABLE); usart_transmit_config(uartx->uart_x, USART_TRANSMIT_ENABLE); usart_word_length_set(uartx->uart_x, uartx->data_length); usart_parity_config(uartx->uart_x, uartx->parity); usart_enable(uartx->uart_x); } |
15.4.2重定向函數int fputc(int ch, FILE *f)
要使用Printf,重定向函數fputc是必須的。在C 語言標準庫中,fputc函數是printf 函數內部的一個函數,功能是將字符ch寫入到文件指針file所指向文件的當前寫指針位置,簡單理解就是把字符寫入到特定文件中。我們使用USART函數重新修改fputc函數內容,達到類似“寫入”的功能。
fputc定義在bsp_uart.c中
C int fputc(int ch, FILE *f) { driver_uart_transmit_byte(&BOARD_UART,(uint8_t)ch); return ch; } |
這個函數比較簡單,就是調用了接口driver_uart_transmit_byte,該接口定義在driver_uart.c中:
C Drv_Err driver_uart_transmit_byte(typdef_uart_struct *uartx,uint8_t data) { uint32_t timeout = driver_tick; while(uartx->uart_control.Com_Flag.Bits.SendState==1) { if((timeout+UART_TIMEOUT_MS) <= driver_tick)? { uartx->uart_control.Com_Flag.Bits.SendState=0; return DRV_ERROR; } } Drv_Err uart_state=DRV_SUCCESS; uartx->uart_control.Com_Flag.Bits.SendSucess=0; uartx->uart_control.Com_Flag.Bits.SendState=1; uart_state=driver_uart_flag_wait_timeout(uartx,USART_FLAG_TBE,SET); usart_data_transmit(uartx->uart_x,data); uartx->uart_control.Com_Flag.Bits.SendSucess=1; uartx->uart_control.Com_Flag.Bits.SendState=0; return uart_state; } |
這段代碼作用是,循環(huán)去讀串口的TBE標志位,并且將待發(fā)送的數據寫到串口寄存器中。
15.4.3main函數實現
串口初始化完成并定義好fputc重定向函數后,就可以通過printf函數往電腦上打印數據了。以下main函數:
C int main(void) { delay_init(); bsp_uart_init(&BOARD_UART); bsp_led_init(&LED0); while(1) { delay_ms(1000); bsp_led_toggle(&LED0); printf("printf:system driver_tick is %lld \r\n",driver_tick); } } |
本例程main函數首先進行了延時函數初始化,再配置開發(fā)板上的USB串口,并設置了一個LED燈用來提示代碼運行。while(1)循環(huán)中先延時1s,再翻轉一次LED狀態(tài),接著使用printf函數打印系統(tǒng)運行tick時間。
15.5實驗結果
使用USB-TypeC線,連接電腦和板上USB to UART口后,配置好串口調試助手,即可看到每秒鐘串口打印的數據了。
本教程由GD32 MCU方案商聚沃科技原創(chuàng)發(fā)布,了解更多GD32 MCU教程,關注聚沃科技官網
-
單片機
+關注
關注
6030文章
44491瀏覽量
632005 -
串口
+關注
關注
14文章
1540瀏覽量
76067 -
開發(fā)板
+關注
關注
25文章
4898瀏覽量
97064 -
USART
+關注
關注
1文章
195瀏覽量
30764 -
GD32
+關注
關注
7文章
403瀏覽量
24112
發(fā)布評論請先 登錄
相關推薦
評論