串口通信-輪詢方式
1 串口通信概述
1.1 計(jì)算機(jī)通信的基本概念
計(jì)算機(jī)通信: 將計(jì)算機(jī)技術(shù)和通信技術(shù)相結(jié)合,完成計(jì)算機(jī)與外部設(shè)備或計(jì)算機(jī)與計(jì)算機(jī)之間的信息交換。按照數(shù)據(jù)傳輸方式的不同,可以分為串行通信和并行通信兩類。
串行通信: 數(shù)據(jù)逐位傳輸,傳輸線少,長(zhǎng)距離傳輸時(shí)成本低,但數(shù)據(jù)的傳輸控制較復(fù)雜。按照實(shí)現(xiàn)數(shù)據(jù)同步的方式,可以分為同步串行和異步串行兩種。
- 同步串行通信: 數(shù)據(jù)傳輸以數(shù)據(jù)塊(一組字符)為單位,在一個(gè)數(shù)據(jù)塊內(nèi),字符與字符間無(wú)間隔,收發(fā)雙方依靠獨(dú)立的時(shí)鐘線進(jìn)行信號(hào)的同步。
- 異步串行通信: 數(shù)據(jù)傳輸以單個(gè)字符為單位,字符和字符之間的間隙任意,字符內(nèi)部每一位持續(xù)的時(shí)間相同。收發(fā)雙方?jīng)]有專門的時(shí)鐘信號(hào),而是依靠事先約定的字符格式和通信速率來(lái)完成通信適用于大批量的數(shù)據(jù)傳輸。
并行通信: 多位數(shù)據(jù)同時(shí)傳輸,傳輸控制簡(jiǎn)單,傳輸速度快,但是在長(zhǎng)距離傳輸時(shí)硬件成本較高。
1.2 異步串行通信
異步通信的兩個(gè)關(guān)鍵點(diǎn)是字符格式和 波特率 ,字符格式?jīng)Q定了數(shù)據(jù)的傳輸形式,波特率決定了字符中每一位數(shù)據(jù)的持續(xù)時(shí)間。
字符格式
? 1 位起始位,規(guī)定為低電平;
? 5~8 位數(shù)據(jù)位,即要傳送的有效信息;
? 1 位奇偶校驗(yàn)位;
? 1~2 位停止位,規(guī)定為高電平。
常用字符格式:1位起始位,8位數(shù)據(jù)位,無(wú)奇偶校驗(yàn),1位停止位
傳輸時(shí)低位在前,高位在后,上圖發(fā)送數(shù)據(jù)為0xE9。
通信速率
波特率:每秒鐘傳送二進(jìn)制數(shù)碼的位數(shù),以bit/s(bps)為單位。
常用的波特率有:9600、19200、38400、57600和115200;
波特率為115200,表示每秒傳輸115200位,且每一位數(shù)據(jù)在數(shù)據(jù)線上持續(xù)時(shí)間為Tbit= 1/115200 ≈ 8.68us
異步串行通信的數(shù)據(jù)接收過(guò)程
接收過(guò)程的本質(zhì)是數(shù)據(jù)采樣,假設(shè)接收端的采樣時(shí)鐘是波特率的16倍。
① 接收過(guò)程由起始位的下降沿啟動(dòng);
② 接收端等待8個(gè)時(shí)鐘周期,以便建立一個(gè)接近比特周期中間的采樣點(diǎn);
③ 接收端等待16個(gè)時(shí)鐘周期,使其進(jìn)入第一個(gè)數(shù)據(jù)位周期的中點(diǎn);
④ 第一個(gè)數(shù)據(jù)位被采樣并存儲(chǔ)在接收寄存器中;
⑤ 串口模塊在采樣第二個(gè)數(shù)據(jù)位之前等待另外16個(gè)時(shí)鐘周期;
⑥ 重復(fù)此過(guò)程,直到所有數(shù)據(jù)位都被采樣和存儲(chǔ);
⑦ 由停止位的上升沿使數(shù)據(jù)線返回到空閑狀態(tài)。
串口通信的數(shù)據(jù)傳輸方向
錯(cuò)誤校驗(yàn)方式
- 奇偶校驗(yàn):奇校驗(yàn)表示數(shù)據(jù)中“1”的個(gè)數(shù)與校驗(yàn)位“1”的個(gè)數(shù)之和為奇數(shù);偶校驗(yàn)表示數(shù)據(jù)中“1”的個(gè)數(shù)與校驗(yàn)位“1”的個(gè)數(shù)之和為偶數(shù)。
- 代碼和校驗(yàn):發(fā)送方將所發(fā)數(shù)據(jù)塊求和,產(chǎn)生一個(gè)字節(jié)的校驗(yàn)字符附加到數(shù)據(jù)塊末尾。接收方采用同樣方式進(jìn)行檢測(cè)。
- 循環(huán)冗余校驗(yàn):通過(guò)某種數(shù)學(xué)運(yùn)算實(shí)現(xiàn)有效信息與校驗(yàn)位之間的循環(huán)校驗(yàn),常用于磁盤信息的傳輸、存儲(chǔ)區(qū)的完整性校驗(yàn)等。
2 STM32串口通信
2.1 串口收發(fā)單元
串口收發(fā)單元主要利用數(shù)據(jù)寄存器DR,發(fā)送引腳TX,接收引腳RX,以及三個(gè)通信狀態(tài)位TXE、TC和RXNE來(lái)完成數(shù)據(jù)的接收和發(fā)送。
- TXE:發(fā)送數(shù)據(jù)寄存器空標(biāo)志。當(dāng)TDR寄存器的內(nèi)容已經(jīng)傳送到發(fā)送移位寄存器 時(shí),該位由硬件置1。如果串口控制寄存器CR1中的TXEIE位為1,將會(huì)觸發(fā)發(fā)送數(shù)據(jù)寄存器空中斷。注意:當(dāng)TXE置1時(shí),數(shù)據(jù)有可能還在發(fā)送。
- TC:發(fā)送完成標(biāo)志。當(dāng)發(fā)送移位寄存器的內(nèi)容發(fā)送完成,同時(shí)TDR寄存器也為 空時(shí),該位由硬件置1,表示本次數(shù)據(jù)傳輸已經(jīng)完成。如果串口控制寄存器CR1中的TCIE位為1,將會(huì)觸發(fā)發(fā)送完成中斷。注意:當(dāng)TC置1時(shí),數(shù)據(jù)才是真正地發(fā)送完成。
- RXNE:接收數(shù)據(jù)寄存器不為空標(biāo)志。當(dāng)移位寄存器的內(nèi)容已經(jīng)傳送到接收數(shù)據(jù)寄存器RDR時(shí),該位由硬件置1。如果串口控制寄存器CR1中的RXNEIE位為1,將會(huì)觸發(fā)接收數(shù)據(jù)寄存器不為空中斷。
數(shù)據(jù)寄存器DR在硬件上分為TDR和RDR兩個(gè)寄存器,通過(guò)數(shù)據(jù)的流向進(jìn)行區(qū)分,在結(jié)構(gòu)設(shè)計(jì)上采用了雙緩沖結(jié)構(gòu);
發(fā)送時(shí),數(shù)據(jù)通過(guò)數(shù)據(jù)總線送入TDR寄存器,然后傳送到發(fā)送移位寄存器完成數(shù)據(jù)轉(zhuǎn)換,從并行數(shù)據(jù)轉(zhuǎn)為串行數(shù)據(jù),最后通過(guò)TX引腳發(fā)送;
接收時(shí),數(shù)據(jù)通過(guò)RX引腳逐位送入接收移位寄存器,8位數(shù)據(jù)接收完成后,送入RDR寄存器,供用戶讀取。
USB轉(zhuǎn)TTL串口模塊
2.2 串口的數(shù)據(jù)類型定義
①外設(shè)句柄的定義:
HAL庫(kù)在結(jié)構(gòu)上,對(duì)每個(gè)外設(shè)抽象成了一個(gè)稱為ppp_HandleTypeDef
的結(jié)構(gòu)體,其中ppp就是每個(gè)外設(shè)的名字。所有的函數(shù)都是工作在ppp_HandleTypeDef
指針之下。
例如,使用USART2時(shí),可以定義USART初始化結(jié)構(gòu)體變量(全局變量)huart2
。
UART_HandleTypeDef huart2;
huart2
就被稱為串口的句柄,它被貫穿整個(gè)USART收發(fā)的流程。
②外設(shè)句柄數(shù)據(jù)類型的組成:
③串口初始化數(shù)據(jù)類型:
成員變量WordLength的取值范圍
宏常量定義 | 含義 |
---|---|
UART_WORDLENGTH_8B | 數(shù)據(jù)位長(zhǎng)度為8位 |
UART_WORDLENGTH_9B | 數(shù)據(jù)位長(zhǎng)度為9位 |
成員變量StopBits的取值范圍
宏常量定義 | 含義 |
---|---|
UART_STOPBITS_1 | 停止位長(zhǎng)度為1位 |
UART_STOPBITS_2 | 停止位長(zhǎng)度為2位 |
成員變量Parity的取值范圍
宏常量定義 | 含義 |
---|---|
UART_PARITY_NONE | 無(wú)奇偶校驗(yàn) |
UART_PARITY_EVEN | 偶校驗(yàn) |
UART_PARITY_ODD | 奇校驗(yàn) |
成員變量Mode的取值范圍
宏常量定義 | 含義 |
---|---|
UART_MODE_RX | 串口僅處于接收模式,只能接收數(shù)據(jù),不能發(fā)送數(shù)據(jù) |
UART_MODE_TX | 串口僅處于發(fā)送模式,只能發(fā)送數(shù)據(jù),不能接收數(shù)據(jù) |
UART_MODE_TX_RX | 串口處于接收和發(fā)送模式,可以同時(shí)收發(fā)數(shù)據(jù) |
成員變量HwFlowCtI的取值范圍
宏常量定義 | 含義 |
---|---|
UART_HWCONTROL_NONE | 無(wú)硬件流控 |
UART_HWCONTROL_RTS | 使能“請(qǐng)求發(fā)送(RTS)”引腳 |
UART_HWCONTROL_CTS | 使能“允許發(fā)送(CTS)”引腳 |
UART_HWCONTROL_RTS_CTS | 使能“請(qǐng)求發(fā)送(RTS)”和“允許發(fā)送(CTS)引腳 |
成員變量OverSampling的取值范圍
宏常量定義 | 含義 |
---|---|
UART_OVERSAMPLING_16 | 采樣頻率是信號(hào)傳輸頻率的16倍 |
UART_OVERSAMPLING_8 | 采樣頻率是信號(hào)傳輸頻率的8倍 |
2.3 外設(shè)初始化設(shè)計(jì)思想
①串口初始化過(guò)程:
抽象—串口初始化函數(shù)MX_USART2_UART_Init
: 將與MCU無(wú)關(guān)的通信參數(shù)存入句柄結(jié)構(gòu) + 使用HAL_UART_Init
執(zhí)行串口初始化操作,將句柄參數(shù)寫入寄存器。
HAL_UART_Init
干了哪些事?
- 調(diào)用
HAL_UART_MspInit
- 修改狀態(tài)忙
- 配置寄存器
- 清除標(biāo)志位
承載—與MCU相關(guān)的初始化函數(shù)HAL_UART_MspInit
:時(shí)鐘初始化 + 引腳初始化
3 串口通信方式
- 輪詢方式:CPU不斷檢測(cè)串口的狀態(tài)標(biāo)志來(lái)判斷數(shù)據(jù)收發(fā)的情況。特點(diǎn):程序設(shè)計(jì)簡(jiǎn)單,但CPU在檢測(cè)標(biāo)志位期間,無(wú)法執(zhí)行其他任務(wù),CPU利用率較低。
- 中斷方式:使能中斷后,接收一字節(jié)數(shù)據(jù)或發(fā)送一字節(jié)后申請(qǐng)中斷,在ISR中完成后續(xù)處理。在數(shù)據(jù)收發(fā)期間,CPU可以執(zhí)行其他任務(wù),CPU利用率較高。
- DMA方式:初始化時(shí)設(shè)置相關(guān)參數(shù),啟動(dòng)DMA傳輸后,數(shù)據(jù)傳輸過(guò)程不需要CPU的干預(yù)。傳輸完成后,再產(chǎn)生DMA中斷,由CPU進(jìn)行后續(xù)處理。傳輸效率最高。
4 輪詢方式的串口通信 ##
串口初始化函數(shù):
HAL_UART_Init
函數(shù)原型 HAL StatusTypeDef HAL_UART_Init (UART_HandleTypeDef *huart) 功能描述 按照串口句柄中指定的參數(shù)初始化串口 入口參數(shù) huart:串口句柄的地址 返回值 HAL狀態(tài)值:HAL_OK表示初始化成功,HAL_ERROR表示初始化失敗 注意事項(xiàng) 1.該函數(shù)將調(diào)用與MCU相關(guān)的初始化函數(shù)HAL_UART_Msplnit完成時(shí)鐘、引腳和中斷等底層硬件的初始化操作2.該函數(shù)由CubeMX自動(dòng)生成 接口函數(shù):
HAL_UART_Transmit
函數(shù)原型 HAL_StatusTypeDef HAL_UART_Transmit(UART_Handle TypeDef *huart, uint 8_t *pData, uint 16_t Size, uint 32_t Timeout) 功能描述 在輪詢方式下發(fā)送一定數(shù)量的數(shù)據(jù) 入口參數(shù)1 huart:串口句柄的地址 入口參數(shù) pData:待發(fā)送數(shù)據(jù)的首地址 入口參數(shù)3 Size:待發(fā)送數(shù)據(jù)的個(gè)數(shù) 入口參數(shù)4 Timeout:超時(shí)等待時(shí)間, 以ms為單位, HAL MAX DELAY表示無(wú)限等待 返回值 HAL狀態(tài)值:HAL_OK表示發(fā)送成功;HAL_ERROR表示參數(shù)錯(cuò)誤;HAL_BUSY表示串口被占用;HAL_TIMEOUT表示發(fā)送超時(shí) 注意事項(xiàng) 1.該函數(shù)連續(xù)發(fā)送數(shù)據(jù),發(fā)送過(guò)程中通過(guò)判斷TXE標(biāo)志來(lái)發(fā)送下一個(gè)數(shù)據(jù),通過(guò)判斷TC標(biāo)志來(lái)結(jié)束數(shù)據(jù)的發(fā)送2.如果在等待時(shí)間內(nèi)沒有完成發(fā)送,則不再發(fā)送,返回超時(shí)標(biāo)志3.該函數(shù)由用戶調(diào)用 接口函數(shù):
HAL_UART_Receive
函數(shù)原型 HAL_StatusTypeDef HAL_UART_Receive(UART_Handle TypeDef *huart, uint 8_t *pData, uint 16_t Size, uint 32_t Timeout) 功能描述 在輪詢方式下接收一定數(shù)量的數(shù)據(jù) 入口參數(shù)1 huart:串口句柄的地址 入口參數(shù) pData:存放數(shù)據(jù)的首地址 入口參數(shù)3 Size:待接收數(shù)據(jù)的個(gè)數(shù) 入口參數(shù)4 Timeout:超時(shí)等待時(shí)間, 以ms為單位, HAL MAX DELAY表示無(wú)限等待 返回值 HAL狀態(tài)值:HAL_OK表示發(fā)送成功;HAL_ERROR表示參數(shù)錯(cuò)誤;HAL_BUSY表示串口被占用;HAL_TIMEOUT表示發(fā)送超時(shí) 注意事項(xiàng) 1.該函數(shù)連續(xù)接收數(shù)據(jù),接收過(guò)程中通過(guò)判斷RXNE標(biāo)志來(lái)發(fā)送下一個(gè)數(shù)據(jù)2.如果在等待時(shí)間內(nèi)沒有完成接收,則不再接收,返回超時(shí)標(biāo)志3.該函數(shù)由用戶調(diào)用
5 任務(wù)實(shí)踐1
在PC上利用串口調(diào)試助手發(fā)送數(shù)據(jù)到MCU,MCU調(diào)用scanf函數(shù)讀取數(shù)據(jù),然后調(diào)用printf函數(shù)發(fā)送應(yīng)答信息到PC。
串口外設(shè)配置
- 異步模式,無(wú)硬件流控
- 設(shè)置通信參數(shù):波特率115200,8位數(shù)據(jù)位,無(wú)奇偶校驗(yàn),1位停止位,使能接收和發(fā)送,16倍過(guò)采樣(CubeMX默認(rèn)配置)
在Keil中勾選Use MicroLIB
編寫代碼
printf和scanf重定向/* USER CODE BEGIN Includes */ #include < stdio.h > /* USER CODE END Includes */ int fputc (int ch, FILE *f) { HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY); return ch; } int fgetc(FILE *f) { uint8_t ch = 0; HAL_UART_Receive(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY); return ch; } /* USER CODE END 4 */
用戶應(yīng)用代碼——猜數(shù)游戲
/* USER CODE BEGIN 3 */ printf("Please guess a number between 0 to 9n"); if (scanf("%d", &guess_num) == 1) { if (guess_num == ans) { printf("You are right! It's %dn", ans); } else { printf("You are wrong! It is not %dn", guess_num); } } } /* USER CODE END 3 */
實(shí)驗(yàn)現(xiàn)象
-
寄存器
+關(guān)注
關(guān)注
31文章
5343瀏覽量
120373 -
計(jì)算機(jī)
+關(guān)注
關(guān)注
19文章
7494瀏覽量
87961 -
STM32
+關(guān)注
關(guān)注
2270文章
10900瀏覽量
356041 -
串口通信
+關(guān)注
關(guān)注
34文章
1626瀏覽量
55529 -
異步串行通信
+關(guān)注
關(guān)注
0文章
16瀏覽量
8427
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論