關於嵌入式學習隨筆->8《UART串行通信原理》
1、什麽是串口
串口是MCU(Microcontroller Unit;微控制單元)重要的外部接口,同時也是軟件開發重要的調試手段,現如今基本上所有的MCU都會帶有串口。以STM32F767為例,它的串口資源相當豐富,功能也十分強大,STM32F767IGT6最多可以提供8路串口,支持8/16倍過采樣、支持自動波特率檢測、支持Modbus通信、支持同步單線通信和半雙工單線通信、支持LIN、支持調制解調器操作、智能卡協議和IrDA SIR ENDEC規範、具有DMA等。
處理器與外部設備通信的兩種方式:
--》並行通信
-傳輸原理:數據各個位同時傳輸。
-優點:速度快
-缺點:占用引腳資源多
--》串行通信
-傳輸原理:數據按位順序傳輸。
-優點:占用引腳資源少
-缺點:速度相對較慢
2、串行通信
按照數據傳送方向,分為:
--》單工:數據傳輸只支持數據在一個方向上傳輸
--》半雙工:允許數據在兩個方向上傳輸,但是,在某一時刻,只允許數據在一個方向上傳輸,它實際上是一種切換方向的單工通信;
--》全雙工:允許數據同時在兩個方向上傳輸,因此,全雙工通信是兩個單工通信方式的結合,它要求發送設備和接收設備都有獨立的接收和發送能力。
串行通信的通信方式:
--》同步通信:帶時鐘同步信號傳輸(SPI,IIC通信 )
--》異步通信:不帶時鐘同步信號(UART串口通信(通用異步收發器),單總線通信)
常見的串行通信接口:
通信標準 | 引腳說明 | 通信方式 | 通信方向 |
UART | TXD:發送端 RXD:接收端 GND:公共地 |
異步通信 | 全雙工 |
單總線 | DQ:發送/接收端 | 異步通信 | 半雙工 |
SPI | SCK:同步時鐘 MISO:主機輸入,從機輸出 MOSI:主機輸出,從機輸入 |
同步通信 | 全雙工 |
IIC | SCL:同步時鐘 SDA:數據輸入/輸出端 |
同步通信 | 半雙工 |
3、異步串口通信UART
--》物理層(電氣層:接口決定):通信接口(RS232,RS485,RS422,TTL)
-RXD:數據輸入引腳。接收數據。
-TXD:數據發送引腳。發送數據。
TTL串口 & RS232 & RS485 & RS422通信接口:
接口類型 | 邏輯1典型值 | 邏輯0典型值 | 說明 | 優缺點 |
TTL | +5/3.3V | 0V | 一般的MCU串口引腳都支持TTL | 優點:接口簡單 缺點:距離在1.5米以內 |
RS232 | -3V~-15V | 3V~15V | 三線,全雙工 | 優點:距離在1.5~30米 缺點:最高傳輸速率20kb/s |
RS485 | -3V~-15V | 3V~15V | 兩線,利用壓差傳輸 | 優點:距離可達1219米, 最大傳輸速率10Mb/s(12米內) |
RS422 | -3V~-15V | 3V~15V | 不用共地,兩線, 平衡驅動差分接收,兩組電源獨立 |
優點:隔離抗幹擾性能強, 距離可達1219米,最大傳輸速率10Mb/s |
--》 數據格式(數據層:芯片決定)
STM32串口異步通信數據格式:
-->起始位:1個邏輯0數據位開始
-->數據位(8位或者9位)
-->奇偶校驗位(第9位)
-->停止位(1,1.5,2位)
-->波特率設置
STM32串口通信過程:
--》通信協議(協議層:程序決定)
通信協議往往由用戶自己根據需要來編寫。
1 void bbsapp_data_cheak(void) 2 { 3 switch(rxState) 4 { 5 case waitForStart: 6 if(aRxBuffer2[0] == 0x66) /*起始符正確*/ 7 { 8 USART2_RX_STA=1; 9 USART2_RX_BUF[0] = aRxBuffer2[0]; 10 rxState = waitForData; 11 } else /*起始符錯誤*/ 12 { 13 rxState = waitForStart; 14 } 15 break; 16 case waitForData: 17 USART2_RX_BUF[USART2_RX_STA] = aRxBuffer2[0]; 18 USART2_RX_STA++; 19 if (USART2_RX_STA == 6) /*數據接收完成,校驗*/ 20 { 21 rxState = waitForChksum; 22 } 23 break; 24 case waitForChksum: 25 USART2_RX_BUF[6] = aRxBuffer2[0]; 26 if (wifi_cheak(USART2_RX_BUF)) /*校驗正確,判斷結束符*/ 27 { 28 rxState = waitForEnd; 29 } else 30 { 31 rxState = waitForStart; /*校驗錯誤*/ 32 } 33 break; 34 case waitForEnd: 35 if (aRxBuffer2[0] == 0x99) /*結束符正確*/ 36 { 37 USART2_RX_BUF[7] = aRxBuffer2[0]; 38 printf("USART3_RX_BUF is %d %d %d %d %d %d %d %d \r\n",USART2_RX_BUF[0],USART2_RX_BUF[1],USART2_RX_BUF[2],USART2_RX_BUF[3],USART2_RX_BUF[4],USART2_RX_BUF[5],USART2_RX_BUF[6],USART2_RX_BUF[7]); 39 wifiDataHandle(); 40 app_ok=1; 41 // LCD_ShowNum(0,0,app_flap,10,8); 42 } else 43 { 44 rxState = waitForStart; /*結束符錯誤*/ 45 46 } 47 rxState = waitForStart; 48 break; 49 default: 50 break; 51 } 52 53 }串口接收數據解析
1 void wifiDataHandle(void) 2 { 3 app_flap = USART2_RX_BUF[1]; //副翼 橫向 4 app_elevator = USART2_RX_BUF[2]; //升降舵 前後 5 app_pwm = USART2_RX_BUF[3]; //油門 6 app_rudder = USART2_RX_BUF[4]; //方向舵 7 if((USART2_RX_BUF[5]&0x01)==0){ keyFlight=0; }else {keyFlight=1;} //一鍵起飛 先置1,1秒後置0 8 if((USART2_RX_BUF[5]&0x02)==0){ keyLand=0; }else {keyLand=1;} //一鍵降落 先置1,1秒後置0 9 if((USART2_RX_BUF[5]&0x04)==0){ emerStop=0; }else {emerStop=1;} //緊急停機 每次取反 10 if((USART2_RX_BUF[5]&0x08)==0){ flipOne=0; }else {flipOne=1;} //固定翻轉 11 if((USART2_RX_BUF[5]&0x10)==0){ flightMode=0; }else {flightMode=1;} //1無頭 0有頭 12 if((USART2_RX_BUF[5]&0x20)==0){ flipFour=0; }else {flipFour=1;} //一鍵翻轉 點擊後置1,當方向鍵移動過一半時清0 13 if((USART2_RX_BUF[5]&0x40)==0){ ledControl=0; }else {ledControl=1;} //光控制 14 if((USART2_RX_BUF[5]&0x80)==0){ gyroCalib=0; }else {gyroCalib=1;} //陀螺儀校準 先置1,1秒後置0 15 16 printf("app_flap app_elevator %d %d ",app_flap,app_elevator); 17 }通信協議
關於嵌入式學習隨筆->8《UART串行通信原理》