Linux下串列埠
1.串列埠通訊
-
DB9串列埠頭型
母頭
公頭
-
DB9 9針腳的功能:
資料:
GND(pin 5):地線
TXD(pin 3):串列埠資料輸出(Transmit Data)
RXD(pin 2):串列埠資料輸入(Receive Data)
握手:
RTS(pin 7):傳送資料請求(Request to Send)
CTS(pin 8):清除傳送(Clear to Send)
DSR(pin 6):資料傳送就緒(Data Send Ready)
DCD(pin 1):資料載波檢測(Data Carrier Detect)
DTR(pin 4):資料終端就緒(Data Terminal Ready)
其它
RI(pin 9):鈴聲指示
1)資料通訊最少需要3根線: TXD RXD GND
2)三線通訊:
(3匯流排空閒,一般是高電平; 起始位,低電平,一個位寬;
(4)接收方探測: 預設匯流排 空閒時是高電平,一旦來一個位的 低電平,說明一幀資料開始了。緊接著就是資料位,一幀資料
有多少個數據位,由通訊雙方定義。資料位: 5, 6,7, 8,一
般是8個位;
(5)資料位發完了,一般會跟奇偶校驗位(奇校驗、偶校驗、無校 驗),驗證收發雙方的資料是否正常
奇校驗: 資料位加上校驗位保證1的個數為奇數;
偶校驗: 資料位加上校驗位保證1的個數為偶數;
資料發完之後,會發一個停止位,停止位的寬度一般是:1, 1.5,2
3)TTL電平與RS232電平的區別
<1>TTL電平標準:
輸出 L: <0.8V ; H:>2.4V。
輸入 L: <1.2V ; H:>2.0V
TTL器件輸出低電平要小於0.8V,高電平要大於2.4V。輸入,低於
1.2V就認為是0,高於2.0就認為是1。
<2>RS232標準
邏輯1的電平為-3~-15V,邏輯0的電平為+3~+15V,注意電平
的定義反相了一次。
2.Linux串列埠程式設計
1)TTY裝置:
TTY裝置包括虛擬控制檯,串列埠以及偽終端裝置。
比如說3G/4G/5G其實最終是 USB介面轉成串列埠(/dey/ttyUSB*)
GPS GPRS/3G/4G/5G/串列埠藍芽/串列埠wife/Lora模組 AT命令
bootargs:console=/dev/ttyS0,115200
stdin、stdout、stderr串列埠1,Linux核心的列印資訊console
2)串列埠程式設計
開啟串列埠
int fd;
fd = open("/dev/ttyS0", O_RDWR);
if(fd == -1)
{
Perror("串列埠開啟失敗");
}
除了使用O_RDWR標誌之外,通常還會使用O_NOCTTY和O_NDELAY這兩個標誌
O_NOCTTY:告訴UNIX這個程式不想成為”控制終端“控制的程式,如果不說明這個標誌,任何輸入都會影響你的程式
O_NDELAY:告訴UNIX這個程式不關心DCD訊號線狀態,即其他埠是否執行,不說明這個標誌,程式下DCD訊號線為低電平時停止
3)串列埠的最基本設定:<1>波特率、<2>校驗位、停止位、資料位
主要使用termios.h標頭檔案中定義的termios結構,如:
struct termios
{
tcflag_t c_iflag; //輸入模式標誌
tcflag_t c_oflag; //輸出模式標誌
tcflag_t c_cflag; //控制模式標誌
tcflag_t c_lflag; //本地模式標誌
cc_t c_line; //line discipline
cc_t c_cc[NCC]; //control characters
}
位操作
struct xxx
{
unsigned char flag; //unsigned char佔兩個位元組,8位
} st;
這樣可以來操做8個LED燈
bit[0] LED1: 1, ON 0: off
bit[1] LED2: 1, ON 0: off
bit[2] LED3: 1, ON 0: off
.
.
.
bit[7] LED3: 1, ON 0: off
flag:bit[7:0] xxxx xxxx
0000 0001
--------------
0000 000x
然後可以這寫程式碼來控制這個:
if(st.flag & (1<<0))
turn_led1(ON);
else
turn_led1(OFF);
如果判斷第三位:
if(st.flag & (1<<3)) //將1左移三位
turn_led1(ON);
else
turn_led1(OFF);
如果我想知道flag:bit[7:5]的相應的值:
xxxyyyx xxxx
首先先丟掉低位
(std.falg>>5)&7 = (std.falg>>5)&(2<<3-1)
用來設定上面的結構體
<1>波特率
int speed_arr[] = { B38400, B19200, B9600, B4800, B2400, B1200, B300, B38400, B19200, B9600, B4800, B2400, B1200, B300, };
int name_arr[] = {38400, 19200, 9600, 4800, 2400, 1200, 300, 38400, 19200, 9600, 4800, 2400, 1200, 300, };
void SetSpeed(int fd, int speed)
{
int i;
struct termios Opt; //定義termios結構
if(tcgetattr(fd, &Opt) != 0)
{
perror(“tcgetattr fd”);
return;
}
for(i = 0; i < sizeof(speed_arr) / sizeof(int); i++)
{
if(speed == name_arr[i])
{
tcflush(fd, TCIOFLUSH);
cfsetispeed(&Opt, speed_arr[i]);
cfsetospeed(&Opt, speed_arr[i]);
if(tcsetattr(fd, TCSANOW, &Opt) != 0)
{
perror(“tcsetattr fd”);
return;
}
tcflush(fd, TCIOFLUSH);
}
}
}
<2>校驗位、停止位、資料位
以下是幾個資料位、停止位和校驗位的設定方法:(以下均為1位停止位)
8位資料位、無校驗位:
Opt.c_cflag &= ~PARENB;
Opt.c_cflag &= ~CSTOPB;
Opt.c_cflag &= ~CSIZE;
Opt.c_cflag |= CS8;
7位資料位、奇校驗:
Opt.c_cflag |= PARENB;
Opt.c_cflag |= PARODD;
Opt.c_cflag &= ~CSTOPB;
Opt.c_cflag &= ~CSIZE;
Opt.c_cflag |= CS7;
7位資料位、偶校驗:
Opt.c_cflag |= PARENB;
Opt.c_cflag &= ~PARODD;
Opt.c_cflag &= ~CSTOPB;
Opt.c_cflag &= ~CSIZE;
Opt.c_cflag |= CS7;
7位資料位、Space校驗:
Opt.c_cflag &= ~PARENB;
Opt.c_cflag &= ~CSTOPB;
Opt.c_cflag &= ~CSIZE;
Opt.c_cflag |= CS7;
3.Linux核心串列埠具體工作
4.socket通訊
1. 網路的7層協議 五層協議(書面) TCP/IP四層協議棧
這裡以實際的四層協議來分析
2.遊覽器訪問www.baidu.com過程
1>由應用程式實現
遊覽器會封裝一個http的報文請求,然後把這個報文傳送給百度的伺服器
2>由作業系統實現
PC會訪問DNS伺服器(114.114.114.114),查詢baidun.com的IP地址123.125.115.110
因為是www協議,那就訪問123.125.115.110的80埠
獲取自己的IP地址,核心給應用程式動態分配一個未用的埠
網路通訊的四要素:源IP、源埠、目的IP、目的埠
6擴充套件
1.將IP地址做域名解析
比如:要訪問192.168.1.X時,我們可以直接通過訪問studio.xxx.com來實
現連線訪問
2.如果客戶端如何判斷伺服器斷開了這個連結
3.如何解決connect()、read()阻塞的問題