树莓派 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万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章