(五)、串口
????? 1、串口通信簡介
???? ??制定通信的規則,通信雙方按照協議規則進行數據收發,將一個設備的數據傳送到另一個設備,擴展硬件系統,串口USART有兩根通信線Tx、Rx,可同時雙向通信,稱之為全雙工,像I2C只有一根數據線只能收或者發,之為半雙工。
? ? ? ?同步即有一根時鐘線,如SCL、SCLK時鐘線,據時鐘線指引采樣數據;異步無時鐘線,需要雙方約定采集頻率,按照約定收發數據。在藍橋杯中就需要約定運行頻率、波特率等。
? ? ? ?單端就是引腳的電平為對地的電壓差,必須共地,差分就是根據兩個線的電壓差來傳輸數據。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?圖 九 串口簡介
?
?????? 2、串口通信結構圖
??????? 藍橋杯中可以理解設備一為電腦、設備二為單片機,Tx、Rx必須交錯連接,主機設備給串口進行供電。我們一般選用串口一以定時器二為發生器,波特率就是傳輸速度一般選用9600,在STC_ISP中串口波特率計算器中按如圖所示配置(圖 十一)生成代碼,生成后要打開總中斷與串口使能(EA = 1; ES = 1)。這樣我們就約定好了采集頻率,可以進行下一步收發。
?
? ? ? ? ? ? ? ? ? ? ? ? 圖 十 串口通信結構圖
? ? ? ? ? ? ? ? ? ? ? ? 圖 十一 串口配置
?? ????3、發送代碼展示
????? ??第一個USART1_Init就是 軟件生成的,自行添加EA = 1;ES =1,下面一個函數簡單來講就是把串口一發送映射到printf上,通過printf來發送,而printf是可以發送字符串的,借助putchar自動一個個發送,所以此時我們完善putchar函數,將發送數據ch放在SBUF中,通過檢測TI發送標志位,發送完成會變成1,所以此時通過while循環等待發送完成,在軟件中手動置0。該函數可以外部調用,但需聲明stdio.h頭文件。
??????? 通過調用printf即可完成發送,如printf(“hsj”);即可向電腦發送hsj字符串數據。在stc-isp中借助USB-CDC/串口助手可驗證。配置9600波特率、無校驗,一位停止位,選擇正確串口com再打開串口即可。
? ? ? ? ? ? ? ? ? ? 圖 十二 串口發送代碼展示
?
????? 4、接收代碼展示
???? 接收電腦傳輸數據時,可能在任何時刻,接收不及時則會導致數據流失,則我們要借助中斷暫時跳出主程序,先接收完數據再回到主程序,來完成發送功能。
? ? ?中斷標志位為4,RI為接收標志位,一旦有數據需要接收,立馬變成1。拉高Uart_Recieve_Flag標志位開始計時,在定時器一的中斷中if(Uart_Recieve_Flag==1) Uart_Recieve_Trick++;將數據儲存到數組中,并手動拉低標志位(RI = 0),如果數據過多我們就通過string.h中庫函數memset清空數組。
? ? 在Uart_Proc中檢測Uart_Recieve_Index,為0證明無數據直接跳出函數,有數據時判斷Uart_Recieve_Trick計時變量,超過10ms表示接收完成停止計時(Uart_Recieve_Flag = 0),開始解析代碼,判斷接收的數據,完成后通過memset再清空數組。
? ? ? ? ? ? ? ? ? ? ? 圖 十三 接收代碼展示1
? ? ? ? ? ? ? ? ? ? ?圖 十四 接收代碼展示2
?
????? ??5、總結
????? 第一步借助軟件配置波特率發生器
?????? 接下來完善putchar函數,借助printf發送
?????? 完成中斷處理函數
?????? 完成主程序超時解析部分
?
提供參考代碼,希望對讀者有幫助
1、串口底層代碼
#include <STC15F2K60S2.H>
#include <stdio.h>void Uart1_Init(void) //9600bps@12.000MHz
{SCON = 0x50; //8位數據,可變波特率AUXR |= 0x01; //串口1選擇定時器2為波特率發生器AUXR |= 0x04; //定時器時鐘1T模式T2L = 0xC7; //設置定時初始值T2H = 0xFE; //設置定時初始值AUXR |= 0x10; //定時器2開始計時EA = 1; //打開總中斷ES = 1; //打開串口使能
}extern char putchar (char ch) //將串口1映射到printf上自動發送字符串
{SBUF = ch;while(TI == 0); //等待發送TI = 0; //發送完成并清空標志位return ch;
}
2、處理數據函數
idata unsigned char Uart_Send[15]; //發送數據數組
idata unsigned char Uart_Recieve[10]; //接收數據數組
idata unsigned char Uart_Recieve_Index; //接收數組指針
idata unsigned char Uart_Recieve_Flag; //接收標志位,1表示已接收
idata unsigned char Uart_Recieve_Trick; //計時變量,用于超時解析void Uart_Proc()
{if(Uart_Recieve_Index == 0) return; //無數據則返回if(Uart_Recieve_Trick >=10) //超時解析{Uart_Recieve_Flag = 0; //停止計時Uart_Recieve_Trick = 0;//解析接收內容//解析接收內容memset(Uart_Recieve,0,10); //清空數組Uart_Recieve_Index = 0;}
}//補充在定時器中需寫
//if(Uart_Recieve_Flag == 1) Uart_Recieve_Trick++;
3、中斷函數
void Uart_Routine() interrupt 4
{if(RI == 1) //有數據{Uart_Recieve_Flag = 1; //開始計時Uart_Recieve_Trick = 0;Uart_Recieve[Uart_Recieve_Index] = SBUF; //儲存數據Uart_Recieve_Index++;RI = 0; //復位標志位if(Uart_Recieve_Index>10) //超載則清空數組{memset(Uart_Recieve,0,10);Uart_Recieve_Index = 0;}}}
?
?
?