ashwatermelon

ashwatermelon

【學習筆記】stm32單片機USART串口

最近學了 stm32 的串口通信。
串口在之前學 51 的時候用過,不過差不多忘乾淨了(悲)
那麼開始複習串口通信。

(一)什麼是 USART#

串口是一種應用十分廣泛的通訊接口,串口成本低、容易使用、通信線路簡單,可實現兩個設備的互相通信。
單片機的串口可以使單片機與單片機、單片機與電腦、單片機與各式各樣的模塊互相通信,極大地擴展了單片機的應用範圍,增強了單片機系統的硬體實力。
其通信方式為異步全雙工,異步是指通信雙方間沒有時鐘線相連,需要預先設置好波特率(傳輸頻率);全雙工是指通信雙方都可以發送和接收信號,互不干擾。
USART 串口通信有兩條線,一條是 TXD,用於發送信號;一條是 RXD,用於接收信號。雙方的 TXD 與對方的 RXD 交叉相連。(圖片莫名奇妙傳不上來,算了)
USART 發送的一個完整的信息包括:起始位、數據位、校驗位、停止位,其中,數據位跟校驗位總共有 8 或者 9 位位,校驗位只有一位,我們可以通過改變停止位的長度來改變發送頻率,不過一般選擇 8 位無校驗,或者 9 位校驗,停止位長度 1 位就可以了。

(二)代碼配置#

stm32 的庫函數中有專門的 USART 函數,所以配置過程可比 51 的簡單多了。
代碼如下:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);

GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOA,&GPIO_InitStructure); GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10; GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOA,&GPIO_InitStructure);

USART_InitTypeDef USART_InitStructure; USART_InitStructure.USART_BaudRate=9600; USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode=USART_Mode_Tx|USART_Mode_Rx;
USART_InitStructure.USART_Parity=USART_Parity_No;
USART_InitStructure.USART_StopBits=USART_StopBits_1;
USART_InitStructure.USART_WordLength=USART_WordLength_8b; USART_Init(USART1,&USART_InitStructure);

USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel=USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0; NVIC_Init(&NVIC_InitStructure);

USART_Cmd(USART1,ENABLE);
我們只要開啟時鐘初始化引腳後用 USART_Init 初始化 USART(波特率 9600,8 位不校驗),然後再用 USART_ITConfig 開啟中斷,最後配置 NVIC 並啟動串口就可以了。

(三)發送與接收信號#

發送信號很簡單我們只要用 USART_SendData 函數就可以了:
void Serial_SendByte(uint8_t Data)
{
USART_SendData(USART1,Data);
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
}

而在這個的基礎上,我們還可以封裝出發送字符串、發送數字的函數,比如下面這個發送字符串的函數:
void Serial_SendString(uint8_t*Data)
{
int j = 0;
for(j=0;Data[j]!='\0';j++)
{
Serial_SendByte(Data[j]);
}
}

而接收數據則需要用中斷,代碼如下:
void USART1_IRQHandler()
{
while(USART_GetITStatus(USART1,USART_IT_RXNE)==RESET);
SerialRXFlag=1;
SerialRXData=USART_ReceiveData(USART1);
}

(四)串口收發數據包#

其實就是讓串口收發某種特定格式的內容,比如數據包包頭為 0xFF,包尾為 0xFE,代碼大致如下:
void Serial_Sendpacket()
{
Serial_SendByte(0xFF);
Serial_SendArray(SerialTXPacket,4);
Serial_SendByte(0xFE);
}

void USART1_IRQHandler()
{
static int pRXPacket = 0;
static uint8_t RxState = 0;
while(USART_GetITStatus(USART1,USART_IT_RXNE)==RESET);
uint8_t RXData = 0;
RXData = USART_ReceiveData(USART1);
switch (RxState)
{
case 0:
if (RXData == 0xFF)
{
RxState = 1;
pRXPacket = 0;
}
break;
case 1:
SerialRXPacket[pRXPacket] = RXData;
pRXPacket++;
if (pRXPacket >= 4)
{
RxState = 2;
}
break;
case 2:
if (RXData == 0xFE)
{
RxState = 0;
SerialRXFlag=1;
}
break;
}
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
}

USART 的內容大概就這麼多,說不上多複雜,因為函數庫已經把我們本來需要配置的一堆東西都做了。

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。