使用树莓派 3B+/4B 测试 gpio,配置硬件串口,测试串口通信。
文章目录
- 1、GPIO扩展口定义、DB9接口定义
- 2、串口设置
- 2.1 开启GPIO串口功能,并使用硬件串口
- 2.2 禁用串口的控制台功能
- 2.3 测试验证串口通信功能
- 2.3.1 c语言实现
- 2.3.2 python实现
- 2.3.3 minicom命令函实现
- 2.4 wiringPi库c语言完整串口通信代码
- 3、GPIO 编程
- 3.1 gpio命令行
- 3.2 Python 库 RPi.GPIO编程
- 3.3 c/c++使用wiringPI库
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配置时,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 ;
}