串口簡介
UART:全雙工、異步、串行通信方式
經常用來打印調試信息
物理層
串口物理層有很多標準及變種:TTL、RS232、RS422、RS485等;
RS232 標準
[圖片上傳失敗...(image-6e7169-1692068503959)]上圖中,設備A 與 設備B 的 DB9接口 通過串口線連接,串口信號線中使用 RS232電平標準 傳輸數據信號。由于 RS232電平標準不能直接被控制器識別,所以需要通過一個 “電平轉換芯片(如MA3232)” 來將 RS232電平 和 TTL電平進行轉換(發送數據時,將TTL電平轉換成RS232電平;接收數據時,將RS232電平轉換成TTL電平)。
TTL電平標準 VS RS232電平標準
邏輯0 | 邏輯1 | |
---|---|---|
TTL | 0 ~ 0.5V | 2.4V ~ 5V |
RS232 | +3V ~ +15V | -15V ~ -3V |
電子電路中常用的是 TTL標準,理想狀態下,用 0V 表示邏輯0,用 5V 表示邏輯1,而實際情況允許一定的誤差,采用的是一個范圍。
RS232標準,為了增加串口通訊傳輸距離和提高抗干擾能力,使用 -15V 表示邏輯1,+15V 表示邏輯0,下圖是表示同一信號的 TTL電平 和 RS232電平:
物理連接
DB9接口的信號線有9根,目前一般只使用 RXD、TXD、GND這3條信號線就可以了。
設備A 設備B TXD -- RXD RXD -- TXD GND -- GND VCC -- VCC
硬件電路
以 USART1 為例,使用 PA9 和 PA10 引腳(也可以使用其他引腳組合,詳見引腳復用)
編程指南
串口初始化指南
主要步驟如下:
1)GPIO 時鐘使能
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
2)USART1 時鐘使能
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
3)GPIO 復用模式初始化
使用 DEBUG_USART_RX_GPIO_PORT 和 DEBUG_USART_RX_PIN 是為了方便代碼移植和書寫,后續代碼都是類似風格,不再單獨說明。
#define DEBUG_USART_RX_GPIO_PORT GPIOA
#define DEBUG_USART_RX_PIN GPIO_Pin_10
#define DEBUG_USART_TX_GPIO_PORT GPIOA
#define DEBUG_USART_TX_PIN GPIO_Pin_9
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; // 復用模式
GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_PIN;
GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_PIN;
GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);
4)引腳復用配置
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);
5)UART 參數配置
主要設置如下參數:
波特率 115200
字長 8位
奇偶校驗 無校驗
不使用硬件流控
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = 115200;
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(USART1, &USART_InitStructure);
6)使能串口
USART_Cmd(USART1, ENABLE);
串口接收中斷配置
7)配置 NVIC 嵌套中斷向量控制器
中斷優先級分組設置,一般是在 main() 函數中設置,后續默認已經配置,不再單獨說明。
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC 參數配置
void uart1_nvic_config(void){ NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);}
8)串口接收中斷使能
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
串口收發數據接口
串口發送數據
如下是發送單個數據的接口,Data 最多是9位
// Transmits single data through the USARTx peripheral.
void USART_SendData(USART_TypeDef* USARTx, uint16_t Data)
{
USARTx->DR = (Data & (uint16_t)0x01FF);
}
串口接收數據
// Returns the most recent received data by the USARTx peripheral.
uint16_t USART_ReceiveData(USART_TypeDef* USARTx)
{
return (uint16_t)(USARTx->DR & (uint16_t)0x01FF);
}
重定向 printf() 和 scanf() 函數
int fputc(int ch, FILE *f)
{
USART_SendData(USART1, (uint8_t)ch);
/* 等待發送完畢 */
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
return (ch);
}
int fgetc(FILE *f)
{
/* 等待串口輸入數據 */
while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);
return (int)USART_ReceiveData(USART1);
}
主要代碼
#define DEBUG_USART_RX_GPIO_PORT GPIOA
#define DEBUG_USART_RX_PIN GPIO_Pin_10
#define DEBUG_USART_TX_GPIO_PORT GPIOA
#define DEBUG_USART_TX_PIN GPIO_Pin_9
void uart1_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; // 復用模式
GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_PIN;
GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_PIN;
GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);
// 引腳復用配置
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);
USART_InitStructure.USART_BaudRate = 115200;
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(USART1, &USART_InitStructure);
uart1_nvic_config();
USART_Cmd(USART1, ENABLE);
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
}
uint16_t uart1_send(USART_TypeDef* USARTx, char *data)
{
unsigned int k = 0;
do
{
USART_SendData(USARTx, *(data+ k));
while (USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET);
k++;
} while (*(data+ k) != ' 主站蜘蛛池模板: 察隅县| 睢宁县| 陈巴尔虎旗| 吉木乃县| 阳曲县| 都江堰市| 沙河市| 廉江市| 文化| 南丰县| 秭归县| 英吉沙县| 双牌县| 青川县| 巩义市| 布拖县| 吐鲁番市| 平果县| 岐山县| 新闻| 商都县| 东安县| 宁海县| 汶上县| 宁明县| 怀化市| 日喀则市| 哈巴河县| 临城县| 葵青区| 平舆县| 文昌市| 南漳县| 松溪县| 朝阳区| 牟定县| 顺昌县| 曲麻莱县| 泽库县| 太康县| 卢氏县|