串列埠通訊基本實現
串列埠功能講解
串列埠框圖
對應的板載引腳,我的是STM32F103VET6
引腳 | APB2匯流排 | APB1匯流排 | APB1匯流排 | APB1匯流排 | APB1匯流排 |
---|---|---|---|---|---|
串列埠 | USART1 | USART2 | USART3 | USART4 | USART5 |
TXD | PA9 | PA2 | PB10 | PC10 | PC12 |
RXD | PA10 | PA3 | PB11 | PC11 | PD2 |
SCLK | PA8 | PA4 | PB12 | ||
NCTS | PA11 | PA0 | PB13 | ||
NRTS | PA12 | PA1 | PB14 |
TXD:資料傳送
RXD:資料接收
SCLK:時鐘,僅同步通訊時使用
nRTS:請求傳送(Request to send)
nCTS:允許傳送(CLear to send)
注意:STM32F103VET6 系統控制器有三個 USART 和兩個 UART,其中 USART1 和時鐘來源 於 APB2 匯流排時鐘,其最大頻率為 72MHz,其他四個的時鐘來源於 APB1 匯流排時鐘,其最 大頻率為 36MHz。UART 只是非同步傳輸功能,所以沒有 SCLK、nCTS 和 nRTS 功能引腳。
資料暫存器——USART_DR:9位有效,包含一個傳送資料暫存器IDR和一個接收資料暫存器RDR,一個地址對應了兩個實體記憶體。
資料暫存器
資料暫存器——USART_DR:只有底9位有效,包含一個傳送資料暫存器TDR和一個接收資料暫存器RDR。一個地址對應了兩個實體記憶體。
資料格式
(啟動位)USART_CR1:M,0:8bit 1:9bit
(停止位)USART_CR2:STOP
(校驗位)USATR_CR1:PCE(使能校驗),PS(選擇校驗),PEIE
(校驗檢測)USART_SR:PE(校驗錯誤)
具體流程
資料傳送
UE:USART使能(USART enable) 0:時鐘與輸出被禁止 1:模組使能
當該位被清零 .
TE:傳送使能(使能後 串列埠可以傳送資料)
記憶體→(讀取)CPU或DMA→傳送資料暫存器(TDR)→傳送移位暫存器→TX
TXE(傳送資料暫存器空)→TXC(傳送移位暫存器完成)
資料接收
UE:USART使能(USART enable) 0:時鐘與輸出被禁止 1:模組使能
當該位被清零 .
RE:接收使能(使能後 串列埠可以接收資料).
RX→接收移位暫存器→接收資料暫存器(RXNE)
波特率
波特率:每秒鐘要傳送多少資料
USART_BRR:波特率暫存器
分數波特率的產生
$$
Tx / Rx 波特率 =fck/16*USARTDIV
$$
fck:外設的時鐘(PCLK1用於USART2、3、4、5,PCLK2用於USART1)
注意需要區分APB1 APB2 兩條匯流排的時鐘
USARTDIV:無符號的定點數 這12位的值設定在USART_BRR暫存器
列如:串列埠1
USART:USART1 時鐘為72M
波特率:115200
115200 = 72000000/16*USARTDIV
USARTDIV = 39.0625
DIV_Fraction = 0.0625*16 = 1 = 0x01
DIV_Mantissa = 39 = 0x17
則:USART_BRR = 0X171
基本結構體
串列埠初始化結構體
typedef struct
{
//串列埠波特率 115200
uint32_t USART_BaudRate;
/*!< This member configures the USART communication baud rate.The baud rate is computed using the following formula:- IntegerDivider = ((PCLKx) / (16 * (USART_InitStruct->USART_BaudRate))- FractionalDivider = ((IntegerDivider - ((u32) IntegerDivider)) * 16) + 0.5 */
//字長 控制暫存器M位
uint16_t USART_WordLength;
/*!< Specifies the number of data bits transmitted or received in a frame.
This parameter can be a value of @ref USART_Word_Length */
//停止位
uint16_t USART_StopBits;
/*!< Specifies the number of stop bits transmitted.This parameter can be a value of @ref USART_Stop_Bits */
//校驗位
uint16_t USART_Parity;
/*!< Specifies the parity mode.This parameter can be a value of @ref USART_Parity @note When parity is enabled, the computed parity is inserted
at the MSB position of the transmitted data (9th bit whenthe word length is set to 9 data bits; 8th bit when the word length is set to 8 data bits). */
//模式(傳送與接收)
uint16_t USART_Mode;
/*!< Specifies wether the Receive or Transmit mode is enabled or disabled.
This parameter can be a value of @ref USART_Mode */
//硬體控制流 中斷
uint16_t USART_HardwareFlowControl;
/*!< Specifies wether the hardware flow control mode is enabledor disabled.
This parameter can be a value of @ref USART_Hardware_Flow_Control */
} USART_InitTypeDef;
串列埠時鐘配置(同步還是非同步通訊)
typedef struct
{
uint16_t USART_Clock; /*!< Specifies whether the USART clock is enabled or disabled.
This parameter can be a value of @ref USART_Clock */
//極性
uint16_t USART_CPOL; /*!< Specifies the steady state value of the serial clock.
//相位 This parameter can be a value of @ref USART_Clock_Polarity */
uint16_t USART_CPHA; /*!< Specifies the clock transition on which the bit capture is made.
This parameter can be a value of @ref USART_Clock_Phase */
uint16_t USART_LastBit; /*!< Specifies whether the clock pulse corresponding to the last transmitted
data bit (MSB) has to be output on the SCLK pin in synchronous mode.
This parameter can be a value of @ref USART_Last_Bit */
} USART_ClockInitTypeDef;
程式碼實現
巨集定義需要的GPIO
//標頭檔案中的引腳 巨集定義
// 串列埠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
串列埠初始化配置
//這裡只在這個函式使用 可用static限制一下
//中斷分組配置函式
static void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* 巢狀向量中斷控制器組選擇 */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/* 配置USART為中斷源 */
NVIC_InitStructure.NVIC_IRQChannel = DEBUG_USART_IRQ;
/* 搶斷優先順序*/
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
/* 子優先順序 */
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
/* 使能中斷 */
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
/* 初始化配置NVIC */
NVIC_Init(&NVIC_InitStructure);
}
//串列埠初始化函式
void USART_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
// 開啟串列埠GPIO的時鐘
RCC_APB2PeriphClockCmd(DEBUG_USART_GPIO_CLK, ENABLE);
// 開啟串列埠外設的時鐘
RCC_APB2PeriphClockCmd(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_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DEBUG_USART_TX_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);
}
給上位機發送資料
void Usart_SendByte(USART_TypeDef *TX_usart, uint8_t data)
{
USART_SendData(TX_usart,data);
//檢測串列埠傳送的資料
//若沒有資料來 就會一直等待
while(USART_GetFlagStatus(TX_usart,USART_FLAG_TXE) == RESET);
主程式測試
#include "stm32f10x.h"
#include "usart.h"
int main(void)
{
USART_Config();
Usart_SendByte(DEBUG_USARTx,100);
while(1)
{
}
}