一文看懂串口協(xié)議
前言
好久沒更新文章了,這篇文章寫寫停停,用了近一周的時間,終于寫完了,謝謝大家的關(guān)注。本篇文章介紹,串口協(xié)議數(shù)據(jù)幀格式、串行通信的工作方式、電平標(biāo)準(zhǔn)、編碼方式及Verilog實現(xiàn)串口發(fā)送一個字節(jié)數(shù)據(jù)和接收一個字節(jié)數(shù)據(jù)。對于MCU串口的發(fā)送接收,可能就是1行代碼就能實現(xiàn)串口的發(fā)送和接收:
STM32的串口接收和發(fā)送
//STM32發(fā)送1個字節(jié)
USART_SendData(USART1, 'A');
while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET);
//STM32接收1個字節(jié):
uint8_t Res;
while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);
Res = USART_ReceiveData(USART1);
51單片機(jī)的發(fā)送和接收
//51單片機(jī)發(fā)送1個字節(jié)
SBUF = 'A;
while(!TI);
TI=0;
//51單片機(jī)接收1個字節(jié):
char Res;
if(RI)
{
Res = SBUF;
RI = 0;
}
STM32實現(xiàn)輸入輸出重定向到串口發(fā)送接收
//可重定向printf函數(shù)
int fputc(int ch, FILE *f)
{
USART_SendData(DEBUG_USARTx, (uint8_t) ch);
while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET);
return (ch);
}
//可重定向scanf函數(shù)
int fgetc(FILE *f)
{
while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_RXNE) == RESET);
return (int)USART_ReceiveData(DEBUG_USARTx);
}
串口數(shù)據(jù)幀格式
波特率
波特率,即比特率(Baud rate),即通信雙方“溝通的語言”,通信雙方要設(shè)置為一樣的波特率才可以正常通信。表示每秒發(fā)送的二進(jìn)制位數(shù),即傳輸1位的時間是:1/波特率 秒,如,波特率9600bps,即每秒傳輸9600bit,那么每一位的時間為:1/9600 s = 104.1666us,常用的波特率有:4800/9600/115200/12800等等,也可以根據(jù)需要自定義波特率大小,如1M或者3M,但是有的PC或者USB-TTL模塊不支持太高速度的波特率,常用的USB-TTL芯片有:CH340,CP2102,PL2103,F(xiàn)T232等,其中FT232HL芯片最大支持12M的波特率,當(dāng)然價格也比其他芯片高一些。起始位和停止位
數(shù)據(jù)幀從起始位開始,到停止位結(jié)束。起始信號用邏輯0表示,而停止位是用邏輯1表示,一般有0.5位、1位、1.5位或2位停止位,常用的一般是1位停止位,只要通信雙方約定一致即可。數(shù)據(jù)位
起始位之后,緊跟著的是數(shù)據(jù)位,低位(LSB)在前,高位(MSB)在后,一般有5位、6位、7位和8位數(shù)據(jù)位,常用的是8位數(shù)據(jù)位,因為一個字節(jié)正好是8位。校驗位
校驗位一般用來判斷接收的數(shù)據(jù)位有無錯誤,校驗方法有:奇校驗(odd)、偶校驗(even)、0校驗(space)、1校驗(mark)及無校驗(noparity)。奇校驗要求有效數(shù)據(jù)和校驗位中“1”的個數(shù)為奇數(shù),比如一個8位長的有效數(shù)據(jù)為:01101001,此時共有4個“1”,為達(dá)到奇數(shù)個"1"的效果,校驗位為“1”,讓“1”的個數(shù)變成5個(奇數(shù))。偶校驗剛好相反,要求有效數(shù)據(jù)和校驗位的“1”數(shù)量為偶數(shù),則此時為達(dá)到偶校驗效果,校驗位為“0”。而0校驗,即校驗位總是為“0”,1校驗校驗位總是為“1”。奇偶校驗邏輯相反,01校驗邏輯相反。一般是奇偶校驗或者是無校驗位。奇偶校驗的Verilog實現(xiàn)
在Verilog中奇偶校驗的計算非常簡單,根據(jù)奇偶校驗的原理,偶校驗為數(shù)據(jù)位各位異或,奇校驗是偶校驗取反,通過使用單目運算符的縮減功能,可以非常簡單的計算奇偶校驗位:input [7:0] data_in, //需要發(fā)送的8位數(shù)據(jù)
wire even_bit; //偶校驗位 = 各位異或
wire odd_bit; //奇校驗位 = ~偶校驗位
assign even_bit = ^data_in; //一元約簡運算符,等效于data_in[0] ^ data_in[1] ^ .....
assign odd_bit = ~even_bit;
wire POLARITY_BIT = even_bit; //偶校驗
關(guān)于波特率允許的誤差
經(jīng)過我的實際測試,波特率是有一定的容錯范圍的,例如,STM32配置成115200波特率,每10ms發(fā)送一個30字節(jié)的字符串,串口芯片用的CH340,上位機(jī)波特率設(shè)置成113000-121000也可以接收,無亂碼,差不多正負(fù)2000的波特率,這容錯范圍也太大了,當(dāng)然如果發(fā)送頻率太快,數(shù)據(jù)量太大,誤碼率肯定會大大增加,所以還是建議通信雙方使用同樣的波特率以減少誤差。串口數(shù)據(jù)的實際波形
使用串口上位機(jī)連接USB-TTL模塊,發(fā)送一個字節(jié)數(shù)據(jù):1位停止位 8位數(shù)據(jù)位 1位奇校驗位 1位停止位,使用示波器的單次觸發(fā)功能,可以在USB-TTL模塊的TX引腳測得串口協(xié)議數(shù)據(jù)的實際波形,你知道這發(fā)送的是什么字符嗎?一個字符的實際波形兩個字符的實際波形單工、半雙工、全雙工、異步和同步的區(qū)別
在介紹串口的電平標(biāo)準(zhǔn)之前,先來了解一下串行通信的工作方式,即單工、半雙工、全雙工,異步和同步的區(qū)別。單工
單工,即數(shù)據(jù)傳輸只在一個方向上傳輸,只能你給我發(fā)送或者我給你發(fā)送,方向是固定的,不能實現(xiàn)雙向通信,如:室外天線電視、調(diào)頻廣播等。半雙工
半雙工比單工先進(jìn)一點,傳輸方向可以切換,允許數(shù)據(jù)在兩個方向上傳輸,但是某個時刻,只允許數(shù)據(jù)在一個方向上傳輸,可以基本雙向通信,如:對講機(jī),IIC通信。全雙工
比半雙工更先進(jìn)的是全雙工,允許數(shù)據(jù)同時在兩個方向傳輸。發(fā)送和接收完全獨立,在發(fā)送的同時可以接收信號,或者在接收的同時可以發(fā)送。它要求發(fā)送和接收設(shè)備都要有獨立的發(fā)送和接收能力,如:電話通信,SPI通信,串口通信。同步和異步的區(qū)別
串行通信可以分為兩種類型,一種叫同步通信,另一種叫異步通信。簡單的說,就是同步通信需要時鐘信號,而異步通信不需要時鐘信號。- 同步:發(fā)送方發(fā)出數(shù)據(jù)后,等接收方發(fā)回響應(yīng)以后才發(fā)下一個數(shù)據(jù)包的通訊方式。
- 異步:發(fā)送方發(fā)出數(shù)據(jù)后,不等接收方發(fā)回響應(yīng),接著發(fā)送下個數(shù)據(jù)包的通訊方式。