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