樹莓派 gpio / 串口通信

使用樹莓派 3B+ 測試 gpio,配置硬件串口,測試串口通信

1、GPIO擴展口定義、DB9接口定義

這裏的板子上40pin引腳有3中編碼方式:
1、Board編碼:對應實際的物理插槽
2、BCM編碼:基本和GPIO的名字對應
2、wiringPi編碼:wiringPi庫使用的引腳編碼方式
在這裏插入圖片描述
DB9公頭接口定義
在這裏插入圖片描述

在進行串口通信,兩個設備間進行雙向通信時,兩個設備的RXD、TXD要交錯連接

2、串口設置

樹莓派包含兩個串口
1.硬件串口/dev/ttyAMA0),硬件串口由硬件實現,有單獨的波特率時鐘源,性能高,可靠。一般優先選擇這個使用。
2.mini串口/dev/ttyS0),mini串口時鐘源是由CPU內核時鐘提供,波特率受到內核時鐘的影響,不穩定。

想要通過樹莓派的GPIO引腳進行穩定的串口通信,需要修改串口的映射關係。
serial0是GPIO引腳對應的串口,serial1是藍牙對應的串口。使用ls -l /dev/serial*查看當前的映射關係:
在這裏插入圖片描述
可以看到這裏是,藍牙串口serial1使用硬件串口ttyAMA0。

2.1 開啓GPIO串口功能,並使用硬件串口

使用sudo raspi-config 進入圖形界面
選擇菜單 Interfacing Options -> P6 Serial,
第一個選項(would you like a login shell to be accessible over serial?)選擇NO,
第二個選項(would you like the serial port hardware to be enabled?)選擇 YES

保存後重啓,查看映射關係
在這裏插入圖片描述
比之前多了一個gpio的串口serial0,並且使用的ttyS0。這裏已經是開啓了GPIO串口功能,但是使用的cpu實現的軟件串口

如果想使用穩定可靠的硬件串口,就要將樹莓派3b+的硬件串口與mini串口默認映射對換(先禁用藍牙 sudo systemctl disable hciuart)。
在/boot/config.txt文件末尾添加一行代碼 dtoverlay=pi3-miniuart-bt
保存後重啓再查看設備對用關係,發現已經調換成功。
在這裏插入圖片描述

2.2 禁用串口的控制檯功能

前面步驟已經交換了硬件串口與mini串口的映射關係,但是,現在還不能使用樹莓派串口模塊與電腦進行通信,因爲,樹莓派gpio口引出串口默認是用來做控制檯使用的,即是爲了用串口控制樹莓派,而不是通信。所以我們要禁用此默認設置。
首先執行命令如下:
sudo systemctl stop [email protected]
sudo systemctl disable [email protected]
然後執行命令行修改文件:
sudo nano /boot/cmdline.txt
並刪除語句console=serial0,115200(沒有的話就不需要此步驟)

2.3 測試驗證串口通信功能

這裏使用三種方式進行測試驗證, c語言下使用wiringPi庫, python語言下使用serial包,最後命令行使用minicom工具。
先安裝以上開發工具
sudo apt-get install wiringpi
sudo apt-get install python-serial
sudo apt-get install minicom

將usb轉ttl模塊引腳的GND、TX、RX分別與樹莓派的GND、RX、TX連接;電腦端啓用串口調試助手,波特率設置一致。

2.3.1 c語言實現

編寫test.c測試代碼,

#include <stdio.h>
#include <wiringPi.h>
#include <wiringSerial.h>
  
int main()
{
    int fd;
    if(wiringPiSetup()<0) {
        return 1;
    }

    //if((fd=serialOpen("/dev/ttyS0",115200))<0) { // gpio 使用mini串口
    if((fd=serialOpen("/dev/ttyAMA0",115200))<0) { // gpio 使用硬件串口
        return 1;
    }
 
    printf("serial test output ...\n");
    serialPrintf(fd,"1234567890abcdef");
 
    serialClose(fd);
    return 0;
}

編譯 gcc test.c -o test -lwiringPi,運行 sudo ./test
在這裏插入圖片描述在這裏插入圖片描述

2.3.2 python實現

# -*- coding: utf-8 -*
import serial
import time

ser = serial.Serial("/dev/ttyAMA0",115200)

if not ser.isOpen():
    print("open failed")
else:
    print("open success: ")
    print(ser)

try:
    while True:
        count = ser.inWaiting()
        if count > 0:
            recv = ser.read(count)
            print("recv: " + recv)
        	ser.write(recv)
        sleep(0.05) 
except KeyboardInterrupt:
    if ser != None:
        ser.close()

運行python代碼,並在串口調試助手中發送字符串,樹莓派收到數據後打印、在回發給串口助手,截圖如下。
在這裏插入圖片描述
在這裏插入圖片描述

2.3.3 minicom命令函實現

使用minicom -b 115200 -D /dev/ttyAMA0進入串口調試界面,這裏將一直等待接收,直到用戶手動退出。退出時ctrl+A,再按鍵X退出。
minicom調試界面默認是不顯示用戶輸入,使用cttl+A,再按E即可開啓(會捕獲換行)。

串口助手和minicom界面的交互如下:
串口助手發送“1234567890abcdef”,
minicom發送"\n”,“1”,"\n",“3”,“4”,"\n"
串口助手發送“1234567890abcdef”,

界面截圖如下:
在這裏插入圖片描述
在這裏插入圖片描述

2.4 wiringPi庫c語言完整串口通信代碼

使用wiringPI庫進行發送和持續接收的示例代碼,如下

#include <stdio.h>
#include <wiringPi.h>
#include <wiringSerial.h>

#include <signal.h>
#include <unistd.h>
#include <stdlib.h>

int running = 1;

void sig_handle(int sig)
{
   if(sig == SIGINT)   running = 0;
}

int main()
{    
    signal(SIGINT, sig_handle);    

    int fd;
    if(wiringPiSetup() < 0){
        printf("wiringPi setup failed.\n");
        return 1;
    }

    int baudrate = 115200;

    //if((fd = serialOpen("/dev/ttyS0", baudrate)) < 0){  
    if((fd = serialOpen("/dev/ttyAMA0",baudrate)) < 0){
        printf("serial open failed.\n");
        return 1;
    }

    printf("serial test output ...\n"); 
    serialPrintf(fd, "0123456789abcdef");  //發送

    while(running)
    {
       int sz = serialDataAvail(fd); // 等待介紹的數據個數
       
       if(sz > 0)
       {
         printf("size %d, ", sz);
         char *buff =(char*)malloc(sz);
         printf("recv: ");
         for(int i = 0; i < sz; i++){
              int c = serialGetchar(fd);  //接收一個字符
              //if(c != -1)
                  buff[i] = c;  
         }
         printf("%s\n", buff);
         free(buff);

         serialPrintf(fd, buff);//回顯
       }
       else{
         usleep(50000); // 必要的延時50ms
       }
    }

    serialClose(fd);
    printf("close serial.\n");

    return 0;
}

tip:延時的作用:1、匹配串口讀寫速度,使得下一次讀時,設備已經完成寫操作; 2、減小資源佔用;
若不延時,CPU佔用高,並且最多一次讀取一個字符。

3、GPIO 編程

這裏演示BCM_gpio 22輸出控制,串接一個220歐姆、led燈珠到GND,進行亮、滅燈控制。
在這裏插入圖片描述
這裏涉及引腳連線、編程中確定口線,需要熟悉引腳編碼。先以gpio命令行工具說明編碼、並進行測試,再使用python、c語言實現。

3.1 gpio命令行

使用gpio -v查看版本
在這裏插入圖片描述
使用gpio readall查看引腳編碼
在這裏插入圖片描述
這裏我們選擇的名稱爲"BCM_GPIO.22",對應的是BCM編碼"22",wPi編碼"3",而實際的物理插槽BOARD編碼是"15"。 因此實際接線應該使用插槽編碼爲15的口線。

gpio工具使用的是BCM編碼。設置BCM_GPIO.22口爲輸出模式, 寫”1”燈亮,寫”0”燈滅。

gpio -g mode 22 out
gpio -g write 22 1
gpio -g write 22 0

3.2 Python 庫 RPi.GPIO編程

這裏的操作結果同上,使用RPi.GPIO庫。若無該庫,先進行安裝 sudo pip install RPi.GPIO
先使用python idle進行簡單控制

import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)   ## 編號默認BCM
GPIO.setup(22, GPIO.OUT)
GPIO.output(22, GPIO.HIGH)
GPIO.output(22, LOW)
GPIO.output(22, 1)
GPIO.output(22, 0)

在利用腳本讓其間隔一秒鐘亮滅

# -*- coding: utf-8 -*-                 
import RPi.GPIO as GPIO               #引入RPi.GPIO庫函數命名爲GPIO
import time                           #引入計時time函數
# BOARD編號方式,基於插座引腳編號
GPIO.setmode(GPIO.BOARD)              #將GPIO編程方式設置爲BOARD模式
# 輸出模式
GPIO.setup(15, GPIO.OUT)              #將Board 15引腳(BCM 22)設置爲輸出引腳

while True:                            #條件爲真,下面程序一直循環執行
    GPIO.output(15, GPIO.HIGH)         #將15引腳電壓置高,點亮LED燈
    time.sleep(1)                      #延時1秒
    GPIO.output(15, GPIO.LOW)          #將15引腳電壓置低,熄滅LED燈
    time.sleep(1)                      #延時1秒

3.3 c/c++使用wiringPI庫

重複上面引用內容: 這裏我們選擇的名稱爲"BCM_GPIO.22",對應的是BCM編碼"22",wPi編碼"3",而實際的物理插槽BOARD編碼是"15"。

使用wiringPI庫時,IO口爲wPi編碼,爲保證和前面的實列對應相同,使用編號爲3

編寫以下test.c代碼
編譯 gcc test.c -o test -lwiringPi,運行 ./test

#include <stdio.h>
#include <wiringPi.h>

// LED Pin - wiringPi pin 3 is BCM_GPIO 22.(pyscial 15)
#define  LED  3

int main (void)
{
  if(wiringPiSetup() < 0){
      printf("wiringPi setup failed.\n");
      return 1;
  }

  pinMode(LED, OUTPUT);  // 設置輸出模式

  for (;;)
  {
    digitalWrite(LED, HIGH) ;	// On
    delay(500) ;		        // mS
    digitalWrite(LED, LOW) ;	// Off
    delay(500) ;
  }
  return 0 ;
}

發佈了66 篇原創文章 · 獲贊 76 · 訪問量 19萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章