一、串口基礎
1.常用的串口相關寄存器
- USART_SR狀態寄存器
- USART_DR數據寄存器
- USART_BRR波特率寄存器
2.串口操作相關庫函數(省略入口參數)
void USART_Init(); //串口初始化:波特率,數據字長,奇偶校驗,硬件流控以及收發使能
void USART_Cmd();//使能串口
void USART_ITConfig();//使能相關中斷
void USART_SendData();//發送數據到串口,
DR uint16_t USART_ReceiveData();//接受數據,從DR讀取接受到的數據
FlagStatus USART_GetFlagStatus();//獲取狀態標誌位
void USART_ClearFlag();//清除狀態標誌位
ITStatus USART_GetITStatus();//獲取中斷狀態標誌位
void USART_ClearITPendingBit();//清除中斷狀態標誌位
3.狀態寄存器
第10-31位保留,硬件強制爲0
第5位:RXNE(讀數據寄存器非空),當該位被置 1 的時候,就是提示已經有數據被接收到了,並且可以讀出來了。這時候我們要做的就是儘快去讀取 USART_DR,通過讀 USART_DR 可以將該位清零,也可以向該位寫 0,直接清除。
第6位:TC(發送完成),當該位被置位的時候,表示 USART_DR 內的數據已經被髮送完成了。如果設置了這個位的中斷,則會產生中斷。該位也有兩種清零方式:1)讀 USART_SR,寫USART_DR。2)直接向該位寫 0。
讀取串口狀態的函數是:FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG);
例如:
判斷讀寄存器是否非空(RXNE),操作庫函數的方法是:USART_GetFlagStatus(USART1, USART_FLAG_RXNE);
4.數據寄存器
5.串口配置的一般步驟
①串口時鐘使能:RCC_APBxPeriphClockCmd();
GPIO時鐘使能:RCC_AHB1PeriphClockCmd();
② 引腳複用映射: GPIO_PinAFConfig();
③GPIO端口模式設置:GPIO_Init(); 模式設置爲GPIO_Mode_AF
④串口參數初始化:USART_Init();
⑤開啓中斷並且初始化NVIC(如果需要開啓中斷才需要這個步驟) NVIC_Init(); USART_ITConfig();
⑥使能串口:USART_Cmd(); ⑦編寫中斷處理函數:USARTx_IRQHandler();
⑧串口數據收發:
void USART_SendData();//發送數據到串口,DR uint16_t USART_ReceiveData();//接受數據,從DR讀取接受到的數據
⑨串口傳輸狀態獲取: FlagStatus USART_GetFlagStatus(); void USART_ClearITPendingBit();
二、實例編寫
1.宏觀變量定義
#define USART_REC_LEN 200 //定義最大接收字節數 200
u8 USART_RX_BUF[USART_REC_LEN]; //接收緩衝,最大USART_REC_LEN個字節.末字節爲換行符
u16 USART_RX_STA; //接收狀態標記
在這裏定義了16位的USART_RX_STA,其中0-13位用於接收數據,第14位用於進行判斷0x0d標誌,若接收到了置1,反之置0,第15位用於判斷接收完成標誌,即第14位確定收到0x0d標誌後,再進行判斷,若收到了0x0a標誌,則將該位置爲1
2.main函數編寫
int main(void)
{
u8 t;
u8 len;
u16 times=0;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//將中斷優先級分組2,2位響應,2位搶斷
delay_init(168); //延時初始化
uart_init(115200); //波特率兩邊要一致,這裏設置爲115200,若不一致則會產生亂碼
LED_Init(); //初始化LED
while(1)
{
//STA爲16位,與0x8000與,即判斷接收到的數據第15位是否爲1,即是否接收到完成
if(USART_RX_STA&0x8000)
{
len=USART_RX_STA&0x3fff;//接收到的數據長度保存到len中
printf("\r\n您發送的消息爲:\r\n");
for(t=0;t<len;t++)
{
//將BUF中保存的數據發送到串口1
USART_SendData(USART1, USART_RX_BUF[t]);
//等待發送結束
while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);
}
printf("\r\n\r\n");
USART_RX_STA=0; //STA清0,以便於下次接收
}
else //沒有接收到完整結束標誌或只接收到一個,跳入else,循環打印提示信息
{
times++;
if(times%200==0)
printf("輸入數據,以回車鍵結束\r\n");
if(times%30==0)
LED0=!LED0;//LED閃爍,系統正在運行
delay_ms(10);
}
}
}
亂碼示例: