目錄
- 一、什么是USART
- 1. USART簡介
- 2. STM32F4中的USART
- 2.1 USART的發送/接收引腳
- 2.2 USART轉為USB介面
- 二、常用的串口相關暫存器
- 三、程式撰寫
- 1. 串口配置的一般步驟
- 2. 撰寫程式
參考正點原子的視頻教程,本文我們將撰寫一段以USART作為通信串口、接收到資料后立即引發中斷、并執行中斷處理函式將資料發送給MCU的程式,
一、什么是USART
1. USART簡介
USART(Universal Synchronous/Asynchronous Receiver/Transmitter)的全稱為通用同步/異步串行接收/發送器,它與普通串口UART的不同在于,USART有同步、異步兩種作業模式;而UART是經過裁剪后的USART,只有異步作業模式,
2. STM32F4中的USART
2.1 USART的發送/接收引腳
STM32F4中有兩個USART(USART1、USART2),其中,我們以USART1為例,它的發送、接收與PA9、PA10引腳相連,從如下的GPIO引腳復用圖中可以看出,PA9可以復用為USART1的發送(TX)功能,而PA10可以復用為USART1的接收(RX)功能,

2.2 USART轉為USB介面
單片機通常需要與電腦互相傳輸資料,但是電腦沒有USART介面,這該怎么辦呢?設計者通常通過一個芯片把USART介面轉換為USB介面,這樣就可以與電腦通信了,
能實作USART轉USB的芯片有很多,STM32F4中使用的是CH340G,

STM32F4中USART1轉USB的原理圖如下所示:

其中,TXD/RXD 是相對于 CH340G 來說的,也就是 USB 串口的發送和接受腳,而 USART1_RX/USART1_TX 則是相對于 STM32F407ZGT6 來說的,這樣,通過對接,就可以實作 USB 串口和 STM32F407ZGT6 的串口通信了,
注:在本文的實驗中,就是用USB串口把USB信號轉換為串口信號,進而通過PA9和PA10的復用功能來與單片機進行通信,
二、常用的串口相關暫存器
常用的串口相關暫存器有三個:
- USART_SR 狀態暫存器,用來記錄一些狀態,如是否接收到資料,是否要發送資料等
- USART_DR 資料暫存器,用來存盤資料,包括要接收的資料和要發送的資料等
- USART_BRR 波特率暫存器,用來調整波特率的大小,
其中,USART_SR和USART_DR的各個位的含義在**《STM32F4xx中文參考手冊》的26.6節可以查到, 本文不再贅述,這里只簡要介紹一下USART_BRR**波特率暫存器的內部結構:
在上篇博文【STM32F4】四、串口通信1——硬體部分中我們在第三部分列出過,下面我們只把波特率發生器的硬體部分展示在下圖中:

首先由USART_BRR暫存器產生初始的時鐘信號,假設頻率為** f ;輸入到分頻系數為USARTDIV的分頻器后,輸出信號頻率變為 f / USARTDIV**;在經過采樣除法器后,最終輸出信號的波特率為** f / USARTDIV / [8 x (2 - OVER8)] **,其中,OVER8可人為設定,
其中,初始頻率 f 通常是固定的,OVER8 通常設為0;那么公式就簡化為波特率 = f / USARTDIV / 16,而為了得到最終的波特率,我們要求的其實就是唯一的可變引數USARTDIV,實際上它也是由USART_BRR暫存器決定的,
但在程式中,我們不需自己計算USART_BRR的配置,我們只要把想要的波特率(如115200)直接寫入程式、傳給相應函式即可,STM32F4提供的庫函式會幫我們計算并對USART_BRR進行配置,
三、程式撰寫
1. 串口配置的一般步驟
根據正點原子的課程,列出串口配置(帶中斷回應)的一般程序如下:
① 必要的時鐘使能
- 串口時鐘使能:RCC_APBxPeriphClockCmd();
- GPIO時鐘使能:RCC_AHB1 PeriphClockCmd();
注:要想使用一個外設,必須要對【外設】、以及【連接外設的GPIO引腳】的時鐘進行使能,② 引腳復用映射:GPIO_PinAFConfig():
③ GPIO埠模式設定:GPIO_Init(); //模式設定為GPIO_Mode_AF
④ 串口引數初始化:USART_Init(); //配置波特率等引數
⑤ 開啟中斷并且初始化NVIC(如果需要開啟中斷才需要這個步驟):
- NVIC_Init();
- USART_ITConfig();
⑥ 使能串口:USART_Cmd();
⑦ 撰寫中斷處理函式:USARTx_IRQHandler();
⑧ 串口資料收發:
- void USART_SendData(); //從DR暫存器中將資料發送出去
- unit16_t USART_ReceiveData(); //從DR暫存器讀取接收到的資料
⑨:串口傳輸狀態獲取:
- FlagStatus USART_GetFlagStatus();
- void USART_ClearITPendingBit();
下面我們也將按照上述步驟,一一撰寫程式,
2. 撰寫程式
下面我們把經過詳細注釋的代碼放上來,全都是按照上述九個步驟來寫的:
#include "stm32f4xx.h"
#include "usart.h"
#include "delay.h"
void My_USART1_Init(void) //配置和初始化的程式,除中斷處理函式外,其他的配置都在這里面
{
GPIO_InitTypeDef GPIO_InitStructure; //用于GPIO配置的結構體
USART_InitTypeDef* USART_InitStruct; //用于USART配置的結構體
NVIC_InitTypeDef* NVIC_InitStruct; //用于NVIC配置的結構體
//===============================一、串口時鐘使能===================================
//使能USART1,由于USART1掛載在APB2總線下,所以要去RCC相關的庫函式中搜索APB2的時鐘使能函式
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
//=================================GPIO時鐘使能=====================================
//因為要通過PA9和PA10的復用功能來使用UART1,所以也要使能GPIOA的時鐘,GPIOA掛載在AHB1總線下
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
//===============================二、引腳復用映射===================================
//通過下面這個函式,把PA9配置為復用功能——USART1_TX,PA10配置為復用功能——USART1_RX
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);
//=============================三、埠模式設定==================================
//下面要配置PA9和PA10配置為復用模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //GPIO_Mode_OUT; //AF即復用模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//================================四、串口引數初始化=================================
//初始化USART1的配置
USART_InitStruct->USART_BaudRate = 115200; //波特率
USART_InitStruct->USART_HardwareFlowControl = USART_HardwareFlowControl_None;//不使用硬體流控制
USART_InitStruct->USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //把發送和接收功能都進行使能
USART_InitStruct->USART_Parity = USART_Parity_No;//不使用奇偶校驗
USART_InitStruct->USART_StopBits = USART_StopBits_1;//使用1個停止位
USART_InitStruct->USART_WordLength = USART_WordLength_8b;//因為沒有奇偶檢驗,所以可以使用8位字長
USART_Init(USART1, USART_InitStruct);
//====================================================================
//=============如果不使用中斷,那么這個程式到這里就可以結束了=============
//====================================================================
//=============================五、開啟中斷并且初始化NVIC============================
//配置NVIC
//首先設定中斷優先級分組
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
//再初始化NVIC
NVIC_InitStruct->NVIC_IRQChannel = USART1_IRQn;//不同的通道定義在頂層頭檔案stm32f4xx.h中 //設定NVIC通道為USART1的通道
NVIC_InitStruct->NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority = 1;//設定搶占優先級為1
NVIC_InitStruct->NVIC_IRQChannelSubPriority = 1;//設定回應優先級為1
NVIC_Init(NVIC_InitStruct);
//==================================六、使能串口====================================
//使能USART1
USART_Cmd(USART1, ENABLE);
//使能USART1的某種中斷
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//把接收非空中斷USART_IT_RXNE使能,即一旦接收到了資訊,就引發中斷,且執行相應的中斷函式
//下一步就要在下面定義USART1的中斷服務函式,函式名是固定的,在官方的系統系統檔案中startup_stm32f40_41xxx.s已經給出:USART1_IRQHandler
}
//================================七、撰寫中斷處理函式===============================
void USART1_IRQHandler(void)
{
u8 res; //用來記錄接收到的資料,因為我們在上面設定的8位字長代表一個資料,所以這里可以用u8來記錄?
//==============================九、串口傳輸狀態獲取=================================
if(USART_GetITStatus(USART1, USART_IT_RXNE)) //讀取USART_IT_RXNE標志位的狀態)
{
//================================八、串口資料收發==================================
res = USART_ReceiveData(USART1); //讀取接收到的資料
USART_SendData(USART1, res); //把接收到的資料發出去
}
}
//主函式
int main(void)
{
My_USART1_Init();
while(1); //在這里無限回圈即可,程式會自動執行 中斷 和 中斷處理函式
return 0;
}
注: 如果編譯時程式出錯,可能是因為在官方庫檔案usart.c里已經定義過一個中斷處理函式USART1_IRQHandler(),把它注釋掉或者把這個檔案刪掉即可,

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/244357.html
標籤:其他
上一篇:Parallels Desktop 16 完美解決無法聯網,無法連接USB
下一篇:智能車培訓階段一第三部分內容摘要

