树莓派从大的方向来说一共出了3代,每一代的CPU外设基本相同,但内核不同,外设里面一共包含两个串口,一个称之为硬件串口(/dev/ttyAMA0),一个称之为mini串口(/dev/ttyS0)。硬件串口由硬件实现,有单独的波特率时钟源,性能高、可靠,mini串口性能低,功能也简单,并且没有波特率专用的时钟源而是由CPU内核时钟提供,因此mini串口有个致命的弱点是:波特率受到内核时钟的影响。内核若在智能调整功耗降低主频时,相应的这个mini串口的波特率便受到牵连了,虽然你可以固定内核的时钟频率,但这显然不符合低碳、节能的口号。在所有的树莓派板卡中都通过排针将一个串口引出来了,目前除了树莓派3代以外 ,引出的串口默认是CPU的那个硬件串口。而在树莓派3代中,由于板载蓝牙模块,因此这个硬件串口被默认分配给与蓝牙模块通信了,而把那个mini串口默认分配给了排针引出的GPIO Tx Rx,下图是树莓派3的接口图
其中红框中就是引出的串口IO,如果我们需要通过UART外接模块,默认情况下必须得使用性能很低的mini串口了,而且随着内核主频的变化,还会造成波特率的变化导致通信的失败,几乎很难使用。所以我们希望恢复硬件串口与GPIO 14/15的映射关系,使得我们能够通过GPIO使用高性能的硬件串口来连接我们的串口设备。
树莓派可以配置文件来修改设备树,我的理解是可以通过配置文件来修改管脚的映射关系,这在许多Cortex-M3内核的单片机中也很常见,可以将同一个串口映射到不同的管脚上,以方便PCB的布线。
为了在树莓派3中通过GPIO使用高性能的硬件串口,我们必须将分配给蓝牙使用的硬件串口与分配给IO排针的mini串口进行对换,这必然会使得蓝牙模块的功能受到影响,但还好,蓝牙并不是必须的。
在树莓派系统中
/boot/overlays/
目录下,提供了一个pi3-miniuart-bt-overlay.dtb的文件,这个文件的作用可以通过该目录下的README文件查看
如果没有pi3-miniuart-bt-overlay.dtb这个文件,点击 http://ukonline2000.com/wp-content/uploads/2016/03/ 下载
README文件中说明了这个文件的功能是将树莓派3的蓝牙切换到mini串口(ttyS0),并且恢复硬件串口(ttyAMA0)到GPIO 14&15脚中。并且给出了载入的方法。
首先在树莓派命令终端中通过命令查看树莓派3当前的串口映射关系
红色框中体现的应该是一种映射关系,此处暂时没有做深究,简单理解 serial0 就是GPIO映射的串口,此时GPIO映射的串口是默认的/dev/ttyS0这个mini串口。
使用下面这条指令编辑 /boot/config.txt 文件
sudo nano /boot/config.txt
在该文件中增加一行代码
dtoverlay=pi3-miniuart-bt
然后保存文件,重启树莓派使之生效。
再通过 ls -l /dev 命令查看修改后的映射关系
前面的步骤已经交换了硬件串口与mini串口的映射关系,但现在想使用树莓派外接串口模块进行通信还不行,因为树莓派IO引出的串口默认是用来做控制台使用的,它的初衷是为了在没有网络接口时,通过串口对树莓派进行相关的配置。因此需要禁用这个默认功能,使得串口为我们自由使用。
在树莓派命令窗口中分别通过如下两个命令停止和禁用串口的控制台功能
sudo systemctl stop [email protected]
sudo systemctl disable [email protected]
由于我们前面已经交换了串口的映射关系,因此这里注意是ttyAMA0。
然后通过下列指令编辑cmdline.txt文件
sudo nano /boot/cmdline.txt
然后看到里面类似如下的内容
dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait
修改如下:
dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait
然后重新启动树莓派,使修改生效。
树莓派3代不同于以往的树莓派旧版,CPU的高性能硬件串口默认分配给了蓝牙使用,GPIO 14&15默认分配的是性能较差的mini串口,在无需使用板载蓝牙的情况下,可以通过配置文件修改树莓派的设备树,使得高性能硬件串口重新恢复映射到IO排针接口中。同时要想通过GPIO 14&15外接串口通信模块还需要关掉串口的默认控制台功能