【迅为电子】RK3568驱动指南|第十七篇 串口-第202章 串口编程

news2024/9/20 14:30:15

瑞芯微RK3568芯片是一款定位中高端的通用型SOC,采用22nm制程工艺,搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码,支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU,可用于轻量级人工智能应用。RK3568 支持安卓 11 和 linux 系统,主要面向物联网网关、NVR 存储、工控平板、工业检测、工控盒、卡拉 OK、云终端、车载中控等行业。


【公众号】迅为电子

【粉丝群】258811263(加群获取驱动文档+例程)

【视频观看】嵌入式学习之Linux驱动(第十七篇 串口_全新升级)_基于RK3568

【购买链接】迅为RK3568开发板瑞芯微Linux安卓鸿蒙ARM核心板人工智能AI主板


第202章 串口编程

为了控制串口通信,我们需要进行串口编程。在Linux系统中,可以使用文件I/O操作和ioctl操作来进行串口编程。文件I/O操作可以用于读取和写入串口数据,ioctl操作可以用于设置串口参数、控制流控制和获取串口状态等操作

202.1串口设备节点介绍 

在嵌入式设备中,串口设备通常以字符设备节点的形式出现在Linux系统中。在Linux系统中,每个设备都由一个设备节点(device node)来表示,设备节点是与设备相关联的一个文件,以/dev目录下的文件形式存在。

串口设备节点通常以tty开头,具体命名方式根据串口的类型和数量不同而不同。开发板系统启动之后,使用以下命令打印终端设备节点,如下图所示:

ls /dev/tty*

dev/ttyX(X 是一个数字编号,譬如 0、1、2、3 等)设备节点:tty是teletype 的简称,在 Linux 中,/dev/ttyX 代表的都是本地终端, Linux 内核在初始化时所生成的 63 个本地终端,包括/dev/tty1~/dev/tty63 一共63 个本地终端,可以是连接到开发板的LCD 显示器、键盘和鼠标等。

串口终端设备节点:从开发板原理图可以了解到,在iTOP-3568开发板上有四个串口,分别UART2、UART4、UART7、UART9,其中UART2为串口调试终端,对应的设备节点为/dev/ttyFIQ0,其他三个串口UART4、UART7、UART9分别对应/dev/ttyS4、/dev/ttyS7、/dev/ttyS9。

基于USB的虚拟串口:ttyGS0以及ttyUSBX(X 是一个数字编号,譬如 0、1、2、3 等)都是USB的虚拟串口,其中ttyGS0为烧写usb虚拟出的串口,在系统启动之后可以在windows终端通过“adb shell”命令进入开发板控制台。ttyUSBX在这里为4G模块的虚拟串口。

202.2 struct termios结构体

struct termios 是 Linux 内核中用于描述终端设备(包括串口设备)参数的结构体。它定义在 <linux/termios.h> 头文件中,包含了多个字段,用于配置和管理终端设备的属性和行为,包括了输入输出波特率、数据位、校验位、停止位等。其定义如下:

struct termios {
    tcflag_t c_iflag;  // 输入模式标志
    tcflag_t c_oflag;  // 输出模式标志
    tcflag_t c_cflag;  // 控制模式标志
    tcflag_t c_lflag;  // 本地模式标志
    cc_t c_cc[NCCS];   // 控制字符数组
};

下面是 struct termios 结构体的一些重要字段:

  • tcflag_t c_iflag:该字段包含了输入模式标志,用于配置终端设备的输入行为,如输入控制字符、输入数据处理等。
  • tcflag_t c_oflag:该字段包含了输出模式标志,用于配置终端设备的输出行为,如输出数据处理、输出控制字符等。
  • tcflag_t c_cflag:该字段包含了控制模式标志,用于配置终端设备的控制参数,如波特率、数据位数、停止位数、校验位等。
  • tcflag_t c_lflag:该字段包含了本地模式标志,用于配置终端设备的本地操作以及输入输出行为。
  • cc_t c_cc[NCCS]:该字段包含了特殊控制字符数组,用于配置终端设备的控制字符,如终端的擦除字符、结束字符、停止字符等。

 

202.2.1 输入模式

在这个结构体中,最重要的c_cflag,可以控制模式控制终端设备的硬件特性,譬如对于串口来说,该字段比较重要,可设置串口波特率、数据位、校验位、停止位等硬件特性。通过设置 struct termios 结构中 c_cflag 成员的标志对控制模式进行配置。可用于 c_cflag 成员的标志如下所示:

成员

对应成员的含义

IGNBRK

忽略输入终止条件

BRKINT

当检测到输入终止条件时发送 SIGINT 信号

IGNPAR

忽略帧错误和奇偶校验错误

PARMRK

对奇偶校验错误做出标记

INPCK

对接收到的数据执行奇偶校验

ISTRIP

将所有接收到的数据裁剪为 7 比特位、也就是去除第八位

INLCR

将接收到的 NL(换行符)转换为 CR(回车符)

IGNCR

忽略接收到的 CR(回车符)

ICRNL

将接收到的 CR(回车符)转换为 NL(换行符)

IUCLC

将接收到的大写字符映射为小写字符

IXON

启动输出软件流控

202.2.2 输出模式

输出模式控制输出字符的处理方式,即由应用程序发送出去的字符数据在传递到串口或屏幕之前是如何处理的。可用于 c_oflag 成员的宏如下所示:

成员

对应成员的含义

OPOST

启用输出处理功能,如果不设置该标志则其他标志都被忽略

OLCUC

将输出字符中的大写字符转换成小写字符

ONLCR

将输出中的换行符(NL '\n')转换成回车符(CR '\r')

OCRNL

将输出中的回车符(CR '\r')转换成换行符(NL '\n')

ONOCR

在第 0 列不输出回车符(CR

ONLRET

不输出回车符

OFILL

发送填充字符以提供延时

OFDEL

如果设置该标志,则表示填充字符为 DEL 字符,否则为 NULL字符

 

202.2.3 控制模式

在这个结构体中,最终要的就是c_cflag ,可以控制模式控制终端设备的硬件特性,譬如对于串口来说,该字段比较重要,可设置串口波特率、数据位、校验位、停止位等硬件特性。通过设置 struct termios 结构中 c_cflag 成员的标志对控制模式进行配置。可用于 c_cflag 成员的标志如下所示:

c_cflag支持的常量名称

CBAUD

波特率的位掩码

B0

0波特率(放弃DTR)

B1800

1800波特率

B2400

2400波特率

B4800

4800波特率

B9600

9600波特率

B19200

19200波特率

B38400

38400波特率

B57600

57600波特率

B115200

115200波特率

CSIZE

数据位的位掩码

CS5

5个数据位

CS6

6个数据位

CS7

7个数据位

CS8

8个数据位

CSTOPB

2个停止位(不设则是1个停止位)

CREAD

接收使能

PARENB

校验位使能

PARODD

使用奇校验而不使用偶校验

HUPCL

最后关闭时挂线(放弃DTR)

CLOCAL

本地连接(不改变端口所有者)

LOBLK

块作业控制输出

CNET_CTSRTS

硬件流控制使能

202.2.4 本地模式

本地模式用于控制终端的本地数据处理和工作模式。通过设置 struct termios 结构体中 c_lflag 成员的标 志对本地模式进行配置。可用于 c_lflag 成员的标志如下所示:

c_iflag支持的常量名称

INPCK

奇偶校验使能

IGNPAR

忽略奇偶校验错误

PARMRK

奇偶校验错误掩码

ISTRIP

除去奇偶校验位

IXON

启动出口硬件流控

IXOFF

启动入口软件流控

IXANY

允许字符重新启动流控

IGNBRK

忽略中断情况

BRKINT

当发生中断时发送SIGINT信号

INLCR

将NL映射到CR

IGNCR

忽略CR

ICRNL

将CR映射到NL

ICANON

启用规范模式

202.2.5 特殊控制字符

特殊控制字符是一些字符组合,如 Ctrl+C、Ctrl+Z 等,当用户键入这样的组合键,终端会采取特殊处理方式。struct termios 结构体中 c_cc 数组将各种特殊字符映射到对应的支持函数。每个字符位置(数组下标)由对应的宏定义的,如下所示

c_cc 支持的常量名称

VKILL

删除行,对应键为CTRL+U

VEOF

位于文件结尾,对应键为CTRL+D

VEOL

 位于行尾,对应键为Carriage return(CR)

VEOL2

 位于第二行尾,对应键为Line feed(LF)

VMIN

指定了最少读取的字符数

VTIME

指定了读取每个字符的等待时间

VINTR

中断控制,对应键为CTRL+C

VQUIT

退出操作,对应键为CRTL+Z

VERASE

删除操作,对应键为Backspace(BS)

在以上所列举的这些宏定义中,TIME 和 MIN 值只能用于非规范模式,可用于控制非规范模式下 read()调用的一些行为特性,后面再向大家介绍。

202.2 常用串口控制函数

串口控制函数是用于管理和控制串口设备的函数,在 Linux 系统中主要通过 ioctl() 系统调用来实现。以下是一些常用的串口控制函数及其功能:

202.2.1 tcgetattr()函数

tcgetattr():该函数用于获取终端设备的属性,包括输入模式、输出模式、控制模式和本地模式等。通过该函数可以获取当前串口设备的配置参数。

tcsetattr() 函数是在 Linux 中用于设置终端设备的属性的函数,通常用于对串口设备的参数进行配置。该函数的原型如下:

int tcsetattr(int fd, int optional_actions, const struct termios *termios_p);

其中,参数说明如下:

fd:是指向打开的串口设备文件描述符的指针,用于标识要进行属性设置的串口设备。

optional_actions:表示对属性的设置动作,可以选择以下几个值:

  • TCSANOW:立即改变属性。
  • TCSADRAIN:等待输出完成后改变属性。
  • TCSAFLUSH:清空输入和输出缓冲区,然后改变属性。

termios_p:是一个指向 struct termios 结构体的指针,包含了要设置的终端属性。struct termios 结构体中包含了串口的配置参数,如波特率、数据位、停止位、校验位、流控制等。

202.2.2 tcsetattr()函数

tcsetattr() 函数是 Linux 系统中用于设置终端设备属性的函数,常用于配置串口设备的参数。该函数的声明如下:

int tcsetattr(int fd, int optional_actions, const struct termios *termios_p);

参数解释:

fd:是指向已打开串口设备的文件描述符的指针,用于指定要设置属性的串口设备。

optional_actions:表示属性设置的动作选项,可以是以下值之一:

  • TCSANOW:立即改变属性。
  • TCSADRAIN:等待输出缓冲区数据发送完毕后再改变属性。
  • TCSAFLUSH:清空输入输出缓冲区后再改变属性。

termios_p:是一个指向 struct termios 结构体的指针,包含了要设置的终端属性,包括波特率、数据位、停止位、校验位、流控制等。

通过调用 tcsetattr() 函数,可以实现对串口设备参数的灵活配置。常见的终端属性设置包括:

  • 设置波特率:通过在 termios_p 结构体中设置正确的输入和输出波特率来指定串口通信的速率。
  • 设置数据位、停止位和校验位:通过在 termios_p 结构体中设置正确的数据位、停止位和校验位来匹配串口设备的配置。
  • 配置流控制:通过设置硬件流控制和软件流控制来控制串口数据的流动。

在调用 tcsetattr() 函数时,需要注意指定合适的 optional_actions 参数,以确保属性设置的动作符合需求。正确地配置串口设备的属性可以保障数据通信的成功和稳定。

202.2.4 cfgetispeed()和cfgetospeed()函数

在 Linux 系统中,没有标准的 cfgetispeed() 和 cfgetospeed() 函数。这两个函数通常是在类 Unix 系统中的 <termios.h> 头文件中定义。它们的作用是用于获取终端设备的输入和输出波特率。这两个函数的功能介绍如下:

cfgetispeed(const struct termios *termios_p)

该函数用于获取终端设备的输入波特率。

参数 termios_p 是一个指向 struct termios 结构体的指针,包含了终端设备的属性信息。

返回值为表示输入波特率的整数值(波特率常用的单位是波特/秒)。

cfgetospeed(const struct termios *termios_p)

该函数用于获取终端设备的输出波特率。

参数 termios_p 是一个指向 struct termios 结构体的指针,包含了终端设备的属性信息。

返回值为表示输出波特率的整数值。

这两个函数用于从终端属性结构体中提取输入和输出波特率的值,以便应用程序可以了解当前终端设备的波特率设置。在使用这两个函数时,需要注意传入正确的 struct termios 结构体指针,以确保获取准确的波特率信息。

在 Linux 系统中,获取终端设备的波特率信息通常通过其他方式实现,如结合使用 tcgetattr() 函数获取终端属性结构体,并从中提取波特率信息。

202.2.3 cfsetispeed()和cfsetospeed()函数

cfsetispeed() 和 cfsetospeed():这两个函数分别用于设置输入波特率和输出波特率。可以通过这两个函数来指定串口设备的通信速率。

cfsetispeed()函数的作用如下:

cfsetispeed(struct termios *termios_p, speed_t speed):

该函数用于设置终端设备的输入波特率。

参数 termios_p 是指向 struct termios 结构体的指针,包含了终端设备的属性信息。

参数 speed 是指定的输入波特率值。

通过调用 cfsetispeed() 函数可以将输入波特率设置为指定的值,以指定串口设备接收数据的速率。

cfsetospeed()函数的作用如下:

cfsetospeed(struct termios *termios_p, speed_t speed):

该函数用于设置终端设备的输出波特率。

参数 termios_p 是指向 struct termios 结构体的指针,包含了终端设备的属性信息。

参数 speed 是指定的输出波特率值。

通过调用 cfsetospeed() 函数可以将输出波特率设置为指定的值,以指定串口设备发送数据的速率。

这两个函数通常与 struct termios 结构体一起使用,通过设置输入和输出波特率来配置串口设备的通信速率。正确地设置输入和输出波特率可以确保串口通信双方的数据传输速率匹配,从而实现稳定的数据交换。

202.2.4 tcflush()和tcflow()函数

tcflush() 和 tcflow() 函数是用于控制终端设备输入输出数据流的函数,常用于串口设备的操作。以下是详细介绍:

tcflush(int fd, int queue_selector)

该函数用于刷新终端设备的输入输出缓冲区。

参数 fd 是指向已打开的终端设备文件描述符的指针,用于标识要操作的终端设备。

参数 queue_selector 是刷新缓冲区的方式,可以是以下值之一:

  1. TCIFLUSH:刷新输入缓冲区,丢弃未读取的数据。
  2. TCOFLUSH:刷新输出缓冲区,丢弃未发送的数据。
  3. TCIOFLUSH:同时刷新输入输出缓冲区。

通过 tcflush() 函数可以根据需求清空终端设备的输入缓冲区、输出缓冲区或同时清空两者。

tcflow(int fd, int action)

该函数用于控制数据流的暂停和恢复。

参数 fd 是指向已打开的终端设备文件描述符的指针,用于标识要操作的终端设备。

参数 action 可以指定以下值之一:

  • TCOOFF:暂停数据的传输,停止发送数据。
  • TCOON:恢复数据的传输,继续发送数据。
  • TCIOFF:暂停数据的传输,停止接收数据。
  • TCION:恢复数据的传输,继续接收数据。

tcflush() 和 tcflow() 函数通常在串口通信中用于控制和管理数据的流动。tcflush() 可以清空缓冲区中的数据,而 tcflow() 可以控制数据的流动状态,暂停或恢复数据的传输。正确使用这两个函数有助于确保串口通信操作的稳定性和准确性。

202.3 串口操作流程

202.3.1设置串口的波特率 

在编写串口应用程序时,设置串口波特率是必须的步骤之一,它决定了数据传输的速率。在 Linux 中,设置波特率通常使用 cfsetspeed() 函数,cfsetspeed()函数所需头文件和函数原型如下所示:

所需头文件

函数原型

#include <termios.h>

#include <unistd.h>

int cfsetspeed(struct termios *termios_p, speed_t speed);

它接受一个 struct termios 结构体作为输入参数,同时返回一个整数值,表示操作是否成功。该函数实际上是对 c_cflag 字段中的波特率进行设置。例如,如果要将波特率设置为 115200,可以调用以下代码: 

struct termios options;
// 获取当前终端配置
tcgetattr(fd, &options);

// 设置波特率为 115200
cfsetspeed(&options, B115200);

// 将新的终端配置写入终端
tcsetattr(fd, TCSANOW, &options);

需要注意以下几点:

(1)需要先打开串口设备文件并且获取串口的属性,包括波特率在内的其他属性。可以使用 tcgetattr() 函数获取属性值,并存储在一个 termios 结构体变量中。

(2)设置波特率时需要调用 cfsetspeed() 函数,并传入一个波特率常量作为参数。常用的波特率常量包括 B9600、B115200 等。这些常量可以在头文件 termios.h 中找到。

(3)设置完成后,需要使用 tcsetattr() 函数将属性值写回到串口设备中。

202.3.2设置数据位大小

在串口通讯中,数据位指的是每个字符(byte)中实际包含的数据位数。通常情况下,一个字符包含8个位(即8个0或1),但有时也可能为7个位或其他值。

在编写串口应用程序时,需要使用 struct termios 结构体中的 c_cflag 成员变量来设置数据位大小。具体来说,需要将 c_cflag 成员变量中与数据位相关的位清零,然后再根据需要设置相应的值。

清零操作通常使用按位与(&)运算符和位运算中的“非”运算符(~),具体步骤如下:

new_cfg.c_cflag &= ~CSIZE; // 将数据位相关的比特位清零

其中,CSIZE 是一个宏定义,表示数据位的位掩码。宏定义通常定义在 termios.h 头文件中,其取值如下:

#define CSIZE   0x00000300  /* 字符长度掩码 */

通过清零操作,将数据位相关的位全部置为0。接下来,可以使用按位或(|)运算符和宏定义来设置具体的数据位数,例如:

new_cfg.c_cflag |= CS8;  // 将数据位数设置为8位

此时,CS8 宏定义将会被解释为一个包含8位的位掩码,通过按位或运算,将其设置到 c_cflag 成员变量中,从而完成数据位的设置。

202.3.3设置奇偶校验位 

串口的奇偶校验位配置一共涉及到 struct termios 结构体中的两个成员变量:c_cflag 和 c_iflag。首先对于 c_cflag 成员,需要添加 PARENB 标志以使能串口的奇偶校验功能,只有使能奇偶校验功能之后才会对输出数据产生校验位,从而对输入数据进行校验检查;同时对于 c_iflag 成员来说,还需要添加 INPCK 标志,这样才能对接收到的数据执行奇偶校验,代码如下所示:

奇校验使能:

new_cfg.c_cflag |= (PARODD | PARENB); // 设置为奇校验
new_cfg.c_iflag |= INPCK; // 使能奇偶校验

偶校验使能:

new_cfg.c_cflag &= ~PARODD;  // 设置为偶校验
new_cfg.c_cflag |= PARENB;   // 使能奇偶校验
new_cfg.c_iflag |= INPCK;    // 对输入数据执行奇偶校验

无校验:

new_cfg.c_cflag &= ~PARENB;  // 禁用奇偶校验
new_cfg.c_iflag &= ~INPCK;   // 不执行奇偶校验

202.3.4设置停止位

在串口通信中,停止位用于指定每个数据帧的结束位置。在传输一个完整的数据字节后,通常需要一个或多个停止位,以便接收端能够确定一个数据帧的结束。停止位的数量通常为1位或2位,其中1位停止位被广泛使用,而2位停止位则较少使用。

在Linux中,通过在 struct termios 结构体中设置 c_cflag 成员变量的 CSTOPB 标志位来控制停止位的数量。当 CSTOPB 为0时,仅使用1位停止位;当 CSTOPB 为1时,则使用2位停止位。

例如,以下代码将串口的停止位设置为1位:

new_cfg.c_cflag &= ~CSTOPB; // 设置停止位为1位

202.4 串口应用编程

在前面了解了串口编程需要的函数知识,接下来让我们动手实践,编写串口应用程序编写好的测试程序存放位置为:iTOP-RK3568开发板【底板V1.7版本】\03_【iTOP-RK3568开发板】指南教程\02_Linux驱动配套资料\04_Linux驱动例程\123_uart_app

#include <stdio.h>
#include <termios.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>

/* 设置串口参数的函数 */
int set_uart(int fd, int speed, int bits, char check, int stop) {
    struct termios newtio, oldtio;

    // 步骤一:保存原来的串口配置
    if(tcgetattr(fd, &oldtio) != 0) {
        printf("tcgetattr oldtio error\n");
        return -1;
    }

    bzero(&newtio, sizeof(newtio));
    
    // 步骤二:设置控制模式标志
    newtio.c_cflag |= CLOCAL | CREAD;
    newtio.c_cflag &= ~CSIZE;

    // 步骤三:设置数据位
    switch(bits) {
        case 7:
            newtio.c_cflag |= CS7;
            break;
        case 8:
            newtio.c_cflag |= CS8;
            break;
    }
    
    // 步骤四:设置奇偶校验位
    switch(check) {
        case 'O': // 偶校验位
            newtio.c_cflag |= PARENB;
            newtio.c_cflag |= PARODD;
            newtio.c_iflag |= (INPCK | ISTRIP);
            break;
        case 'E': // 奇校验位
            newtio.c_cflag |= PARENB;
            newtio.c_cflag &= ~PARODD;
            newtio.c_iflag |= (INPCK | ISTRIP);
            break;
        case 'N': // 无校验
            newtio.c_cflag &= ~PARENB;
            break;
    }
    
    // 步骤五:设置波特率
    switch(speed) {
        case 9600:
            cfsetispeed(&newtio, B9600);
            cfsetospeed(&newtio, B9600);
            break;
        case 115200:
            cfsetispeed(&newtio, B115200);
            cfsetospeed(&newtio, B115200);
            break;
    }
    
    // 步骤六:设置停止位
    switch(stop) {
        case 1:
            newtio.c_cflag &= ~CSTOPB; // 1位停止位
            break;
        case 2:
            newtio.c_cflag |= CSTOPB; // 2位停止位
            break;
    }
    
    // 步骤七:刷新输入队列
    tcflush(fd, TCIFLUSH);
    
    // 步骤八:设置配置立刻生效
    if (tcsetattr(fd, TCSANOW, &newtio) != 0) {
        printf("tcsetattr newtio error\n");
        return -2;
    }
    
    return 0;
}

int main(int argc, char *argv[]) {
    int fd;
    char buf[128];
    int count;
    
    // 步骤九:打开串口设备
    fd = open("/dev/ttyS9", O_RDWR | O_NOCTTY | O_NDELAY);
    
    if (fd < 0) {
        printf("open error \n");
        return -1;
    }

    // 设置串口参数
    set_uart(fd, 115200, 8, 'N', 1);
    
    // 写入数据
    write(fd, argv[1], strlen(argv[1]));
    sleep(1);
    
    // 读取数据
    count = read(fd, buf, sizeof(buf));
    buf[count] = '\0';
    
    // 输出读取的数据
    printf("read message is %s\n", buf);
    
    // 关闭串口设备
    close(fd);
    
    return 0;
}

202.5 运行测试

202.5.1编译应用程序

首先进行应用程序的编译,因为测试APP是要在开发板上运行的,所以需要aarch64-linux-gnu-gcc来编译,输入以下命令,编译完成以后会生成一个app的可执行程序,如下图所示:

 aarch64-linux-gnu-gcc app.c -o app

 

然后将编译完成的可执行程序app拷贝到开发板上。

202.5.2 运行测试

202.5.2.1 串口硬件连接

本实验使用的串口是串口9,串口9在开发板底板的背面,使用杜邦线将下图中的UART9_TX_M1和UART9_RX_M1连接起来。

 

202.5.2.2 运行测试

将编译完成的可执行程序app拷贝到开发板上,如下所示:

然后输入以下命令运行应用程序

./app 123456abc

 

如上图所示,在运行这段程序时,如果一切正常,程序将尝试打开串口设备 /dev/ttyS9,配置串口参数(波特率、数据位、校验位、停止位),然后尝试从串口设备中读取数据并将其输出。

至此,串口应用编程实验完成!

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2049176.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

计算机毕业设计选什么题目好?基于vue的音乐播放系统

✍✍计算机毕业编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java、…

LangGraph Studio:首款智能体(agent)IDE

0 前言 LangGraph Studio 提供了一个专门的智能体IDE&#xff0c;用于可视化、交互和调试复杂的智能体应用程序。本文来了解如何在桌面使用。 LLM为新型智能体应用程序的发展铺平了道路——随这些应用程序演进&#xff0c;开发它们所需工具也必须不断改进。今天推出的 LangG…

C++(10)类语法分析(1)

C(10)之类语法分析(1) Author: Once Day Date: 2024年8月17日 一位热衷于Linux学习和开发的菜鸟&#xff0c;试图谱写一场冒险之旅&#xff0c;也许终点只是一场白日梦… 漫漫长路&#xff0c;有人对你微笑过嘛… 全系列文章可参考专栏: 源码分析_Once-Day的博客-CSDN博客 …

JavaFX布局-DialogPane

JavaFX布局-DialogPane 常用属性标题区域headerTextheader 内容区域contentTextcontent graphic按钮设置expandableContent 实现方式Java实现 一个特殊的布局容器&#xff0c;常用于弹出框&#xff0c;与Dialog配合一起使用包含标题区&#xff0c;内容区域&#xff0c;扩展区域…

Merkle树(Merkle Tree):高效地验证某个数据块是否包含在数据集中

目录 Merkle树(Merkle Tree) 一、基本结构 二、构建过程 三、主要作用 四、应用领域 Merkle树(Merkle Tree) Merkle树(Merkle Tree),也被称为默克尔树或Merkle哈希树,是一种基于哈希的数据结构,主要用于验证大规模数据集的完整性和一致性。它的名字来源于其发明…

【Unity教程】使用 Animation Rigging实现IK制作程序化的动画

在 Unity 开发中&#xff0c;为角色创建逼真且自适应的动画是提升游戏体验的关键。在本教程中&#xff0c;我们将结合 Animation Rigging 工具和 IK&#xff08;Inverse Kinematics&#xff0c;反向运动学&#xff09;插件来实现程序化的动画。 视频教程可以参考b战大佬的视频 …

不只是翻译,更是智慧碰撞!有道翻译与3大强敌的全方位较量

现在的科技牛得不行&#xff0c;翻译软件早就成了咱们学习、工作、生活里少不了的帮手。它们不光是把语言的墙给推倒了&#xff0c;还让咱们说话交流快多了。今儿个&#xff0c;咱们就一块儿瞧瞧2024年的翻译软件圈子&#xff0c;瞅瞅那几个最火的翻译工具&#xff0c;它们怎么…

生信软件30 - 快速单倍型分析工具merlin

Merlin可用于连锁分析或关联分析、IBD和亲缘关系估计、单倍型分析、错误检测和模拟。 1. merlin下载 下载地址&#xff1a; http://csg.sph.umich.edu/abecasis/merlin/download/ # linux版本 wget http://csg.sph.umich.edu/abecasis/merlin/download/Linux-merlin.tar.gz …

如何在本地和远程删除 Git 分支?

如何在本地和远程删除 Git 分支&#xff1f; 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页&#xff0c;我是博主英杰&#xff0c;211科班出身&#xff0c;就职于医疗科技公司&#xff0c;热衷分享知识&#xff0c;武汉城市开发者社区主理人 擅长.n…

创新赛场的制胜法宝:如何让你的商业计划书脱颖而出

创新赛场的制胜法宝&#xff1a;如何让你的商业计划书脱颖而出 前言明确产品或服务的核心功能突出创新性用户需求和市场痛点具体示例和场景详细描述产品和服务的方法实例化产品与服务视觉辅助工具未来展望结语 前言 作为一名资深的项目负责人&#xff0c;我有幸参与了无数次创新…

React + Vite项目别名配置

Node版本&#xff1a;v20.16.0Vite版本&#xff1a;5.4.1 安装 types/node 依赖包 pnpm i types/node -D pnpm ls types/node配置 vite.config.js 文件: resolve: {alias: {"": join(__dirname, "./src/"),}, },使用配置好的别名 &#xff1a; 由上图我们…

考试:操作系统知识(02)

进程同步和互斥 临界资源&#xff1a;各进程间需要以互斥方式对其进行访问的资源。 临界区&#xff1a;指进程中对临界资源实施操作的那段程序。本质是一段程序代码。 ◆互斥&#xff1a;某资源(即临界资源) 在同一时间内只能由一个任务单独使用&#xff0c;使用时需要加锁&…

kafka连接图形化工具(Offset Explorer和CMAK)

kafka连接图形化工具 1、Offset Explorer1.1、下载Offset Explorer1.2、安装Offset Explorer1.3、配置Offset Explorer连接kafka 2、CMAK&#xff08;kafka的web管理后台&#xff09;2.1、下载2.2、解压安装2.3、配置2.4、启动2.5、CMAK访问 1、Offset Explorer Offset Explor…

【数据结构】二叉树链式结构(c语言)(附源码)

&#x1f31f;&#x1f31f;作者主页&#xff1a;ephemerals__ &#x1f31f;&#x1f31f;所属专栏&#xff1a;数据结构 目录 前言 一、节点的定义 二、创建一棵二叉树 1. 创建新节点 2. 手动创建二叉树 三、方法的声明 四、方法的实现 1. 前、中、后序遍历 1.1 前…

libLZMA库iOS18平台编译

1.下载xz源码: 使用autogen.sh生成configure文件 2.生成makefile rm -rf ./build/iOS && mkdir -p ./build/iOS && cd ./build/iOS && ../../configure --host=arm-apple-darwin64 --prefix=`pwd`/Frameworks/lzma CC="xcrun -sdk iphoneos cl…

二十天刷leetcode【hot100】算法- day2[前端Typescript]

指针 6.三数之和 给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 nums[i] nums[j] nums[k] 0 。请你返回所有和为 0 且不重复的三元组。 注意&#xff1a;答案中不可以包含重复的…

Maven项目中Allure和AspectJ的配置及测试执行(常见报错解决方法)

Maven项目中Allure和AspectJ的配置及测试执行 在自动化测试领域&#xff0c;Allure和AspectJ是两个非常有用的工具。Allure提供了丰富的测试报告&#xff0c;而AspectJ则允许我们以声明式的方式编写横切关注点&#xff0c;如日志记录、事务管理等。本文将指导您如何在Maven项目…

MySQL基础练习题47-判断三角形

目录 题目 准备数据 分析数据 方法一 &#xff1a;if函数 方法二&#xff1a;case when 题目 对每三个线段报告它们是否可以形成一个三角形。 准备数据 ## 创建库 create database db; use db;## 创建表 Create table If Not Exists Triangle (x int, y int, z int)## …

XSS-过滤特殊符号的正则绕过

靶场网址&#xff1a;https://xss.pwnfunction.com/ 题目源码&#xff1a; mafia (new URL(location).searchParams.get(mafia) || 11)mafia mafia.slice(0, 50)mafia mafia.replace(/[\\\"\\-\!\\\[\]]/gi, _)mafia mafia.replace(/alert/g, _)eval(mafia) 分析代码…

autojsUI界面分享 免责条款界面

个人简介 &#x1f468;&#x1f3fb;‍&#x1f4bb;个人主页&#xff1a;九黎aj &#x1f3c3;&#x1f3fb;‍♂️幸福源自奋斗,平凡造就不凡 &#x1f31f;如果文章对你有用&#xff0c;麻烦关注点赞收藏走一波&#xff0c;感谢支持&#xff01; &#x1f331;欢迎订阅我的…