正点原子嵌入式linux驱动开发——Linux 串口RS232/485/GPS 驱动

news/2024/11/28 15:44:41/

串口是很常用的一个外设,在Linux下通常通过串口和其他设备或传感器进行通信,根据
电平的不同,串口分为TTL和RS232
。不管是什么样的接口电平,其驱动程序都是一样的,通过外接RS485这样的芯片就可以将串口转换为RS485信号,正点原子的STM32MP1开发板就是这么做的。对于正点原子的STM32MP1开发板而言有8个串口,四个同步串口(USART1、USART2、USART3和USART6),四个异步串口(UART4、UART5、UART7和UART8)

RS232和RS485接口连接到了STM32MP1的USART3接口上,通过跳线帽选择USART3作为RS232还是RS485。GPS模块是连接到UART5接口上,因此这些外设最终都归结为USART3和UART5的串口驱动。本章就来学习一下如何驱动STM32MP1开发板上的USART3串口和UART5,进而实现RS232、RS485以及GPS驱动

Linux下UART驱动框架

uart_driver注册/注销

同I2C、SPI一样,Linux也提供了串口驱动框架,只需要按照相应的串口框架编写驱动程序即可。串口驱动没有什么主机端和设备端之分,就只有一个串口驱动,而且这个驱动也
已经由ST官方编写好了,真正要做的就是在设备树中添加所要使用的串口节点信息
。当
系统启动以后串口驱动和设备匹配成功,相应的串口就会被驱动起来,生成/dev/ttySTMX(X=0….n)文件。

虽然串口驱动不需要自行实现,但是串口驱动框架还是需要了解的,uart_driver结构体表示UART驱动,uart_driver定义在 include/linux/serial_core.h文件中,内容如下:

uart_driver结构体

每个串口驱动都需要定义一个uart_driver,加载驱动的时候通过uart_register_driver函数向系统注册这个uart_driver,此函数原型如下:

int uart_register_driver(struct uart_driver *uart) 

函数参数和返回值含义如下:

  • uart:要注册的uart_driver。
  • 返回值:0,成功;负值,失败。

注销驱动的时候也需要注销掉前面注册的uart_driver,需要用到uart_unregister_driver函数,函数原型如下:

void uart_unregister_driver(struct uart_driver *uart) 

函数参数和返回值含义如下:

  • uart:要注销的uart_driver。
  • 返回值:无。

uart_port添加/移除

uart_port表示一个具体的port,uart_port定义在 include/linux/serial_core.h文件,内容如下(有省略):

uart_port结构体

uart_port中最主要的就是第240行的ops,ops包含了串口的具体驱动函数。每个UART都有一个uart_port,那么uart_port是怎么和uart_driver结合起来的呢?这里要用到uart_add_one_port函数,函数原型如下:

int uart_add_one_port(struct uart_driver *reg, struct uart_port *port) 

函数参数和返回值含义如下:

  • reg:此port对应的uart_driver。
  • port:要添加到uart_driver中的port。
  • 返回值:0,成功;负值,失败。

卸载UART驱动的时候也需要将uart_port从相应的uart_driver中移除,需要用到uart_remove_one_port函数,函数原型如下:

int uart_remove_one_port(struct uart_driver *reg, struct uart_port *port) 

函数参数和返回值含义如下:

  • reg:要卸载的port所对应的uart_driver。
  • port:要卸载的uart_port。
  • 返回值:0,成功;负值,失败。

uart_ops实现

在上面讲解uart_port的时候说过,uart_port中的ops成员变量很重要,因为ops包含了针对UART具体的驱动函数,Linux系统收发数据最终调用的都是ops中的函数 。ops是uart_ops类型的结构体指针变量,uart_ops定义在include/linux/serial_core.h文件中,内容如下:

示例代码 46.1.3 uart_port 结构体
37 struct uart_ops {
38     unsigned int (*tx_empty)(struct uart_port *);
39     void (*set_mctrl)(struct uart_port *, unsigned int mctrl);
40     unsigned int (*get_mctrl)(struct uart_port *);
41     void (*stop_tx)(struct uart_port *);
42     void (*start_tx)(struct uart_port *);
43     void (*throttle)(struct uart_port *);
44     void (8unthrottle)(struct uart_port *);
45     void (*send_xchar)(struct uart_port *, char ch);
46     void (*stop_rx)(struct uart_port *);
47     void (*enable_ms)(struct uart_port *);
48     void (*break_ctl)(struct uart_port *, int ctl);
49     int (*startup)(struct uart_port *);
50     void (*shutdown)(struct uart_port *);
51     void (*flush_buffer)(struct uart_port *);
52     void (*set_termios)(struct uart_port  *, struct ktermios *new, 
53                 struct ktermios *old);
54     void (*set_ldisc)(struct uart_port *, struct ktermios *);
55     void (*pm)(struct uart_port *, unsigned int state, 
56                     unsigned int oldstate);
57
58     /*
59      * Return a string describing the type of the port
60      */
61     const char *(*type)(struct uart_port *);
62
63     /*
64      * Release IO and memory resources used by the
65      * This includes iounmap if
66      */
67     void (*release_port)(struct uart_port *);
68
69     /*
70      * Request IO and memory resources used by the
71      * This includes iomapping the port if
72      */
73     int (*request_port)(struct uart_port *);
74     void (*config_port)(struct uart_port  *, int);
75     int (*verify_port)(struct uart_port *, struct serial_struct );
76     int (*ioctl)(struct uart_port *, unsigned int, unsigned long);
77 #ifdef CONFIG_CONSOLE_POLL
78     int (*poll_init)(struct uart_port *);
79     void (*poll_put_char)(struct uart_port *, unsigned char);
80     int (*poll_get_char)(struct uart_port *);
81 #endif
82 };

UART驱动编写人员需要实现uart_ops,因为uart_ops是最底层的UART驱动接口,是实实在在的和UART寄存器打交道的。关于uart_ops结构体中的这些函数的具体含义请参考Documentation/serial/driver这个文档

UART驱动框架大概就是这些,接下来理论联系实际,看一下ST官方的UART驱动文件是如何编写的。

STM32MP1 UART驱动分析

UART的platform驱动框架

打开stm32mp151.dtsi文件,找到USART3对应的子节点,子节点内容如下所示:

usart3设备节点

重点看一下第2行的compatible属性值为“st,stm32h7-uart”。在linux源码中搜索这个值即可找到对应的UART驱动文件,此文件为drivers/tty/serial/stm32-usart.c,在此文件中可以找到如下内容:

示例代码 46.2.2 UART platform 驱动框架
1218 static const struct of_device_id stm32_match[] = {
1219     { .compatible = "st,stm32 uart", .data = &stm32f4_info},
1220     { .compatible = "st,stm32f7 uart", .data = &stm32f7_info},
1221     { .compatible = "st,stm32h7 uart", .data = &stm32h7_info},
1222     {},
1223 };
......
1668 static struct platform_driver stm32_serial_driver = {
1669     .probe = stm32_usart_serial_probe,
1670     .remove = stm32_usart_serial_remove,
1671     .driver = {
1672         .name = DRIVER_NAME,
1673         .pm = &stm32_serial_pm_ops,
1674         .of_match_table = of_match_ptr(stm32_match),
1675     },
1676 };
1677
1678 static int __init stm32_usart_init(void)
1679 {
1680 static char banner[] __initdata = "STM32 USART driver initialized";
1681     int ret;
1682
1683     pr_info("%s\n", banner);
1684
1685     ret = uart_register_driver(&stm32_usart_driver);
1686     if (ret)
1687         return ret;
1688
1689     ret = platform_driver_register(&stm32_serial_driver);
1690     if (ret)
1691         uart_unregister_driver(&stm32_usart_driver);
1692
1693     return ret;
1694 }
1695
1696 static void __exit stm32_usart_exit(void)
1697 {
1698     platform_driver_unregister(&stm32_serial_driver);
1699     uart_unregister_driver(&stm32_usart_driver);
1700 }
1701
1702 module_init(stm32_usart_init);
1703 module_exit(stm32_usart_exit);

可以看出STM32MP1的UART本质上是一个platform驱动,第1218-1223行,设备树所
使用的匹配表,第1221行的compatible属性值为“st,stm32h7-uart”。

第1668-1676行,platform驱动框架结构体stm32_serial_driver。

第1678-1694行,驱动入口函数,第1685行调用uart_register_driver函数向Linux内核注册uart_driver,在这里就是stm32_usart_driver。

第1696-1700行,驱动出口函数,第1699行调用uart_unregister_driver函数注销掉前面注册的uart_driver,也就是stm32_usart_driver。

uart_driver初始化

在stm32_usart_init函数中向Linux内核注册了stm32_usart_driver,stm32_usart_driver就是uart_driver类型的结构体变量,stm32_usart_driver定义如下:

stm32_usart_driver结构体

uart_port初始化与添加

当UART设备和驱动匹配成功以后stm32_usart_serial_probe函数就会执行,此函数的重点工作就是初始化uart_port,然后将其添加到对应的uart_driver中。在看stm32_usart_serial_probe函数之前先来看一下stm32_port结构体,stm32_port是ST为STM32MP1系列SOC定义的一个设备结构体,此结构体内部就包含了uart_port成员变量,stm32_port结构体内容如下所示(有
缩减):

stm32_port结构体

第258行,uart_port结构体成员变量:port。

第279行,这里定义了一个数组为stm32_ports,数组的类型为stm32_port结构体,数组的长度为8。这是因为STM32MP157最多只有8个串口,一个串口对应一个stm32_port,因此数组长度就是8。

接下来看一下stm32_usart_serial_probe函数,函数内容如下:

stm32_usart.c文件代码段

第1312行,调用stm32_usart_of_get_port函数,它主要是负责配置stm32_ports数组。

第1322行,调用stm32_usart_init_port函数,它主要是负责获取SOC UART外设首地址、
中断号、注册中断函数同时还设置uart_ops为stm32_uart_ops,stm32_uart_ops就是STM32MP1最底层的驱动函数集合。

第1374行,使用uart_add_one_port向uart_driver添加uart_port,在这个就是向stm32_usart_driver添加stm32port->port。

接下来看一下stm32_usart_of_get_port函数,因为stm32_usart_serial_probe函数会调用此函数来获取串口信息,这些串口信息会放到示例代码46.2.4中的stm32_ports数组里面。stm32_usart_of_get_port函数源码如下:

stm32_usart_of_get_port函数

第1197行,通过of_alias_get_id函数从设备树的aliases节点中获取“serial”相关的ID。打开stm32mp157d-atk.dts文件,当前此文件里面的aliases节点内容如下图所示:

aliases节点

从上图可以看出,此时alases节点里面只有一个serial0,对应STM32MP157的uart4。所以stm32_usart_of_get_port函数只能得到uart4这一个串口的信息,如果要使用其他的串口,那就必须向alases节点里面按照如下格式添加对应的串口信息

serialX=&串口名字;

这个X表示0-7,那是因为STM32MP1的串口只有8个。&后面的串口名字一定要对应设备树中具体的串口名,比如usart3、uart5等

第1206-1213行,获取对应的串口信息,然后保存到stm32_ports数组中,获取到的串口ID就是串口在数组中的索引。

第1214行,返回得到的串口信息。

接下来再来看一下stm32_usart_init_port函数,stm32_usart_serial_probe函数会调用此函数来初始化串口!函数源码如下所示:

stm32_usart_init_port函数

stm32_usart_init_port函数主要是负责获取SOC UART外设首地址、中断号、注册中断函数。重点是1149行设置uart_ops为stm32_uart_ops,stm32_uart_ops就是 STM32MP1最底层的驱动函数集合

stm32_uart_ops结构体变量

stm32_uart_ops就是uart_ops类型的结构体变量,保存了STM32MP1串口最底层的操作函
数,stm32_uart_ops定义如下:

stm32_uart_ops

stm32_uart_ops中的函数基本都是和STM32MP1的UART寄存器打交道的,这里就不去详细的分析了。简单的了解了STM32MP1的UART驱动以后再来学习一下,如何驱动正点原子STM32MP1开发板上的USART3接口和UART5接口。

硬件原理图分析

本实验要用到的STM32MP1的USART3接口和UART5接口,USART3连接RS485和RS232的公头,UART5连接GPS和RS232的母头。依次来看一下这个两个串口的硬件原理图。

RS232原理图

RS232原理图如下图所示:

RS232原理图

正点原子STM32MP157开发板一共有2个RS232串口,上图中COM1是母头,COM2为公头,这两个RS232串口都是通过SP3232这个芯片来实现

COM1母头连接到STM32MP1的UART5接口上,COM1和正点原子的ATK模块共用USART5,把JP5的1-3和2-4连接起来以后SP3232就和URAT5连接到一起了。 UART5_TX和UART5_RX分别接到了PB13和PB12这两个引脚上

COM2公头连接到了STM32MP1的USART3接口上,COM2和RS485共用USART3,把JP4的3-5和4-6连接起来以后SP3232就和USRAT3连接到一起了USART3_TX和USART3_RX分别接到了PD8和PD9这两个引脚上

RS485原理图

RS485和COM2共用USART3,将上图中JP4的3-5和4-6连接起来,这时候RS485就连接到了USART3上。RS485原理图如下图所示:

RS485原理图

RS485采用SP3485这颗芯片来实现,RO为数据输出端,RI为数据输入端,RE是接收使能信号(低电平有效),DE是发送使能信号(高电平有效)。在上图中RE和DE经过一系列的电路,最终通过RS485_RX来控制,这样可以省掉一个RS485收发控制IO,将RS485完全当作一个串口来使用,方便写驱动。

GPS原理图

正点原子有一款GPS+北斗定位模块,型号为ATK1218-BD,STM32MP157开发板留出了这款GPS定位模块的接口,接口原理图如下图所示:

ATK MODULE模块

前面讲解RS232原理图的时候说了,COM1和正点原子的ATK模块共用USART5接口,正点原子的ATK1218-BD这个模块用的就是ATK模块接口。如果要使用GPS模块,就要将RS232原理图中JP5的3-5和4-6连接起来。这样GPS模块就连接到了USART5上,USART5驱动成功以后就可以直接读取GPS模块数据了。从上图可以看出,ATK模块还有两个引脚GBC_KEY和GBC_LED分别连接到了STM32MP157的PC13和PI8上,这两个引脚是给其他模块准备的,GPS模块并没有用到。

RS232驱动编写

前面已经说过了,STM32MP1的UART驱动ST已经编写好了,所以不需要自行编写。要做的就是在设备树中添加USART3和UART5对应的设备节点即可。打开stm32mp157d-atk.dts文件,因为usart3和uasrt5的节点在stm32mp151.dtsi已经存在了,只要在stm32mp157d-atk.dts文件里面向这些节点追加一些内容即可,追加步骤如下:

添加usart3和uart5引脚信息

先在stm32mp15-pinctrl.dtsi文件看下没有usart3和uart5的引脚配置,以及引脚配置是
否是开发板对应的。默认情况下stm32mp15-pinctrl.dtsi里面是有usart3的引脚配置,但是
不是正点原子开发板所使用的PD8和PD9,所以不能使用。直接在stm32mp15-pinctrl.dtsi里面添加usart3和uart5这两个串口对应的引脚信息,内容如下:

示例代码 46.4.1 要追加的 pinmux 配置
1 usart3_pins_c: usart3-2 {
2     pins1 {
3         pinmux = <STM32_PINMUX('D', 8, AF7)>; /* USART3_TX */
4         bias-disable;
5         drive-push-pull;
6         slew-rate = <0>;
7     };
8     pins2 {
9         pinmux = <STM32_PINMUX('D', 9, AF7)>; /* USARTS_RX */
10         bias-disable;
11     };
12 };
13
14 uart5_pins_a: uart5-0 {
15     pins1 {
16         pinmux = <STM32_PINMUX('B', 13, AF14)>; /* UART5_TX */
17         bias-disable;
18         drive-push-pull;
19         slew-rate = <0>;
20     };
21     pins2 {
22         pinmux = <STM32_PINMUX('B', 12, AF14)>; /* UART5_RX */
23         bias-disable;
24     };
25 };

示例代码46.4.1里配置了两个pinmux分别为usart3_pins_c和uart5_pins_a。稍后向usart3和uart5中追加内容的时候就会用到这两个节点。

向usart3和uart5节点追加内容

还是在stm32mp157d-atk.dts文件中,在不是根节点下追加如下代码:

示例代码 46.4.2 串口的节点
1  &usart3 { 
2      pinctrl-names = "default"; 
3      pinctrl-0 = <&usart3_pins_c>; 
4      status = "okay"; 
5  }; 
6 
7  &uart5 { 
8     pinctrl-names = "default";
9       pinctrl-0 = <&uart5_pins_a>; 
10     status = "okay"; 
11 };

这里追加了两个串口,分别为uart5和usart3,追加的内容很简单都是使用了刚刚添加的pinmux配置。把status属性原来为“disabled”改为“okay”。

设置串口别名

之前UART驱动分析已经知道,驱动会读取aliases节点,添加的别名如下所示:

示例代码 46.4.3 串口的别名
1 aliases {
2     serial0 = &uart4;
3     serial1 = &uart5;
4     serial2 = &usart3;
5 };

serial0是uart4的别名,表示在系统启动生成一个名为“/dev/ttySTM0”的设备文件serial1就会生成“/dev/ttySTM1”如此类推,最多8个。serial0就是调试串口。

修改完成以后重新编译设备树并使用新的设备树启动Linux,如果设备树修改成功的话系统启动以后就会有如下图所示设备文件:

串口设备文件

ttySTM0为serial0,对应uart4;ttySTM1为serial1,对应uart5;ttySTM2为serial2,对应usart3。

移植minicom

minicom类似常用的串口调试助手,是Linux下很常用的一个串口工具,将minicom移植到开发板中,这样就可以借助minicom对串口进行读写操作

buildroot已经集成了minicom,所以只需要重新配置buildroot,使能minicom即可。首先跳转到buildroot的源码目录下,打开buildroot的图形化配置界面里配置以下选项:

-> Target packages
-> Hardware handling
[*] minicom

配置如下图所示:

使能minicom

保存buildroot的配置文件,输入命令“sudo make”重新编译文件系统。编译的时候要联网,因为buildroot在编译的时候需要从网上下载 minicom源码。当编译完成后,进入output/images目录,运行以下命令把文件系统替换进去:

cd output/images/ //进入到 output/images目录
sudo tar -axvf rootfs.tar -C /home/zuozhongkai/linux/nfs/rootfs //解压到 nfsroot目录

上述命令将buildroot中output/images/rootfs.tar这个压缩包解压到/home/zuozhongkai/linux/nfs/rootfs这个目录中,这个目录就是当前nfsroot目录,需要根据自己的实际情况解压到对应的目录文件中。

完成以后重启开发板!重启以后在开发板中输入“minicom -v”来查看minicom工作是否正常,结果如下图所示:

minicom版本号

从上图可以看出,此时minicom版本号为2.7.90,minicom版本号查看正常。输入如下命令打开minicom配置界面:

minicom -s

此时minicom配置界面就可以打开了,如下图所示:

minicom配置界面

如果出现如上图所示的界面,那么minicom就已经能够正常工作了。

RS232驱动测试

RS232连接设置

在测试之前要先将STM32MP1开发板的RS232接口与电脑连接起来,正点原子STM32MP1开发板上两个RS232接口如下图所示:

RS232接口

从上图中可以看出,正点原子开发板上有2个 RS232接口。这里要注意的是这两个RS232接口一个为公头,一个为母头,方便外接自己的设备。上图中左边的COM2为公头,可以通过JP4跳接到USART3上。右边的COM1为母头,可以通过JP5跳接到UART5上。本实验使用右边的COM1,所以需要将JP5的两个跳线帽接到上方,也就是将UART5与COM1连接起来

跳线帽设置好以后使用RS232线将开发板与电脑连接起来,这里建议使用USB转DB9(RS232)数据线,比如正点原子的CH340方案的USB转DB9数据线,如下图所示:

USB转DB9数据线

上图中所示的数据线是带有CH340芯片的,因此当连接到电脑以后就会出现一个COM口,这个COM口就是要使用的COM口。比如在正点原子教程中的电脑上就是COM11,在MobaXterm上新建一个连接,串口为COM11,波特率为115200。

minicom设置

在开发板中输入“minicom -s”,打开minicom配置界面,选中“Serial port setup”,如下图所示:

选中串口设置项

选中“Serial port setup”点击回车,进入设置菜单,如下图所示:

串口设置项

上图中有14个设置项目,分别对应A、B……N,比如第一个是选中串口UART5的串口文件为/dev/ttySTM1(因为设备别名serial1=&UART5),因此串口设置要设置为/dev/ttySTM1。设置方法就是按下键盘上的‘A’,然后输入“/dev/ttySTM1”即可,如下图所示:

串口设置文件设置

设置完以后按下回车键确认,确认完以后就可以设置其他的配置项。比如‘E’设置波特率、数据位和停止位的、‘F’设置硬件流控的,设置方法都一样,设置完以后如下图所示:

UART5设置

都设置完成以后按下回车键确认并退出,这时候会退回到之前的界面,按下ESC键退出配置界面,退出以后如下图所示:

minicom串口界面
上图就是串口调试界面,可以看出当前的串口文件为/dev/ttySTM1,按下CTRL-A,然后再按下Z就可以打开minicom帮助信息界面,如下图所示:

minicom帮助信息界面

从上图可以看出,minicom有很多快捷键,本实验打开minicom的回显功能,回显功能配置项为“local Echo on/off…E”,因此按下E即可打开/关闭回显功能。

RS232收发测试

发送测试

首先测试开发板通过UART5向电脑发送数据的功能,需要打开minicom的回显功能(不打开也可以,但是在minicom中看不到自己输入的内容),回显功能打开以后输入“AAAA”,如下图所示:

通过UART5向电脑发送“AAAA”

上图中的“AAAA”就是开发板通过UART5向电脑发送的数据,那么电脑的COM11就会接收到“AAAA”,MobaXterm中COM11收到的数据如下图所示:

电脑接收到开发板发送的数据

可以看出,开发板通过UART3向电脑发送数据正常,接下来测试开发板数据接收功能。

接收测试

接下来测试开发板的UART5接收功能,同样的,要先打开MobaXterm上COM11的本地回显,正点原子教程里面没有指导该功能,但是开发板是可以接收到在COM11上输入的字符。比如,这里输入‘123456’,此时开发板接收到的数据如下图所示:

开发板接收到发送的数据

UART5收发测试都没有问题,说明UART5驱动工作正常。如果要退出minicom,在minicom通信界面按下CRTL+A,然后按下X来关闭minicom。

RS485测试

前面已经说过了,STM32MP1开发板上的RS485接口连接到了USART3上,因此本质上就是个串口。 RS232实验已经将USART3的驱动编写好了,所以RS485实验就不需要编写任何驱动程序,可以直接使用minicom来进行测试

RS485连接设置

首先是设置JP4跳线帽,将1-3、2-4连接起来, RS485接口如下图所示:

RS485接口设置

一个板子是不能进行RS485通信测试的,还需要另一个RS485设备,比如另外一块STM32MP1开发板。这里可以使用正点原子出品的USB三合一串口转换器,支持USB转TTL、RS232和RS485,如下图所示:

正点原子USB三合一川口转换器

使用杜邦线将USB串口转换器的RS485接口和STM32MP157开发板的RS485连接起来,A接A,B接B,不能接错了!连接完成以后如下图所示:

串口转换器和开发板RS485连接示意图

串口转换器通过USB线连接到电脑上,用的是 CH340版本的,因此就不需要安装驱动,如果使用的是FT232版本的就需要安装相应的驱动。连接成功以后电脑就会有相应的COM口,比如教程中电脑上就是COM6,接下来就是测试。

RS485收发测试

RS485的测试和RS232一模一样!电脑上USB多合一转换器对应COM12。因为MobaXterm没有找到回显设置,因此这里为了方便观察,USB多合一转换器使用SecureCRT这个终端软件。使用SecureCRT创建一个COM12的连接,开发板使用USART3,对应的串口设备文件为/dev/ttySTM2,因此开发板使用minicom创建一个/dev/ttySTM2的串口连接。串口波特率都选择115200 8位数据位,1位停止位,关闭硬件和软件流控

RS485发送测试

首先测试开发板通过RS485发送数据,设置好minicom以后,同样输入“AAAA”,也就是通过RS485向电脑发送一串“AAAA”。如果RS485驱动工作正常的话,那么电脑就会介绍到开发板发送过来的“AAAA”,如下图所示:

RS485数据发送测试

从上图可以看出开发板通过RS485向电脑发送“AAAA”成功,说明RS485数据发送正常。

RS485接收测试

接下来测试一下RS485数据接收,电脑通过RS485向开发板发送“BBBB”,然后观察minicom是否能接收到“BBBB”。结果如下图所示:

RS485数据接收测试

从上图中可以看出开发板接收到电脑通过RS485发送过来的“BBBB”,说明RS485数据接收正常。

GPS测试

GPS连接设置

GPS模块大多数都是串口输出的,这里以正点原子出品的ATK118-BD模块为例,这是一款GSP+北斗的定位模块,如下图所示:

正点原子ATK1218-BD定位模块

首先要设置STM32MP1开发板上的JP5跳线帽,将UART5与ATK模块接口上的串口连接起来,如下图所示:

UART5跳线帽连到GPS

此时UART5_TX和UART5_RX已经连接到了开发板上的ATK MODULE上,直接将ATK1218-BD模块插到开发板上的ATK MODULE接口即可,开发板上的ATK MODULE接口是6脚的,而 ATK1218-BD模块是5脚的,因此需要靠下插(VCC对应 5V)!然后GPS需要接上天线,天线的接收头一定要放到户外,因此室内一般是没有GPS信号的。连接完成以后如下图所示:

GPS模块连接示意图

GPS数据接收测试

GPS都是被动接收定位数据的,模块接收定位卫星数据,然后计算出位置信息通过串口输出。所以要先设置minicom,UART5对应/dev/ttySTM1,串口设置要求如下:

  1. 波特率设置为38400,因为正点原子的ATK1218-BD模块默认波特率就是38400。
  2. 8位数据位,1位停止位。
  3. 关闭硬件和软件流控。

设置好以后如下图所示:

串口设置

设置好以后就可以静静的等待GPS数据输出,GPS模块第一次启动可能需要几分钟搜星,
等搜到卫星以后才会有定位数据输出。搜到卫星以后GPS模块输出的定位数据如下图所示:

GPS数据

总结

这一篇实验,其实就是对于STM32MP157开发板的串口的使用,这里驱动也是ST官方已经写好的,我们需要做的就是直接在pinctrl加节点写好GPIO的复用,然后在设备树里面添加对应的串口节点,并关联上pinctrl。还有就是在buildroot里面要配置一下minicom这个串口调试,方便测试串口。

之后的测试,RS485个人觉得可以关注一下,至于RS232可以看到其实现在用的已经很少了,就直接都是RS232转串口就可以了,比如精英板就是串口直接Type-C了,不会再用RS232。


http://www.ppmy.cn/news/1183649.html

相关文章

Java之数据类型与变量

目录 1. 字面常量 2. 数据类型 3. 变量 3.1 变量概念 3.2 语法格式 3.3 整型变量 3.3.1 整型变量 3.3.2 长整型变量 3.3.3 短整型变量 3.3.4 字节型变量 3.4 浮点型变量 3.4.1 双精度浮点型 3.4.2 单精度浮点型 3.5 字符型变量 3.6 布尔型变量 3.7 类型转换 3.7…

中微爱芯74逻辑兼容替代TI/ON/NXP工规品质型号全

这里写自定义目录标题 工业级型号全产品线概述![在这里插入图片描述](https://img-blog.csdnimg.cn/097ef810b2234f07b0c0c1e962a73761.png)批量应用行业头部客户兼容替代封装对照逻辑参数对比电平转换系列型号对照HC/HCT 系列型号对照AHC/AHCT 系列型号对照LV/LVC 系列型号对照…

Linux下protobuf和 protobuf-c安装使用

如果在 C语言中使用 protobuf&#xff0c;就需要使用 protobuf-c这个库。 protobuf使用详解&#xff1a;https://blog.csdn.net/qq_42402854/article/details/134066566 下面在 Linux下安装 protobuf和 protobuf-c。 一、下载 protobuf和 protobuf-c 官方的 Protocol Buffer提…

电脑有自带的录屏功能吗win7

win7有自带的录屏软件&#xff0c;名字叫“问题步骤记录器”&#xff0c;可以实现将每一步操作截成图片&#xff0c;并自动配以相关文字说明的功能。打开记录器的方法&#xff1a;1、按“WinR”键&#xff0c;打开“运行”窗口&#xff1b;2、在“运行”窗口中&#xff0c;输入…

带有 Vagrant 和 Virtualbox 的 Elasticsearch 集群

模拟分布式存储和计算环境的一种简单方法是使用 Virtualbox 作为 VM&#xff08;“虚拟机”&#xff09;的提供者&#xff0c;使用 Vagrant 作为前端脚本引擎来配置、启动和停止这些 VM。这篇文章的目标是构建一个集群虚拟设备&#xff0c;提供 Elasticsearch 作为可由主机使用…

java基础 特殊文件

1.Properties属性文件&#xff1a; 1.1使用Properties读取属性文件里的键值对数据&#xff1a; package specialFile;import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.util.Enumeration; import java.util.Propert…

同一个页面同一区域两个el-table在v-if下样式重叠问题

&#x1f349;正常情况下在radio切换时两个表格的样式应如下 &#x1f349;实际上用v-if显示时会出现以下问题&#xff08;本该属于时间段相同模块的表格却出现在时间段自定义的表格中&#xff09; &#x1f349;解决方案&#xff1a; &#x1f343;一、将v-if替换成v-show(…

设备的分配与回收(考虑因素,数据结构,分配步骤)

目录 1.设备分配时应考虑的因素1.设备的固有属性2.设备分配算法3.设备分配中的安全性1.安全分配方式2.不安全分配方式 2.静态分配与动态分配3.设备分配管理中的数据结构1.“设备、控制器、通道”之间的关系2.设备控制表&#xff08;DCT)3.控制器控制表(COCT)4.通道控制表&#…