1. 程式人生 > 實用技巧 >串列埠通訊基本實現

串列埠通訊基本實現

串列埠功能講解

串列埠框圖

對應的板載引腳,我的是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;

程式碼實現

功能實現:中斷接收與傳送 串列埠控制RGB燈亮滅

巨集定義需要的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)
	{
	}
}