串口通信是一種設備間非常常用的串行通行方式,其簡單便捷,大部分電子設備都支持。
一、物理層
常用RS-232標準,主要規定了信號的用途、通信接口以及信號的電平標準。
“DB9接口”之間通過串口信號線建立起連接,串口信號線使用”RS-232標準“傳輸數據信號,這些信號通過記過電平轉換芯片轉換成控制器能識別的TLL標準的電平信號,才能實現通信。
1.電平標準
可分為TTL標準以及RS-232標準。
常見的電子電路中常見TTL的電平標準,理想狀態使用5V表示二進制邏輯1,0V表示邏輯0;而為了增加串口通信的遠距離傳輸以及抗干擾能力,RS-232使用-15V表示邏輯1,+15V表示邏輯0。
因為控制器一般使用TTL電平標準,所以常常使用MA3232芯片將TTL以及RS-232電平的信號進行互相轉換。
2.RS-232信號線
最初RS-232串口標準常用于計算機、路由與調制調節器(“貓”)之間通信,設備被分為數據終端設備DTE(計算機、路由)和數據通信設備DCE(調制調節器)。舊臺式計算機,一般都有RS-232標準的COM口,也稱DB9接口。
DB9信號線說明
公頭標準接法,只要使用直通型串口線連接起來即可。
二、協議層
協議層中,規定了數據包的內容,它由起始位、主體數據、校驗位以及停止位組成,通信雙方的數據包格式要約定一致才能正常收發數據 。
1、波特率
異步通信中由于沒有時鐘信號,所以2個通信設備需約定好波特率,常見的有4800、9600、115200等。
2、通信的起始和停止信號
串口通信的一個數據包從起始信號開始,知道停止信號結束。數據包的起始信號由一個邏輯0的數據位表示,而數據包的停止信號可由0.5、1、1.5或2個邏輯1的數據位表示,只要雙方約定一致即可。
3、有效數據
在數據包的起始位之后緊接著的就是要傳輸的主體數據內容,也稱為有效數據,有效數據的長度常被約定為 5、6、7或 8位長
4、數據校驗
在有效數據之后,有一個可選的數據校驗位。由于數據通信相對容易受到外部干擾導致傳輸數據出現偏差,可以在傳輸過程加上校驗位來解決這個問題。校驗方法有奇校驗(odd)、偶校驗(even)、0校驗(space)、1校驗(mark)以及無校驗(noparity)。 奇校驗要求有效數據和校驗位中“1”的個數為奇數,比如一個 8 位長的有效數據為:01101001,此時總共有 4 個“1”,為達到奇校驗效果,校驗位為“1”,最后傳輸的數據將是 8 位的有效數據加上 1 位的校驗位總共 9 位。
偶校驗與奇校驗要求剛好相反,要求幀數據和校驗位中“1”的個數為偶數,比如數據幀:11001010,此時數據幀“1”的個數為 4 個,所以偶校驗位為“0”。 0 校驗是不管有效數據中的內容是什么,校驗位總為“0”,1 校驗是校驗位總為“1”。
三、STM32的USART簡介
通用同步異步收發器是一個串行通信設備,可以靈活的與外部設備進行全雙工數據交換。有別與USART,還有一個UART,它在USART基礎上裁剪掉了同步通信功能,只有異步通信。簡單區分同步和異步就是看通信時需不需要對外提供時鐘輸出,我們平時用的串口通信基本都是 UART。
串口通信一般是以幀格式傳輸數據,即一幀一幀傳輸,每幀包含有起始信號、數據信息、停止信息,可能還有校驗信息。
USART 滿足外部設備對工業標準 NRZ 異步串行數據格式的要求,并且使用了小數波特率發生器,可以提供多種波特率,使得它的應用更加廣泛。USART 支持同步單向通信和半雙工單線通信;還支持局域互連網絡 LIN、智能卡(SmartCard)協議與 lrDA(紅外線數據協會) SIR ENDEC規范。
USART支持使用 DMA,可實現高速數據通信。
四、USART功能框圖剖析
下文結合圖片看加深理解。
1、功能引腳
TX:發送數據輸出引腳。
RX:接收。
SW_RX:數據接收引腳,屬于內部引腳。
nRTS:請求以發送,n表示低電平有效。如果使能 RTS 流控制,當USART接收器準備好接收新數據時就會將nRTS變成低電平;當接收寄存器已滿時,nRTS將被設置為高電平。該引腳只適用于硬件流控制。
nCTS:清除以發送(Clear To Send),n表示低電平有效。如果使能 CTS流控制,發送器在發送下一幀數據之前會檢測 nCTS 引腳,如果為低電平,表示可以發送數據,如果為高電平則在發送完當前數據幀之后停止發送。該引腳只適用于硬件流控制。
SCLK:發送器時鐘輸出引腳。這個引腳僅適用于同步模式。
USART:下圖是STM32F103VET6芯片的USART引腳
USART1的時鐘來源于APB2總線時鐘,最大頻率為72MHZ,其他4個時鐘來源于APB1總線時鐘,最大頻率36MHZ。UART只有異步傳輸功能,沒有SCLK、nCTS和nRTS功能引腳。
2.數據寄存器
USART說數據寄存器(USART_DR)只有低 9 位有效,并且第 9 位數據是否有效要取決于USART 控制寄存器 1(USART_CR1)的 M 位設置,當 M 位為 0 時表示 8 位數據字長,當 M位為 1 表示 9 位數據字長,我們一般使用 8位數據字長。
USART_DR包含了已發送的數據或者接收到的數據。USART_DR實際是包含了兩個寄存器,一個專門用于發送的可寫 TDR,一個專門用于接收的可讀 RDR。當進行發送操作時,往 USART_DR寫入數據會自動存儲在 TDR內;當進行讀取操作時,向 USART_DR讀取數據會自動提取 RDR 數據。
TDR和RDR都是介于系統總線和移位寄存器之間。串行通信是一個位一個位傳輸的,發送時把 TDR 內容轉移到發送移位寄存器,然后把移位寄存器數據每一位發送出去,接時把接收到的每一位順序保存在接收移位寄存器內然后才轉移到 RDR。
USART 支持 DMA 傳輸,可以實現高速數據傳輸。
3.控制器
USART有專門控制發送的發送器、控制接收的接收器,還有喚醒單元、中斷控制等。
使用USART之前需要向USART_CR1寄存器的UE位置1使能USART,UE位用于開啟供給串口的時鐘。發送或者接收數據字長可選8或9位,由USARTT_CR1的M位控制。
1)發送器
當USART_CR1寄存器的發送使能位TE置1時,啟動數據發送,發送移位寄存器的數據會在TX引腳輸出,低位在前,高位在后。如果是同步模式SCLK也輸出時鐘信號。
一個字符幀發送需要3部分:起始位、數據幀、停止位。起始位是一個位周期的低電平,位周期就是每一位占用的時間 ;數據幀就是我們要發送的8或9位數據,數據是最低位開始傳輸的;停止位是一定時間周期的高電平。
停止位的時間長短可以通過USART控制寄存器2(USART_CR2)的STOP[1:0]位控制,可選0.5個、1個、1.5個、2個停止位。默認使用1個停止位。2個停止位適用于正常USART模式、單線模式和調制解調器模式。0.5和1.5個停止位用于智能卡模式。
當發使能位TE置1之后,發送器開始會發送一個空閑幀(一個數據幀長度的高電平),接下來就可以往USART_DR寄存器寫入要發送的數據。在寫入最后一個數據后,需等待USART狀態寄存器(USART_SR)的TC位為1,表示數據傳輸完成。USART_CR1寄存器的TCIE位置1,則產生中斷。
發送數據時,幾個重要的標志位如下:
TE:發送使能。
TXE:發送寄存器為空,發送單個字節時使用。
TC:發送完成,發送多個字節數據時候使用。
TXIE:發送完成中斷使能。
2)接收器
將CR1寄存器的RE位置1,使能USART接收,使得接收器在RX線開始搜索起始位。在確定起始位后,就根據RX線電平狀態把數據存放在接收移位寄存器內。接收完成后就把接收移位寄存器的數據移到PDR內,并把USART_SR寄存器的RXNE位置。如果USART_CR2寄存器的RXNEIE置1可以產生中斷。
接收數據時,幾個重要的標志位如下:
RE: 接收使能。
RXNE:讀數據寄存器非空。
RXNEIE:發送完成中斷使能。
4.小數波特率生成
USART 的發送器和接收器使用相同的波特率。計算公式如下:
其中,f PLCK 為 USART 時鐘, USARTDIV 是一個存放在波特率寄存器(USART_BRR)的一個無符號定點數。其中 DIV_Mantissa[11:0]位定義 USARTDIV 的整數部分,DIV_Fraction[3:0]位定義 USARTDIV 的小數部分。
例如:DIV_Mantissa=24(0x18),DIV_Fraction=10(0x0A),此時 USART_BRR 值為0x18A;那么USARTDIV的小數位10/16=0.625;整數位24,最終USARTDIV的值為24.625。
如果知道 USARTDIV 值為 27.68,那么 DIV_Fraction=16*0.68=10.88,最接近的正整數為 11,所以 DIV_Fraction[3:0]為 0xB;DIV_Mantissa=整數(27.68)=27,即為 0x1B。
波特率的常用值有 2400、9600、19200、115200。下面以實例講解如何設定寄存器值得到波特率的值。
我們知道 USART1 使用 APB2 總線時鐘,最高可達 72MHz,其他 USART 的最高頻率為 36MHz。我們選取 USART1 作為實例講解,即 f PLCK =72MHz。為得到 115200bps 的波特率,此時:115200 =72000000/(16 ? USARTDIV) 解 得 USARTDIV=39.0625 , 可 算 得 DIV_Fraction=0.0625*16=1=0x01 ,DIV_Mantissa=39=0x17,即應該設置 USART_BRR 的值為 0x171。
5.校驗控制
STM32F103系列控制器USART支持奇偶校驗。使用校驗位時,串口傳輸的長度將在8位數據幀上加上1位的校驗位,總共9位,此時USART_CR1寄存器的M位需要設置位1,即9數據位。將USART_CR1寄存器的PCE位置1就可以啟動奇偶校驗控制,奇偶校驗由硬件自動完成。啟動了奇偶校驗控制之后,發送數據幀時會自動添加校驗位,接收數據自動驗證校驗位。接收數據時如果出現奇偶校驗位驗證失敗,會將USART_SR寄存器的PE置1,并可以產生奇偶校驗中斷。
使用了奇偶校驗控制位后,每個字符幀的格式變成了:起始位+數據幀+校驗位+停止位。
6.中斷控制
五、USART初始化結構體
初始化結構體的定義在stm32f10x_usart.h文件中,初始化庫函數定義在stm32f10x_usart.c中。
USART初始化結構體
typedef struct {
uint32_t USART_BaudRate; // 波特率
uint16_t USART_WordLength; // 字長
uint16_t USART_StopBits; // 停止位
uint16_t USART_Parity; // 校驗位
uint16_t USART_Mode; // USART 模式
uint16_t USART_HardwareFlowControl; // 硬件流控制
} USART_InitTypeDef;
1)USART_BaudRate:波特率設置。標準庫函數會根據設定值計算得到USARTDIV值,從而設置USART_BRR的寄存器值。
2)USART_WordLength:.數據幀字長,它設定USART_CR1寄存器M位的值。如果沒有使能奇偶位校驗控制,一般使用8數據位。
3)USART_StopBits停止位設置。
4)USART_Parity:奇偶校驗控制選擇。
5)USART_Mode:USART模式選擇有USART_Mode_Rx和USART_Mode_Tx,允許使用邏輯或運算選擇兩個,它設定 USART_CR1寄存器的 RE 位和 TE位。
6)USART_HardwareFlowControl:硬件流控制選擇,只有在硬件流控制模式下才有效,可選有,使能RTS、使能CTS、同時使能RTS和CTS、不使用硬件流。
當使用同步模式,需配置SCLK引腳輸出脈沖的屬性,標準庫使用一個時鐘初始化結構體USART_ClockInitTypeDef來設置,該結構體內容只有在同步模式下才設置。
USART時鐘初始化結構體
typedef struct {
uint16_t USART_Clock; // 時鐘使能控制
uint16_t USART_CPOL; // 時鐘極性
uint16_t USART_CPHA; // 時鐘相位
uint16_t USART_LastBit; // 最尾位時鐘脈沖
} USART_ClockInitTypeDef;
1)USART_Clock:同步模式下SCLK引腳上時鐘輸出使能控制,可選禁止時鐘輸出(USART_Clock_Disable)或開啟時鐘輸出(USART_Clock_Enable);如果使用同步模式發送,一般都需要開啟時鐘。它設定 USART_CR2 寄存器的 CLKEN 位的值。 ?
2)USART_CPOL:同步模式下 SCLK 引腳上輸出時鐘極性設置,可設置在空閑時SCLK引腳為低電平(USART_CPOL_Low)或高電平(USART_CPOL_High)。它設定USART_CR2寄存器的 CPOL位的值。
3)USART_CPHA:同步模式下 SCLK 引腳上輸出時鐘相位設置,可設置在時鐘第一個變化沿捕獲數據(USART_CPHA_1Edge)或在時鐘第二個變化沿捕獲數據。它設定 USART_CR2寄存器的 CPHA位的值。USART_CPHA與 USART_CPOL配合使用可以獲得多種模式時鐘關系。
4)USART_LastBit:選擇在發送最后一個數據位的時候時鐘脈沖是否在SCLK引腳輸出,可以是不輸出脈沖(USART_LastBit_Disable) 、 輸出脈沖(USART_LastBit_Enable)。它設定 USART_CR2 寄存器的 LBCL位的值。
六、USART1接發通信實驗
USART 只需兩根信號線即可完成雙向通信,對硬件要求低,使得很多模塊都預留USART 接口來實現與其他模塊或者控制器進行數據傳輸,比如 GSM 模塊,WIFI 模塊、藍牙模塊等等。在硬件設計時,注意還需要一根“共地線”。
來編寫一個程序實現開發板與電腦通信,在開發板上電時通過USART發送一串字符串給電腦,然后開發板進入中斷接收等待狀態,如果電腦有發送數據過來,開發板就會產生中斷,我們在中斷服務函數接收數據,并馬上把數據返回發送給電腦。
1、編程思路
1) 使能 RX和 TX 引腳 GPIO時鐘和 USART時鐘;
2) 初始化 GPIO,并將 GPIO復用到 USART上;
3) 配置 USART 參數;
4) 配置中斷控制器并使能 USART接收中斷;
5) 使能 USART;
6) 在 USART接收中斷服務函數實現數據接收和發送。
2、代碼分析
1)GPIO和USART宏定義
/**
* 串口宏定義,不同的串口掛載的總線和 IO 不一樣,移植時需要修改這幾個宏
*/
// 串口 1-USART1
#define DEBUG_USARTx USART1
#define DEBUG_USART_CLK RCC_APB2Periph_USART1
#define DEBUG_USART_APBxClkCmd RCC_APB2PeriphClockCmd
#define DEBUG_USART_BAUDRATE 115200
// USART GPIO 引腳宏定義
#define DEBUG_USART_GPIO_CLK (RCC_APB2Periph_GPIOA)
#define DEBUG_USART_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd
#define DEBUG_USART_TX_GPIO_PORT GPIOA
#define DEBUG_USART_TX_GPIO_PIN GPIO_Pin_9
#define DEBUG_USART_RX_GPIO_PORT GPIOA
#define DEBUG_USART_RX_GPIO_PIN GPIO_Pin_10
#define DEBUG_USART_IRQ USART1_IRQn
#define DEBUG_USART_IRQHandler USART1_IRQHandler
使用宏定義方便程序移植和升級 。開發板中的 CH340G 的收發引腳默認通過跳帽連接到 USART1,如果想使用其他串口,可以把 CH340G 跟 USART1 直接的連接跳帽拔掉,然后再把其他串口的 IO用杜邦線接到 CH340G的收發引腳即可。
這里我們使用USART1,設定波特率為115200,選定USART的GPIO為PA9和PA10。
2)嵌套向量中斷控制器NVIC配置
static void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* 嵌套向量中斷控制器組選擇 */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/* 配置 USART 為中斷源 */
NVIC_InitStructure.NVIC_IRQChannel = DEBUG_USART_IRQ;
/* 搶斷優先級為 1 */
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
/* 子優先級為 1 */
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
/* 使能中斷 */
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
/* 初始化配置 NVIC */
NVIC_Init(&NVIC_InitStructure);
}
3)USART初始化配置
void USART_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
// 打開串口 GPIO 的時鐘
DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE);
// 打開串口外設的時鐘
DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE);
// 將 USART Tx 的 GPIO 配置為推挽復用模式
GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);
// 將 USART Rx 的 GPIO 配置為浮空輸入模式
GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);
// 配置串口的工作參數
// 配置波特率
USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE;
// 配置 針數據字長
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
// 配置停止位
USART_InitStructure.USART_StopBits = USART_StopBits_1;
// 配置校驗位
USART_InitStructure.USART_Parity = USART_Parity_No ;
// 配置硬件流控制
USART_InitStructure.USART_HardwareFlowControl =
USART_HardwareFlowControl_None;
// 配置工作模式,收發一起
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
// 完成串口的初始化配置
USART_Init(DEBUG_USARTx, &USART_InitStructure);
// 串口中斷優先級配置
NVIC_Configuration();
// 使能串口接收中斷
USART_ITConfig(DEBUG_USARTx, USART_IT_RXNE, ENABLE);
// 使能串口
USART_Cmd(DEBUG_USARTx, ENABLE);
}
調用RCC_APB2PeriphClockCmd函數開啟GPIO端口時鐘,使用GPIO之前必須開啟對應的時鐘。RCC_APB2PeriphClockCmd函數開啟USART時鐘。
使用GPIO之前需要初始化配置它,并且還要添加特殊設置,因為我們使用它作為外設引腳,一般都有特殊功能,模式設置為復用功能,把串口的Tx引腳配置為復用推挽輸出,Rx引腳為浮空輸入,數據完全由外部輸入決定。
配置USAT1通信參數為:波特率115200,字長8,1個停止位,沒有校驗位,不使用硬件流控制,收發一體工作模式,然后調用USART初始化函數完成配置。
USART接收中斷,需要配置NVIC,這里調用NVIC_Configuration函數完成配置,然后調用USART_ITConfig函數使能USART接收中斷。
最后 調用USART_Cmd函數使能USART,最終配置的是USART_CR1的UE位,具體作用是開啟USART工作時鐘,沒有時鐘那USART這個外設就工作不了。
4)字符發送
/***************** 發送一個字符 **********************/
void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch)
{
/* 發送一個字節數據到 USART */
USART_SendData(pUSARTx,ch);
/* 等待發送數據寄存器為空 */
while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
}
/***************** 發送字符串 **********************/
void Usart_SendString( USART_TypeDef * pUSARTx, char *str)
{
unsigned int k=0;
do {
Usart_SendByte( pUSARTx, *(str + k) );
k++;
} while (*(str + k)!='\0');
/* 等待發送完成 */
while (USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET) {
}
}
Usart_SendByte用來指定USART發送一個ASCLL碼字符,它有2個形參:第一個USART第二個待發送的字符,它通過調用庫函數USART_SendData來實現等待,并且增加了等待發送完成功能,它接收兩個參數:一個是USART,一個是事件標志。這里循環檢測發送數據寄存器這個標志,當跳出while循環時,說明發送數據寄存器為空。
Usart_SendString函數用來發送一個字符串,實際調用Usar_SendByte函數發送每個字符,直到遇到空字符才停止發送。最后使用循環檢測發送完成的事件標志TC,保證數據完成后才退出函數。
5)USART中斷服務函數
void DEBUG_USART_IRQHandler(void)
{
uint8_t ucTemp;
if (USART_GetITStatus(DEBUG_USARTx,USART_IT_RXNE)!=RESET)
{
ucTemp = USART_ReceiveData( DEBUG_USARTx );
USART_SendData(USARTx,ucTemp);
}
}
該代碼在stm32f10x_it.c文件中的,用來集中存放中斷服務函數。當使能了中斷并中斷發生時,就會執行這里的中斷服務函數。
6)main函數
int main(void)
{
/*初始化 USART 配置模式為 115200 8-N-1,中斷接收*/
USART_Config();
Usart_SendString( DEBUG_USARTx,"這是一個串口中斷接收回顯實驗\n");
while (1) {
}
}
USART_Config()函數完成USART初始化配置,包括GPIO USART配置,接收中斷使能等。
接下來調用字符發送函數把數據發給串口調試助手。
最后什么也不做,等待接收中斷產生,并在中斷服務函數中回傳數據。
七、USART1指令控制RGB彩燈實驗
1、思路要點
1)初始化配置RGB彩色燈GPIO
2)使能RX和TX引腳GPIO時鐘和USART時鐘
3)初始化GPIO,并將GPIO復用到USART上
4)配置USART參數
5)使能USART
6)獲取指令輸入,根據控制RGB彩色燈
2、代碼分析
1)GPIO和USART宏定義
1 #define DEBUG_USARTx USART1
2 #define DEBUG_USART_CLK RCC_APB2Periph_USART1
3 #define DEBUG_USART_APBxClkCmd RCC_APB2PeriphClockCmd
4 #define DEBUG_USART_BAUDRATE 115200
5
6 // USART GPIO 引腳宏定義
7 #define DEBUG_USART_GPIO_CLK (RCC_APB2Periph_GPIOA)
8 #define DEBUG_USART_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd
9
10 #define DEBUG_USART_TX_GPIO_PORT GPIOA
11 #define DEBUG_USART_TX_GPIO_PIN GPIO_Pin_9
12 #define DEBUG_USART_RX_GPIO_PORT GPIOA
13 #define DEBUG_USART_RX_GPIO_PIN GPIO_Pin_10
14
15 #define DEBUG_USART_IRQ USART1_IRQn
16 #define DEBUG_USART_IRQHandler USART1_IRQHandler
2)USART初始化配置
1 void USART_Config(void)
2 {
3 GPIO_InitTypeDef GPIO_InitStructure;
4 USART_InitTypeDef USART_InitStructure;
5
6 // 打開串口 GPIO 的時鐘
7 DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE);
8
9 // 打開串口外設的時鐘
10 DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE);
11
12 // 將 USART Tx 的 GPIO 配置為推挽復用模式
13 GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN;
14 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
15 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
16 GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);
17
18 // 將 USART Rx 的 GPIO 配置為浮空輸入模式
19 GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN;
20 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
21 GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);
22
23 // 配置串口的工作參數
24 // 配置波特率
25 USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE;
26 // 配置 針數據字長
27 USART_InitStructure.USART_WordLength = USART_WordLength_8b;
28 // 配置停止位
29 USART_InitStructure.USART_StopBits = USART_StopBits_1;
30 // 配置校驗位
31 USART_InitStructure.USART_Parity = USART_Parity_No ;
32 // 配置硬件流控制
33 USART_InitStructure.USART_HardwareFlowControl =
34 USART_HardwareFlowControl_None;
35 // 配置工作模式,收發一起
36 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
37 // 完成串口的初始化配置
38 USART_Init(DEBUG_USARTx, &USART_InitStructure);
39
40 // 使能串口
41 USART_Cmd(DEBUG_USARTx, ENABLE);
42 }
與上實驗基本一樣,唯一不同沒使用使能中斷
3)重定向printf和scanf函數
1 ///重定向 c 庫函數 printf 到串口,重定向后可使用 printf 函數
2 int fputc(int ch, FILE *f)
3 {
4 /* 發送一個字節數據到串口 */
5 USART_SendData(DEBUG_USARTx, (uint8_t) ch);
6
7 /* 等待發送完畢 */
8 while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET);
9
10 return (ch);
11 }
12
13 ///重定向 c 庫函數 scanf 到串口,重寫向后可使用 scanf、getchar 等函數
14 int fgetc(FILE *f)
15 {
16 /* 等待串口輸入數據 */
17 while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_RXNE) == RESET);
18
19 return (int)USART_ReceiveData(DEBUG_USARTx);
20 }
fputc函數是printf函數內部的一個函數,功能是將字符ch寫入文件指針f所指向文件的當前寫指針位置,我們使用USART函數重新修改fputc函數內容,達到類似寫入的功能。
fgetc實現字符讀取功能。
還有一點需要注意的,使用 fput和 fgetc函數達到重定向 C語言標準庫輸入輸出函數必須在 MDK的工程選項把“Use MicroLIB”勾選上,MicoroLIB 是缺省 C庫的備選庫,它對標準 C庫進行了高度優化使代碼更少,占用更少資源。
為使用 printf、scanf 函數需要在文件中包含 stdio.h頭文件。
4)輸出提示信息
1 static void Show_Message(void)
2 {
3 printf("\r\n 這是一個通過串口通信指令控制 RGB 彩燈實驗 \n");
4 printf("使用 USART 參數為:%d 8-N-1 \n",USART_BAUDRATE);
5 printf("開發板接到指令后控制 RGB 彩燈顏色,指令對應如下:\n");
6 printf(" 指令 ------ 彩燈顏色 \n");
7 printf(" 1 ------ 紅 \n");
8 printf(" 2 ------ 綠 \n");
9 printf(" 3 ------ 藍 \n");
10 printf(" 4 ------ 黃 \n");
11 printf(" 5 ------ 紫 \n");
12 printf(" 6 ------ 青 \n");
13 printf(" 7 ------ 白 \n");
14 printf(" 8 ------ 滅 \n");
15 }
5)main函數
1 int main(void)
2 {
3 char ch;
4
5 /* 初始化 RGB 彩燈 */
6 LED_GPIO_Config();
7
8 /* 初始化 USART 配置模式為 115200 8-N-1 */
9 USART_Config();
10
11 /* 打印指令輸入提示信息 */
12 Show_Message();
13 while (1)
14 {
15 /* 獲取字符指令 */
16 ch=getchar();
17 printf("接收到字符:%c\n",ch);
18
19 /* 根據字符指令控制 RGB 彩燈顏色 */
20 switch (ch)
21 {
22 case '1':
23 LED_RED;
24 break;
25 case '2':
26 LED_GREEN;
27 break;
28 case '3':
29 LED_BLUE;
30 break;
31 case '4':
32 LED_YELLOW;
33 break;
34 case '5':
35 LED_PURPLE;
36 break;
37 case '6':
38 LED_CYAN;
39 break;
40 case '7':
41 LED_WHITE;
42 break;
43 case '8':
44 LED_RGBOFF;
45 break;
46 default:
47 /* 如果不是指定指令字符,打印提示信息 */
48 Show_Message();
49 break;
50 }
51 }
52 }
首先我們定義一個字符變量來存放接收到的字符。
接下來調用 LED_GPIO_Config 函數完成 RGB 彩色 GPIO 初始化配置,該函數定義在bsp_led.c 文件內。
調用 USART_Config 函完成 USART初始化配置。
Show_Message函數使用 printf 函數打印實驗指令說明信息。
getchar函數用于等待獲取一個字符,并返回字符。我們使用 ch變量保持返回的字符,接下來判斷 ch內容執行對應的程序。
我們使用 switch語句判斷 ch 變量內容,并執行對應的功能程序。
上一篇:STM32 時鐘配置之寄存器操作
下一篇:STM32筆記:RCC結構與配置流程
推薦閱讀
史海拾趣
Chesivale Electronics公司深知人才是企業發展的核心動力。因此,公司一直注重人才隊伍建設。公司通過校園招聘、社會招聘等多種渠道吸引優秀人才加入,同時建立完善的培訓機制和晉升機制,激發員工的積極性和創造力。這些措施使得公司的人才隊伍不斷壯大,為公司的發展提供了有力的人才保障。
隨著公司規模的擴大,Baton Lock意識到單一市場已無法滿足其增長需求。于是,公司開始在全球范圍內尋找合作伙伴和設立生產基地。通過在歐洲、亞洲等地建立分支機構,Baton Lock成功打開了多個新市場,進一步提升了其品牌影響力。
在追求持續增長的道路上,CUI Inc.采取了一項重要舉措——收購加拿大電源制造商Tectrol Inc.。這次收購為CUI帶來了豐富的產品線和技術資源,尤其是Tectrol在標準和定制電源解決方案方面的領先設計能力和制造能力。通過整合Tectrol的技術和資源,CUI進一步鞏固了其在電源設計領域的領先地位,并為其未來的發展奠定了堅實的基礎。
作為國內電源管理芯片的重要廠商,芯朋微電子一直致力于實現進口替代。公司不斷投入研發,推出了一系列高效能、低功耗、品質穩定的電源管理集成電路產品,推動整機的能效提升和技術升級。這些努力使得芯朋微電子在國內電源管理芯片市場中的地位日益穩固。
AMERICASEMI公司成立于XXXX年,起初是一家專注于半導體技術研發的小型創業公司。在創立初期,公司面臨著資金短缺、市場競爭激烈等諸多挑戰。然而,憑借創始團隊對半導體技術的深刻理解和市場需求的敏銳洞察,AMERICASEMI成功開發出一系列具有競爭力的半導體產品,并逐漸在市場中占據了一席之地。
【藏書閣】 集成電路(荒井英甫)——21世紀大學新型參考教材系列 目錄: 集成電路a 1 集成電路的學習方法 1·1 集成電路的發明 1·2 集成電路發展的動力 1·3 集成電路的未來 1·4 本書的構成 練習題 引用文獻 2 集成電路中的半導體器件 2·1 pn結 2·2 雙極型晶體管 2·3 mos晶體管 2·4 集成電路 ...… 查看全部問答∨ |
|
無意在網上找到的,因此把目錄整理出來,有兄弟需要的發郵件給我yulzhu@gmail.com,注明需要哪一部分,直接發怕有些問題。 混合動力有關材料 Toyota Series - Hybrid Hybrid01 Hybrid System Overview.pdf Hybrid02 Hybrid System ...… 查看全部問答∨ |
|
求助!!!定時器同步配置問題-一個上升沿信號觸發定時器TIM2,同時根據上升沿信號啟 最近在做一個RLC(電阻、電感、電容)測量儀,測量插座只有一個,因此需要利用程序區分三種不同的器件; 區分方法是利用通過三種器件后的波形超前滯后關系判別,將正弦信號轉化為矩形波后輸入定時器通道1。與此同時將沒有經過原器件的正弦波也轉化為 ...… 查看全部問答∨ |
|
哥們太菜了,對這方面一點不懂,我想實現150mA的升壓電路,IC手冊上使用2.2uH的電感,我找到一些功率電感1A以上,感覺用不上,價格也高。不知道使用圖片里這種疊層電感是否可行,我找了一些資料,沒發現有關于這種電感電流的參數。 … 查看全部問答∨ |