STM32——串口通信
STM32——串口通信
宗旨:技術(shù)的學(xué)習(xí)是有限的,分享的精神是無限的。
一、異步串口通信協(xié)議
? ? ? ? STM32 的串口非常強大,它不僅支持最基本的通用串口同步、異步通信,還具有 LIN 總線功能(局域互聯(lián)網(wǎng))、IRDA 功能(紅外通信)、SmartCard 功能。一般我們利用串口打印調(diào)試信息。
?
二、串口工作過程分析
? ? ? ? 我們只需要大概了解串口發(fā)送的過程即可。從下至上,我們看到串口外設(shè)主要由三個部分組成,分別是波特率控制、收發(fā)控制和數(shù)據(jù)存儲轉(zhuǎn)移。
1、 波特率
? ? ? ? 波特率,即每秒傳輸?shù)亩M制位數(shù),用 b/s (bps)表示,通過對時鐘的控制可以改變波特率。在配置波特率時,我們向波特比率寄存器 USART_BRR 寫入?yún)?shù),修改了串口時鐘 的分 頻 值USARTDIV 。USART_BRR 寄存 器 包括 兩 部分 , 分別 是 DIV_Mantissa(USARTDIV 的整數(shù)部分)和 DIV_Fraction(USARTDIV 的小數(shù))部分,最終,計算公式為 USARTDIV=DIV_Mantissa+(DIV_Fraction/16)。
USARTDIV 是對串口外設(shè)的時鐘源進行分頻的,對于 USART1,由于它掛載在 APB2總線上,所以它的時鐘源為 f PCLK2 ;而 USART2、3 掛載在 APB1 上,時鐘源則為 fPCLK1,串口的時鐘源經(jīng)過 USARTDIV 分頻后分別輸出作為發(fā)送器時鐘及接收器時鐘,控制發(fā)送和接收的時序。
2、 收發(fā)控制
? ? ? ? 寄存器 :CR1、CR2、CR3 和 SR,即USART 的三個控制寄存器(Control Register)及一個狀態(tài)寄存器(Status Register)。通過向寄存器寫入各種控制參數(shù)來控制發(fā)送和接收,如奇偶校驗位、停止位等,還包括對USART 中斷的控制;串口的狀態(tài)在任何時候都可以從狀態(tài)寄存器中查詢得到。具體的控制和狀態(tài)檢查,我們都是使用庫函數(shù)來實現(xiàn)的。
3、 數(shù)據(jù)存儲轉(zhuǎn)移
? ? ? ? 收發(fā)控制器根據(jù)我們的寄存器配置,對數(shù)據(jù)存儲轉(zhuǎn)移部分的移位寄存器進行控制。當我們需要發(fā)送數(shù)據(jù)時,內(nèi)核或 DMA 外設(shè)(一種數(shù)據(jù)傳輸方式,在后面介紹)把數(shù)據(jù)從內(nèi)存(變量)寫入到發(fā)送數(shù)據(jù)寄存器 TDR 后,發(fā)送控制器將適時地自動把數(shù)據(jù)從 TDR 加載到發(fā)送移位寄存器,然后通過串口線 Tx,把數(shù)據(jù)一位一位地發(fā)送出去,當數(shù)據(jù)從 TDR轉(zhuǎn)移到移位寄存器時,會產(chǎn)生發(fā)送寄存器 TDR 已空事件 TXE,當數(shù)據(jù)從移位寄存器全部發(fā)送出去時,會產(chǎn)生數(shù)據(jù)發(fā)送完成事件 TC,這些事件可以在狀態(tài)寄存器中查詢到。
而接收數(shù)據(jù)則是一個逆過程,數(shù)據(jù)從串口線 Rx 一位一位地輸入到接收移位寄存器,然后自動地轉(zhuǎn)移到接收數(shù)據(jù)寄存器 RDR,最后用內(nèi)核指令或 DMA
?
三、UART
串口配置流程:
(1)??????使能串口1的時鐘
(2)??????配置串口1的I/O
(3)??????配置串口1的工作模式,具體為波特率為 115200 、8 個數(shù)據(jù)位、1 個停止位、無硬件流控制。即 115200 8-N-1。
void USART1_Config(void) {GPIO_InitTypeDef GPIO_InitStructure; // 串口IO結(jié)構(gòu)體USART_InitTypeDef USART_InitStructure;/* 配置串口時鐘 */RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);/* TX --PA9 -- 通用推挽式輸出 -- 50MHZ */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);/* RX --PA10 -- 輸入*/GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOA, &GPIO_InitStructure);/* 串口初始化 -- 115200-8-1 */USART_InitStructure.USART_BaudRate = 115200; // 波特率115200USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 8位數(shù)據(jù)位USART_InitStructure.USART_StopBits = USART_StopBits_1; // 1位停止位USART_InitStructure.USART_Parity = USART_Parity_No ; // 無奇偶校驗位USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowC ontrol_None; // 無硬件流USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // 配置串口的模式。為了配置雙線全雙工通信,需要把 Rx 和 Tx 模式都開啟。USART_Init(USART1, &USART_InitStructure); // 填充完結(jié)構(gòu)體, 向寄存器寫入配置參數(shù)USART_Cmd(USART1, ENABLE); // 使能 USART1 外設(shè) }<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">?</span>? ? ? ? 要想 printf() 函數(shù)工作的話,我們需要把 printf() 重新定向到串口中。為了實現(xiàn)重定向 printf() 函數(shù),我們需要重寫 fputc() 這個 C 標準庫函數(shù),因為 printf()在C 標準庫函數(shù)中實質(zhì)是一個宏,最終是調(diào)用了 fputc() 這個函數(shù)。
// 重定向到串口 int fputc(int ch, FILE *f) {/* 發(fā)送一個字節(jié)數(shù)據(jù)到 串口 */USART_SendData(USART1, (uint8_t) ch);/* 等待發(fā)送完畢 */while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);return (ch); }總結(jié)
以上是生活随笔為你收集整理的STM32——串口通信的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: tkinter-界面化抽签小程序
- 下一篇: 线性链表java实现_java实现线性单