dede小说网站模板下载/购物网站
串口是很常用的一个外设,在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_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中最主要的就是第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对应的子节点,子节点内容如下所示:
重点看一下第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定义如下:
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结构体内容如下所示(有
缩减):
第258行,uart_port结构体成员变量:port。
第279行,这里定义了一个数组为stm32_ports,数组的类型为stm32_port结构体,数组的长度为8。这是因为STM32MP157最多只有8个串口,一个串口对应一个stm32_port,因此数组长度就是8。
接下来看一下stm32_usart_serial_probe函数,函数内容如下:
第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函数源码如下:
第1197行,通过of_alias_get_id函数从设备树的aliases节点中获取“serial”相关的ID。打开stm32mp157d-atk.dts文件,当前此文件里面的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函数主要是负责获取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中的函数基本都是和STM32MP1的UART寄存器打交道的,这里就不去详细的分析了。简单的了解了STM32MP1的UART驱动以后再来学习一下,如何驱动正点原子STM32MP1开发板上的USART3接口和UART5接口。
硬件原理图分析
本实验要用到的STM32MP1的USART3接口和UART5接口,USART3连接RS485和RS232的公头,UART5连接GPS和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采用SP3485这颗芯片来实现,RO为数据输出端,RI为数据输入端,RE是接收使能信号(低电平有效),DE是发送使能信号(高电平有效)。在上图中RE和DE经过一系列的电路,最终通过RS485_RX来控制,这样可以省掉一个RS485收发控制IO,将RS485完全当作一个串口来使用,方便写驱动。
GPS原理图
正点原子有一款GPS+北斗定位模块,型号为ATK1218-BD,STM32MP157开发板留出了这款GPS定位模块的接口,接口原理图如下图所示:
前面讲解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 |
配置如下图所示:
保存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版本号为2.7.90,minicom版本号查看正常。输入如下命令打开minicom配置界面:
minicom -s |
此时minicom配置界面就可以打开了,如下图所示:
如果出现如上图所示的界面,那么minicom就已经能够正常工作了。
RS232驱动测试
RS232连接设置
在测试之前要先将STM32MP1开发板的RS232接口与电脑连接起来,正点原子STM32MP1开发板上两个RS232接口如下图所示:
从上图中可以看出,正点原子开发板上有2个 RS232接口。这里要注意的是这两个RS232接口一个为公头,一个为母头,方便外接自己的设备。上图中左边的COM2为公头,可以通过JP4跳接到USART3上。右边的COM1为母头,可以通过JP5跳接到UART5上。本实验使用右边的COM1,所以需要将JP5的两个跳线帽接到上方,也就是将UART5与COM1连接起来。
跳线帽设置好以后使用RS232线将开发板与电脑连接起来,这里建议使用USB转DB9(RS232)数据线,比如正点原子的CH340方案的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’设置硬件流控的,设置方法都一样,设置完以后如下图所示:
都设置完成以后按下回车键确认并退出,这时候会退回到之前的界面,按下ESC键退出配置界面,退出以后如下图所示:
上图就是串口调试界面,可以看出当前的串口文件为/dev/ttySTM1,按下CTRL-A,然后再按下Z就可以打开minicom帮助信息界面,如下图所示:
从上图可以看出,minicom有很多快捷键,本实验打开minicom的回显功能,回显功能配置项为“local Echo on/off…E”,因此按下E即可打开/关闭回显功能。
RS232收发测试
发送测试
首先测试开发板通过UART5向电脑发送数据的功能,需要打开minicom的回显功能(不打开也可以,但是在minicom中看不到自己输入的内容),回显功能打开以后输入“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设备,比如另外一块STM32MP1开发板。这里可以使用正点原子出品的USB三合一串口转换器,支持USB转TTL、RS232和RS485,如下图所示:
使用杜邦线将USB串口转换器的RS485接口和STM32MP157开发板的RS485连接起来,A接A,B接B,不能接错了!连接完成以后如下图所示:
串口转换器通过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向电脑发送“AAAA”成功,说明RS485数据发送正常。
RS485接收测试
接下来测试一下RS485数据接收,电脑通过RS485向开发板发送“BBBB”,然后观察minicom是否能接收到“BBBB”。结果如下图所示:
从上图中可以看出开发板接收到电脑通过RS485发送过来的“BBBB”,说明RS485数据接收正常。
GPS测试
GPS连接设置
GPS模块大多数都是串口输出的,这里以正点原子出品的ATK118-BD模块为例,这是一款GSP+北斗的定位模块,如下图所示:
首先要设置STM32MP1开发板上的JP5跳线帽,将UART5与ATK模块接口上的串口连接起来,如下图所示:
此时UART5_TX和UART5_RX已经连接到了开发板上的ATK MODULE上,直接将ATK1218-BD模块插到开发板上的ATK MODULE接口即可,开发板上的ATK MODULE接口是6脚的,而 ATK1218-BD模块是5脚的,因此需要靠下插(VCC对应 5V)!然后GPS需要接上天线,天线的接收头一定要放到户外,因此室内一般是没有GPS信号的。连接完成以后如下图所示:
GPS数据接收测试
GPS都是被动接收定位数据的,模块接收定位卫星数据,然后计算出位置信息通过串口输出。所以要先设置minicom,UART5对应/dev/ttySTM1,串口设置要求如下:
- 波特率设置为38400,因为正点原子的ATK1218-BD模块默认波特率就是38400。
- 8位数据位,1位停止位。
- 关闭硬件和软件流控。
设置好以后如下图所示:
设置好以后就可以静静的等待GPS数据输出,GPS模块第一次启动可能需要几分钟搜星,
等搜到卫星以后才会有定位数据输出。搜到卫星以后GPS模块输出的定位数据如下图所示:
总结
这一篇实验,其实就是对于STM32MP157开发板的串口的使用,这里驱动也是ST官方已经写好的,我们需要做的就是直接在pinctrl加节点写好GPIO的复用,然后在设备树里面添加对应的串口节点,并关联上pinctrl。还有就是在buildroot里面要配置一下minicom这个串口调试,方便测试串口。
之后的测试,RS485个人觉得可以关注一下,至于RS232可以看到其实现在用的已经很少了,就直接都是RS232转串口就可以了,比如精英板就是串口直接Type-C了,不会再用RS232。
相关文章:

正点原子嵌入式linux驱动开发——Linux 串口RS232/485/GPS 驱动
串口是很常用的一个外设,在Linux下通常通过串口和其他设备或传感器进行通信,根据 电平的不同,串口分为TTL和RS232。不管是什么样的接口电平,其驱动程序都是一样的,通过外接RS485这样的芯片就可以将串口转换为RS485信号…...

HDFS工作流程和机制
HDFS写数据流程(上传文件) 核心概念--Pipeline管道 HDFS在上传文件写数据过程中采用的一种传输方式。 线性传输:客户端将数据写入第一个数据节点,第一个数据节点保存数据之后再将快复制到第二个节点,第二节点复制给…...

CMMI/ASPICE认证咨询及工具服务
服务概述 质量专家戴明博士的名言“如果你不能描述做事情的过程,那么你不知道你在做什么”。过程是连接有能力的工程师和先进技术的纽带,因此产品开发过程直接决定了产品的质量和研发的效率。 经纬恒润可结合多体系要求,如IATF16949\ISO26262…...

【NI-DAQmx入门】计数器
1.计数器的作用 NI产品的计数器一般来说兼容TTL信号,定义如下:0-0.8V为逻辑低电平,2~5V为高电平,0.8-2V为高阻态,最大上升下降时间为50ns。 计数器可以感测上升沿(从逻辑低到逻辑高的转变)和下降…...

Python爬取读书网的图片链接和书名并保存在数据库中
一个比较基础且常见的爬虫,写下来用于记录和巩固相关知识。 一、前置条件 本项目采用scrapy框架进行爬取,需要提前安装 pip install scrapy# 国内镜像 pip install scrapy -i https://pypi.douban.com/simple 由于需要保存数据到数据库,因…...

js解决加油站
在一条环路上有 n 个加油站,其中第 i 个加油站有汽油 gas[i] 升。 你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发,开始时油箱为空。 给定两个整数数组 gas 和 cost &…...

【c++|opencv】二、灰度变换和空间滤波---5.中值滤波
every blog every motto: You can do more than you think. https://blog.csdn.net/weixin_39190382?typeblog 0. 前言 1. 中值滤波 #include<iostream> #include<opencv2/opencv.hpp> #include"Salt.h"using namespace cv; using namespace std;voi…...

python之pytorch多进程
目录 1、创建并运行并行进程 2、使用队列(Queue)来共享数据 3、进程池 4、进程锁 5、比较使用多进程和使用单进程执行一段代码的时间消耗 6、共享变量 多进程是计算机科学中的一个术语,它是指同时运行多个进程,这些进程可以…...

sqoop 抽数报错com.mysql.cj.exceptions.WrongArgumentException: HOUR_OF_DAY: 2 -> 3
文章目录 1.sqoop 抽数报错: Caused by: com.mysql.cj.exceptions.WrongArgumentException: HOUR_OF_DAY: 2 -> 3 at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructor…...

【Acwing170】加成序列(dfs+迭代加深+剪枝)题解和一点感想
本思路来自acwing算法提高课 题目描述 看本文需要准备的知识 1.dfs算法基本思想 2.对剪枝这个词有个简单的认识 迭代加深思想和此题分析 首先,什么是迭代加深呢?当一个问题的解有很大概率出现在递归树很浅的层,但是这个问题的解本身存在…...

Android开发知识学习——Kotlin进阶
文章目录 次级构造主构造器init 代码块构造属性data class相等性解构Elvis 操作符when 操作符operatorLambdainfix 函数嵌套函数注解使用处目标函数简化函数参数默认值扩展函数类型内联函数部分禁用用内联具体化的类型参数抽象属性委托属性委托类委托 Kotlin 标准函数课后题 次…...

iOS使用AVCaptureSession实现音视频采集
AVCaptureSession配置采集行为并协调从输入设备到采集输出的数据流。要执行实时音视频采集,需要实例化采集会话并添加适当的输入和输出。 AVCaptureSession:管理输入输出音视频流AVCaptureDevice:相机硬件的接口,用于控制硬件特性…...

springboot和flask整合nacos,使用openfeign实现服务调用,使用gateway实现网关的搭建(附带jwt续约的实现)
环境准备: 插件版本jdk21springboot 3.0.11 springcloud 2022.0.4 springcloudalibaba 2022.0.0.0 nacos2.2.3(稳定版)python3.8 nacos部署(docker) 先创建目录,分别创建config,logs…...
深入浅出排序算法之基数排序
目录 1. 前言 1.1 什么是基数排序⭐⭐⭐ 1.2 执行流程⭐⭐⭐⭐⭐ 2. 代码实现⭐⭐⭐ 3. 性能分析⭐⭐ 3.1 时间复杂度 3.2 空间复杂度 1. 前言 一个算法,只有理解算法的思路才是真正地认识该算法,不能单纯记住某个算法的实现代码! 1.…...

CSS选择器、CSS属性相关
CSS选择器 CSS属性选择器 通过标签的属性来查找标签,标签都有属性 <div class"c1" id"d1"></div>id值和class值是每个标签都自带的属性,还有另外一种:自定义属性 <div class"c1" id"d1&…...

设计模式(21)中介者模式
一、介绍: 1、定义:中介者模式(Mediator Pattern)是一种行为型设计模式,它通过引入一个中介者对象来降低多个对象之间的耦合度。在中介者模式中,各个对象之间不直接进行通信,而是通过中介者对象…...

JVM虚拟机:通过一个例子解释JVM中栈结构的使用
代码 代码解析 main方法执行,创建栈帧并压栈。 int d8,d为局部变量,是基础类型,它位于虚拟机栈的局部变量表中 然后创建了一个TestDemo的对象,这个对象在堆中,并且这个对象的成员变量(day&am…...

会自动写代码的AI大模型来了!阿里云推出智能编码助手通义灵码
用大模型写代码是什么样的体验?10月31日,杭州云栖大会上,阿里云对外展示了一款可自动编写代码的 AI 助手,在编码软件的对话窗口输入“帮我用 python 写一个飞机游戏”,短短几秒,这款名为“通义灵码”的 AI …...

如何公网远程访问本地WebSocket服务端
本地websocket服务端暴露至公网访问【cpolar内网穿透】 文章目录 本地websocket服务端暴露至公网访问【cpolar内网穿透】1. Java 服务端demo环境2. 在pom文件引入第三包封装的netty框架maven坐标3. 创建服务端,以接口模式调用,方便外部调用4. 启动服务,出现以下信息表示启动成功…...

python 练习 在列表元素中合适的位置插入 输入值
目的: 有一列从小到大排好的数字元素列表, 现在想往其插入一个值,要求: 大于右边数字小于左边数字 列表元素: [1,4,6,13,16,19,28,40,100] # 方法: 往列表中添加一个数值,其目的方便元素位置往后…...

企业级JAVA、数据库等编程规范之命名风格 —— 超详细准确无误
🧸欢迎来到dream_ready的博客,📜相信你对这两篇博客也感兴趣o (ˉ▽ˉ;) 📜 表白墙/留言墙 —— 初级SpringBoot项目,练手项目前后端开发(带完整源码) 全方位全步骤手把手教学 📜 用户登录前后端…...

有什么可以自动保存微信收到的图片和视频的方法么
8-1 在一些有外勤工作的公司里,经常会需要在外面工作的同事把工作情况的图片发到指定微信或者指定的微信群里,以记录工作进展等,或者打卡等,对于外勤人员来说,也就发个图片的事,但是对于在公司里收图片的人…...

面试算法46:二叉树的右侧视图
题目 给定一棵二叉树,如果站在该二叉树的右侧,那么从上到下看到的节点构成二叉树的右侧视图。例如,图7.6中二叉树的右侧视图包含节点8、节点10和节点7。请写一个函数返回二叉树的右侧视图节点的值。 分析 既然这个题目和二叉树的层相关&a…...

R语言使用surveyCV包对NHANES数据(复杂调查加权数据)进行10折交叉验证
美国国家健康与营养调查( NHANES, National Health and Nutrition Examination Survey)是一项基于人群的横断面调查,旨在收集有关美国家庭人口健康和营养的信息。 地址为:https://wwwn.cdc.gov/nchs/nhanes/Default.aspx 既往咱们…...

WOS与CNKI数据库的citespace分析教程及常见问题解决
本教程为面向新手的基于citespace的数据可视化教程,旨在帮助大家更快了解行业前沿的研究内容。 获取最新版本的citespace软件 在citespace官网下载最新的版本(如果是老版本,可能会提示让你去官网更新为最新版,老版本不再提供服务…...

NEFU数字图像处理(三)图像分割
一、图像分割的基本概念 1.1专有名词 前景和背景 在图像分割中,我们通常需要将图像分为前景和背景两个部分。前景是指图像中我们感兴趣、要分割出来的部分,背景是指和前景不相关的部分。例如,对于一张人物照片,人物就是前景&…...

UEditorPlus v3.6.0 图标补全,精简代码,快捷操作重构,问题修复
UEditor是由百度开发的所见即所得的开源富文本编辑器,基于MIT开源协议,该富文本编辑器帮助不少网站开发者解决富文本编辑器的难点。 UEditorPlus 是有 ModStart 团队基于 UEditor 二次开发的富文本编辑器,主要做了样式的定制,更符…...

C++ Set
定义 set不同于vector,strin,list这种存储容器,set是一种关联式容器,底层是搜二叉; 功能 set可以确定唯一的值,可以排序去重。 接口 insert() #include <iostream> #include<set> using namespace std;int main…...

基于知识库的chatbot或者FAQ
背景 最近突然想做一个基于自己的知识库(knowlegebase)的chatbot或者FAQ的项目。未来如果可以在公司用chatgpt或者gpt3.5之后的模型的话,还可以利用gpt强大的语言理解力和搜索出来的用户问题的相关业务文档来回答用户在业务中的问题。 Chat…...