树莓派 gpio / 串口通信

15 篇文章 11 订阅
3 篇文章 3 订阅

使用树莓派 3B+/4B 测试 gpio,配置硬件串口,测试串口通信。

树莓派4B安装Debian 12(bookworm)和树莓派5B的配置差异可以跳转参看 【树莓派4B、树莓派5使用 Debian 12(bookworm) 的配置

1、GPIO扩展口定义、DB9接口定义

这里的板子上40pin引脚有3中编码方式:
1、Board编码:对应实际的物理插槽
2、BCM编码:基本和GPIO的名字对应
2、wiringPi编码:wiringPi库使用的引脚编码方式
在这里插入图片描述
DB9公头接口定义
在这里插入图片描述

在进行串口通信,两个设备间进行双向通信时,两个设备的RXD、TXD要交错连接

2、串口设置

树莓派包含两个串口(树莓派3及以前版本)
1.硬件串口/dev/ttyAMA0),硬件串口由硬件实现,有单独的波特率时钟源,性能高,可靠。一般优先选择这个使用。
2.mini串口/dev/ttyS0),mini串口时钟源是由CPU内核时钟提供,波特率受到内核时钟的影响,不稳定。

树莓派3及以前版本仅2个串口,4和400有4个串口,cm系列有6个串口,详见 树莓派官网Configuring UARTs
 
树莓派4开启 ttyAMA1,可以直接配置 dtoverlay=uart2 即可(其他 ttyAMA2 -> uart3, ttyAMA3 -> uart4, ttyAMA4 -> uart5,具体引脚配置可以通过 dtoverlay -h uartN 查看)。
 
注意 CM4 使用双相机的dtb配置( 树莓派计算模块CM4 eMMC系统烧写、配置、相机连接)时,ttyAMA1会失效

想要通过树莓派的GPIO引脚进行稳定的串口通信,需要修改串口的映射关系。
serial0是GPIO引脚对应的串口,serial1是蓝牙对应的串口,默认未启用serial0。使用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 (树莓派4B也使用这个命令)。 还可以直接配置禁用bluetooth,代码为 dtoverlay=disable-bt,见参考链接 【树莓派 功能配置(含网络)不定期更新】

保存后重启再查看设备对用关系,发现已经调换成功。
在这里插入图片描述

2.2 禁用串口的控制台功能

前面步骤已经交换了硬件串口与mini串口的映射关系,但是,现在还不能使用树莓派串口模块与电脑进行通信,因为,树莓派gpio口引出串口默认是用来做控制台使用的,即是为了用串口控制树莓派,而不是通信。所以我们要禁用此默认设置。
首先执行命令如下:
sudo systemctl stop serial-getty@ttyAMA0.service
sudo systemctl disable serial-getty@ttyAMA0.service
然后执行命令行修改文件:
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 ;
}

  • 31
    点赞
  • 294
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

aworkholic

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值