—————目錄—————
一、通信的一些基本概念理解
二、串口通信協議簡介
三、功能框圖理解
四、stm32與上位機通信
五、DMA
————————————
對應課程
野火 第21節USART
https://i.youku.com/firege
一、通信的一些基本概念理解
1. 串行與並行通信
【1】並行通信定義:
在計算機和終端之間的數據傳輸通常是靠電纜或信道上的電流或電壓變化【脈衝信號】實現的。如果一組數據的各數據位在多條線上同時被傳輸,這種傳輸方式稱爲並行通信。
【2】串行更常見:
並行數據傳輸只適用於近距離的通信,通常傳輸距離小於30米。且串行簡單,傳輸只用一根線,更新迭代更快。
2. 全雙工、半雙工、單工
【1】區分:
全雙工:可以同時互傳
半雙工:可以分時互傳
單工:單向傳輸
【2】半雙工用的最多
3. 同步與異步
【1】區分:
同步:同步雙方的時鐘誤差需較小。傳輸數據大多數爲有效數據
異步:在有效數據中插入各種標識符,暗示開始、結束、校驗。
4. 通信的速率【比特率與波特率】
【1】區分
比特率:每秒鐘傳輸的二進制位數,單位爲比特每秒(bit/s)
波特率:沒秒鐘傳輸的碼元個數
碼元:碼元是在信道中最小的一個脈衝單位。
【2】碼元
二進制碼元:0、1
四進制碼元:00、01、10、11
八進制碼元:000、001、010、011、100、101、110、111
【3】聯繫
當且僅當碼元爲二進制碼元時,波特率和比特率等價。
二、串口通信協議簡介
1. 物理層【硬件層】
TTL電平:從單片機、芯片出來的電平都叫TTL電平。其中STM32的高電平爲3.3V,51單片機的高電平爲5V。
USB內部構造圖,兩邊的是USB電平,中間是數據
2.協議層【軟件層】
【1】數據包的組成如圖三
【2】校驗方式
、奇校驗:1的和爲奇數
、偶校驗:1的和爲偶數
、0校驗:校驗位恆爲0
、1校驗:校驗位恆爲1
三、功能框圖理解
1.串口的引腳
接口通過三個引腳與其他設備連接在一起.任何USART雙向通信至少需要兩個引腳,RX、TX
【1】USART和UART相差了個S,S 叫做 synchronous(同步)
——USART : 通用同步/異步串行接收/發送器
(Universal Synchronous/Asynchronous Receiver/Transmitter)
——UART : 通用異步收發傳輸器(Universal Asynchronous Receiver/Transmitter)
【2】重點:會找引腳
2.波特率
【1】基本概念:表示每秒鐘發送的碼元個數;在串口裏面,波特率剛好等於比特率。
【2】算波特率:
(1)涉及到寄存器USART_BRR(波特率寄存器)
(2)串口1是在APB2總線上,其他串口是在APB1總線上,在寫程序的時候注意要切換時鐘
3.寄存器簡介
【1】狀態寄存器 SR(Status register)
【2】數據寄存器 DR (Data Register)
【3】波特率寄存器 BRR ()
【4】控制寄存器1 CR1(Control Register)
【5】控制寄存器2 CR2
【6】控制寄存器3 CR3
【7】保護時間和預分頻寄存器 GTPR
4.數據的發送、數據接收的流程
【1】初始化
串口初始化
在項目開發過程中,異步串口使用比較多。串口的每個數據幀格式如下:
字長通常爲8個數據位
停止位通常爲1個停止位
步驟:打開校驗使能 ->選擇校驗方式 ->校驗出錯中斷使能
當PE == 1 時,奇偶校驗產生錯誤
同步時鐘:同步時鐘初始化
【2】數據發送、接收過程
(1) 發送 總體共二步:
第一步:把UE = 1,TE = 1 、RE = 1 .<USART使能,發送使能,接收使能>
第二步:TXE = 1 , TC = 1 <發送寄存器爲爲空,發送完成>
附:
a. TXE: TX empty;TC: transmission complete
b.發送一個字節可以只判斷TXE,發送多個字節必須判斷TC
c. TXE = 1 : 發送數據寄存器的數據全部發送到發送移位寄存器中了.
d. TC = 1 : 發送移位寄存器爲空,數據全部發送到TX處,發送完成。
e. 他們相應的中斷位分別爲TXEIE、TCIE
(2)接收 總體二步
第一步:UE = 1; TE = 1 ;RE = 1;
第二步:RXNE = 1;<接收數據寄存器爲空,接收完畢>
附:
a. RXNE 即爲 RX not empty.
b. 接收 只能判斷一個,RXNE.
c.對應中斷 RXNEIE
四、stm32與上位機通信
1、printf函數可以發給上位機,這需要fputc函數、fgetc函數來幫忙,放到usart.c裏面
///重定向c庫函數printf到串口,重定向後可使用printf函數
int fputc(int ch, FILE *f)
{
/* 發送一個字節數據到串口 */
USART_SendData(DEBUG_USARTx, (uint8_t) ch);
/* 等待發送完畢 */
while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET);
return (ch);
}
///重定向c庫函數scanf到串口,重寫向後可使用scanf、getchar等函數
int fgetc(FILE *f)
{
/* 等待串口輸入數據 */
while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_RXNE) == RESET);
return (int)USART_ReceiveData(DEBUG_USARTx);
}
- 串口1~5 分別定義五種宏定義
/**
* 串口宏定義,不同的串口掛載的總線和IO不一樣,移植時需要修改這幾個宏
*/
#define DEBUG_USART1 0
#define DEBUG_USART2 0
#define DEBUG_USART3 0
#define DEBUG_USART4 0
#define DEBUG_USART5 1
#if DEBUG_USART1
// 串口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
#elif DEBUG_USART2
// 串口2-USART2
#define DEBUG_USARTx USART2
#define DEBUG_USART_CLK RCC_APB1Periph_USART2
#define DEBUG_USART_APBxClkCmd RCC_APB1PeriphClockCmd
#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_2
#define DEBUG_USART_RX_GPIO_PORT GPIOA
#define DEBUG_USART_RX_GPIO_PIN GPIO_Pin_3
#define DEBUG_USART_IRQ USART2_IRQn
#define DEBUG_USART_IRQHandler USART2_IRQHandler
#elif DEBUG_USART3
//// 串口3-USART3
#define DEBUG_USARTx USART3
#define DEBUG_USART_CLK RCC_APB1Periph_USART3
#define DEBUG_USART_APBxClkCmd RCC_APB1PeriphClockCmd
#define DEBUG_USART_BAUDRATE 115200
// USART GPIO 引腳宏定義
#define DEBUG_USART_GPIO_CLK (RCC_APB2Periph_GPIOB)
#define DEBUG_USART_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd
#define DEBUG_USART_TX_GPIO_PORT GPIOB
#define DEBUG_USART_TX_GPIO_PIN GPIO_Pin_10
#define DEBUG_USART_RX_GPIO_PORT GPIOB
#define DEBUG_USART_RX_GPIO_PIN GPIO_Pin_11
#define DEBUG_USART_IRQ USART3_IRQn
#define DEBUG_USART_IRQHandler USART3_IRQHandler
#elif DEBUG_USART4
// 串口4-UART4
#define DEBUG_USARTx UART4
#define DEBUG_USART_CLK RCC_APB1Periph_UART4
#define DEBUG_USART_APBxClkCmd RCC_APB1PeriphClockCmd
#define DEBUG_USART_BAUDRATE 115200
// USART GPIO 引腳宏定義
#define DEBUG_USART_GPIO_CLK (RCC_APB2Periph_GPIOC)
#define DEBUG_USART_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd
#define DEBUG_USART_TX_GPIO_PORT GPIOC
#define DEBUG_USART_TX_GPIO_PIN GPIO_Pin_10
#define DEBUG_USART_RX_GPIO_PORT GPIOC
#define DEBUG_USART_RX_GPIO_PIN GPIO_Pin_11
#define DEBUG_USART_IRQ UART4_IRQn
#define DEBUG_USART_IRQHandler UART4_IRQHandler
#elif DEBUG_USART5
// 串口5-UART5
#define DEBUG_USARTx UART5
#define DEBUG_USART_CLK RCC_APB1Periph_UART5
#define DEBUG_USART_APBxClkCmd RCC_APB1PeriphClockCmd
#define DEBUG_USART_BAUDRATE 115200
// USART GPIO 引腳宏定義
#define DEBUG_USART_GPIO_CLK (RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD)
#define DEBUG_USART_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd
#define DEBUG_USART_TX_GPIO_PORT GPIOC
#define DEBUG_USART_TX_GPIO_PIN GPIO_Pin_12
#define DEBUG_USART_RX_GPIO_PORT GPIOD
#define DEBUG_USART_RX_GPIO_PIN GPIO_Pin_2
#define DEBUG_USART_IRQ UART5_IRQn
#define DEBUG_USART_IRQHandler UART5_IRQHandler
#endif
五、DMA
1、DMA有三種方式 M-M, P-M, M-P
M-M任何通道都可以用, P-M, M-P需要遵循下表
2.仲裁
軟件仲裁 :CCR寄存器
硬件仲裁 :
通道1 > 通道2 > 通道3 > 通道4 > 通道5 > 通道6 > 通道7
DMA1 > DMA2
3.結構體
typedef struct
{
uint32_t DMA_PeripheralBaseAddr; /*!< Specifies the peripheral base address for DMAy Channelx. */
uint32_t DMA_MemoryBaseAddr; /*!< Specifies the memory base address for DMAy Channelx. */
uint32_t DMA_DIR; /*!< Specifies if the peripheral is the source or destination.
This parameter can be a value of @ref DMA_data_transfer_direction */
uint32_t DMA_BufferSize; /*!< Specifies the buffer size, in data unit, of the specified Channel.
The data unit is equal to the configuration set in DMA_PeripheralDataSize
or DMA_MemoryDataSize members depending in the transfer direction. */
uint32_t DMA_PeripheralInc; /*!< Specifies whether the Peripheral address register is incremented or not.
This parameter can be a value of @ref DMA_peripheral_incremented_mode */
uint32_t DMA_MemoryInc; /*!< Specifies whether the memory address register is incremented or not.
This parameter can be a value of @ref DMA_memory_incremented_mode */
uint32_t DMA_PeripheralDataSize; /*!< Specifies the Peripheral data width.
This parameter can be a value of @ref DMA_peripheral_data_size */
uint32_t DMA_MemoryDataSize; /*!< Specifies the Memory data width.
This parameter can be a value of @ref DMA_memory_data_size */
uint32_t DMA_Mode; /*!< Specifies the operation mode of the DMAy Channelx.
This parameter can be a value of @ref DMA_circular_normal_mode.
@note: The circular buffer mode cannot be used if the memory-to-memory
data transfer is configured on the selected Channel */
uint32_t DMA_Priority; /*!< Specifies the software priority for the DMAy Channelx.
This parameter can be a value of @ref DMA_priority_level */
uint32_t DMA_M2M; /*!< Specifies if the DMAy Channelx will be used in memory-to-memory transfer.
This parameter can be a value of @ref DMA_memory_to_memory */
}DMA_InitTypeDef;
4. M -> P 編程要點
初始化串口
配置DMA初始化結構體
編寫主函數(開啓串口發送DMA請求)
/* 初始化USART */
USART_Config();
/* 配置使用DMA模式 */
USARTx_DMA_Config();
/* USART1 向 DMA發出TX請求 */
USART_DMACmd(DEBUG_USARTx, USART_DMAReq_Tx, ENABLE);