树莓派3B+和Pixhawk 2.4.8的连接 —— 使用 serial0
树莓派管脚定义图
查看树莓派的系统版本
cat /proc/version
显示
Linux version 4.14.79-v7+ (dc4@dc4-XPS13-9333) (gcc version 4.9.3 (crosstool-NG crosstool-ng-1.22.0-88-g8460611)) #1159 SMP Sun Nov 4 17:50:20 GMT 2018
查看串口的对应关系
ls -l /dev/serial*
可以看到设备的映射关系
lrwxrwxrwx 1 root root 7 2月 16 12:58 /dev/serial0 -> ttyS0
lrwxrwxrwx 1 root root 5 2月 16 12:58 /dev/serial1 -> ttyAMA0
根据树莓派官方文档的描述,
树莓派上使用的SoCs有两个内置UART,一个是PL011,一个是mini UART。它们是使用不同的硬件块实现的,因此它们具有稍微不同的特征。然而,两者都是3.3V的设备,这意味着当连接到RS232或其他使用不同电压水平的系统时必须格外小心。…
默认情况下,在安装了无线/蓝牙模块(Raspberry Pi 3和Raspberry Pi Zero W)的树莓派上,PL011 UART与蓝牙模块相连,而mini UART则是主要的UART,上面有一个Linux控制台。在所有其他型号上,PL011被用作主要的UART。
在Linux设备术语中,默认情况下,/dev/ttyS0表示迷你UART,而/dev/ttyAMA0表示PL011。主要的UART是分配给Linux控制台的UART,它依赖于上面描述的树莓派模型。还有符号链接:/dev/serial0,它总是引用主要的UART(如果启用);/dev/serial1,它同样总是引用次要的UART(如果启用)。
但这个mini UART有点复杂
mini UART的波特率与VC4 GPU上的VPU的核心频率有关。这意味着,当VPU调频器改变核心频率时,UART的波特率也会发生变化。这使得UART在默认状态下只能有限使用。默认情况下,如果选择mini UART作为主要的UART,它将被禁用。要启用它,请将enable_uart=1添加到/root/config.txt。这也将固定核心频率到250MHz(除非设置force_turbo,当它将固定到VPU turbo频率)。当迷你UART不是主要的UART时,例如您使用它来连接蓝牙控制器,您必须向config添加core_freq=250到conifg.txt,否则迷你UART将无法工作。
最新的Raspbian提供一个补丁,把蓝牙映射到mini UART,而让GPIO 14和GPIO 15管脚作为串口0的收发管脚。
执行
sudo nano /boot/config.txt
把下面内容添加进去即可。
enable_uart=1
dtoverlay=pi3-miniuart-bt
force_turbo=1
还要保证串口不被作为启动的控制台
sudo nano /boot/cmdline.txt
内容为
dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repai$
即保证和串口相关的定义都删除掉。
然后重启
sudo reboot
查看串口的属性
stty -F /dev/ttyAMA0 -a #ttyS0为要查看的串口
#默认波特率是9600
stty -F /dev/ttyAMA0 ispeed 115200 ospeed 115200 cs8 # 可以用stty设置串口参数
设置了波特率,打开测试
echo "This is from RaspBerry Pi" > /dev/ttyAMA0 | cat /dev/ttyAMA0
在PC上测试时,连接线不能太长,否则会出妖蛾子。
有可能串口被占用,用pi打开的时候报Permission Denied,删掉相关服务
sudo systemctl stop [email protected]
sudo systemctl disable [email protected]
sudo systemctl stop [email protected]
sudo systemctl disable [email protected]
写个基本的测试,参考的是
https://blog.csdn.net/qq_33479881/article/details/83540738
的代码。不知道为什么,我的板子上wiringSerial库不好使。
//////////////////////serial_test.cpp////////////////////////////
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
//Open Port & Set Port
int SerialInit(const char* device,speed_t baud) {
int fd = open(device, O_RDWR|O_NOCTTY|O_NDELAY);
if(-1 == fd) {
cerr << "Open Serial Port Error!" << endl;
return -1;
}
if( (fcntl(fd, F_SETFL, 0)) < 0 ) {
cerr << "Fcntl F_SETFL Error!" << endl;
close(fd);
return -1;
}
termios stNew, stOld;
if(tcgetattr(fd, &stOld) != 0) {
cerr << "tcgetattr error!" << endl;
close(fd);
return -1;
}
stNew = stOld;
cfmakeraw(&stNew);
//set speed
cfsetispeed(&stNew, baud);
cfsetospeed(&stNew, baud);
//set databits
stNew.c_cflag |= (CLOCAL|CREAD);
stNew.c_cflag &= ~CSIZE;
stNew.c_cflag |= CS8;
//set parity
stNew.c_cflag &= ~PARENB;
stNew.c_iflag &= ~INPCK;
//set stopbits
stNew.c_cflag &= ~CSTOPB;
stNew.c_cc[VTIME]=0;//
stNew.c_cc[VMIN]=1;//
tcflush(fd,TCIFLUSH);//
if( tcsetattr(fd,TCSANOW,&stNew) != 0 ) {
cerr << "tcsetattr Error!" << endl;
close(fd);
return -1;
}
return fd;
}
int main(int argc, char **argv) {
int fd = SerialInit("/dev/ttyAMA0",/*B921600 */ B115200);
if( -1 == fd ) {
cerr << "SerialInit Error!" << endl;
return 1;
}
const char* sendmsg = "This is from RaspberryPi!\n";
int len = strlen(sendmsg);
write(fd,sendmsg,len);
cout << sendmsg << endl;
char buffer[100];
while(1) {
usleep(20000);
int bytes = read(fd, buffer, 100);
if(-1 == bytes) {
cerr << "Read Data Error!" << endl;
break;
}
if(0 < bytes) {
buffer[bytes] = 0;
cout << "Recv Data: " << buffer << endl;
}
}
close(fd);
return 0;
}
编译执行
g++ serial_test.cpp -o serial_test
在电脑上能收发信息了,下一步和飞控通讯。