(七)Linux库的串口开发
文章目录
- 基于官方提供的串口测试
- 代码部分
- 解析代码部分
- 1. `usage` 函数
- 2. `opt_parsing_err_handle` 函数
- 3. `sig_handle` 函数
- 4. `init_serial` 函数
- 5. `serial_write` 函数
- 6. `serial_read` 函数
- 7. `run_read_mode` 函数
- 8. `run_write_mode` 函数
- 9. `run_loopback_test` 函数
- 进行测试
- 第一步编译
- 第二步发送到板子
- 第三步调试
- 测试前注意
- 先测回环
- 再测写
- 最后测读
- 基于原生Linux串口开发
- 代码
- 测试
- 优化基于Linux原生串口开发
- 代码
- 测试
基于官方提供的串口测试
代码部分
创龙T113-i官方资料包给的代码:
uart_rw.c,功能很高端,支持读取、写入和回环测试三种模式!
/* Copyright 2018 Tronlong Elec. Tech. Co. Ltd. All Rights Reserved. */#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/select.h>
#include <sys/time.h>
#include <fcntl.h>
#include <termios.h>
#include <string.h>
#include <errno.h>
#include <stdbool.h>
#include <libgen.h>
#include <signal.h>
#include <getopt.h>#define NOPASS_CONDITIONS 3
#define INADEQUATE_CONDITIONS 10enum Mode { READ, WRITE, LOOPBACK };/* Exit flag */
volatile bool g_quit = false;/* Short option names */
static const char g_shortopts [] = ":d:s:rwvhl";/* Option names */
static const struct option g_longopts [] = {{ "device", required_argument, NULL, 'd' },{ "read", no_argument, NULL, 'r' },{ "write", no_argument, NULL, 'w' },{ "loopback", no_argument, NULL, 'l' },{ "size", required_argument, NULL, 's' },{ "version", no_argument, NULL, 'v' },{ "help", no_argument, NULL, 'h' },{ 0, 0, 0, 0 }
};static void usage(FILE *fp, int argc, char **argv) {fprintf(fp,"Usage: %s [options]\n\n""Options:\n"" -d | --device Device such as '/dev/ttyS0'\n"" -r | --read Read\n"" -w | --write Write\n"" -l | --loopback loopback test\n"" -s | --size Read size\n"" -v | --version Display version information\n"" -h | --help Show help content\n"" e.g. %s -d /dev/ttyS1 -r -s 256\n"" %s -d /dev/ttyS1 -w -s 1024\n"" %s -d /dev/ttyS1 -l -s 1024\n\n""", argv[0], argv[0], argv[0], argv[0]);
}static void opt_parsing_err_handle(int argc, char **argv, int flag) {/* Exit if no input parameters are entered */int state = 0;if (argc < 2) {printf("No input parameters are entered, please check the input.\n");state = -1;} else {/* Feedback Error parameter information then exit */if (optind < argc || flag) {printf("Error: Parameter parsing failed\n");if (flag)printf("\tunrecognized option '%s'\n", argv[optind-1]);while (optind < argc) {printf("\tunrecognized option '%s'\n", argv[optind++]);}state = -1;}}if (state == -1) {printf("Tips: '-h' or '--help' to get help\n\n");exit(2);}
}void sig_handle(int arg) {g_quit = true;
}int init_serial(int *fd, const char *dev) {struct termios opt;/* open serial device */if ((*fd = open(dev, O_RDWR)) < 0) {perror("open()");return -1;}/* define termois */if (tcgetattr(*fd, &opt) < 0) {perror("tcgetattr()");return -1;}opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);opt.c_oflag &= ~OPOST;/* Character length, make sure to screen out this bit before setting the data bit */opt.c_cflag &= ~CSIZE;/* No hardware flow control */opt.c_cflag &= ~CRTSCTS;/* 8-bit data length */opt.c_cflag |= CS8;/* 1-bit stop bit */opt.c_cflag &= ~CSTOPB;/* No parity bit */opt.c_iflag |= IGNPAR;/* Output mode */opt.c_oflag = 0;/* No active terminal mode */opt.c_lflag = 0;/* Input baud rate */if (cfsetispeed(&opt, B115200) < 0)return -1;/* Output baud rate */if (cfsetospeed(&opt, B115200) < 0)return -1;/* Overflow data can be received, but not read */if (tcflush(*fd, TCIFLUSH) < 0)return -1;if (tcsetattr(*fd, TCSANOW, &opt) < 0)return -1;return 0;
}int serial_write(int *fd, const char *data, size_t size) {int ret = write(*fd, data, size);if ( ret < 0 ) {perror("write");tcflush(*fd, TCOFLUSH);}return ret;
}int serial_read(int *fd, char *data, size_t size) {size_t read_left = size;size_t read_size = 0;char *read_ptr = data;struct timeval timeout = {5, 0};memset(data, 0, size);fd_set rfds;while (!g_quit) {FD_ZERO(&rfds);FD_SET(*fd, &rfds);timeout.tv_sec = 5;timeout.tv_usec = 0;if (read_left == 0)break;switch (select(*fd+1, &rfds, NULL, NULL, &timeout)) {case -1:perror("select()");break;case 0:perror("timeout and retry");break;default:if (FD_ISSET(*fd,&rfds)) {read_size = read(*fd, read_ptr, read_left);if (read_size == 0)break;read_ptr += read_size;read_left -= read_size;}}}return read_size;
}int run_read_mode(char *dev, size_t size) {char *buf = NULL;int fd = -1;int ret = -1;ret = init_serial(&fd, dev);if (ret < 0) {close(fd);return -1;}printf("Mode : read\n");if (size <= 0) {printf ("Error : Incorrect size settings\n");exit(INADEQUATE_CONDITIONS);}buf = (char*)malloc(size + 1);buf[size] = '\0';ret = serial_read(&fd, buf, size);printf("recv: %s\nsize: %d\n", buf, ret);free(buf);return 0;
}int run_write_mode(char *dev, size_t size) {int fd = -1;int ret = -1;ret = init_serial(&fd, dev);if (ret < 0) {close(fd);return -1;}printf("Mode : write\n");if (size <= 0) {printf("Error : Incorrect size settings\n");exit(INADEQUATE_CONDITIONS);}int i = 0;char context;size_t write_size = 0;while (!g_quit) {if (i > 7)i = 0;context = (char)('0' + i);write_size += serial_write(&fd, &context, sizeof(context));i ++;if (size == write_size)break;}printf("send size: %zd\n", write_size);return 0;
}int run_loopback_test(char *dev, size_t size) {int fd;int ret;size_t buf_size;int serial_buf_size;ret = init_serial(&fd, dev);if (ret < 0)return -1;printf("Start uart loopback testing.\n");/* Serial port buffer size generally defaults to 2k - 4k */char *write_buf = (char*)malloc(size);char *read_buf = (char*)malloc(size);buf_size = size;while (buf_size > 0){if(buf_size > 1024) {serial_buf_size = 1024;} else {serial_buf_size = buf_size;}// Generate random data to write.memset(write_buf, rand() % 26 + 65, serial_buf_size);memset(read_buf, 0, serial_buf_size);ret = serial_write(&fd, write_buf, serial_buf_size);/* delay > 1024 / 115200 * 1000000 */usleep(90000);ret = serial_read(&fd, read_buf, serial_buf_size);ret = memcmp(read_buf, write_buf, serial_buf_size);if (ret != 0) {printf("Result : Test failed\n");goto release;}buf_size -= 1024;}printf("send size: %zd\n", size);printf("recv size: %zd\n", size);printf("Result : Test pass\n");release:free(write_buf);free(read_buf);close (fd);if (ret != 0) {return NOPASS_CONDITIONS;} else {return 0;}
}int main(int argc, char *argv[]) {int c = 0;int flag = 0;int mode = -1;size_t size = 0;char *dev = NULL;int ret = -1;/* Parsing input parameters */while ((c = getopt_long(argc, argv, g_shortopts, g_longopts, NULL)) != -1) {switch (c) {case 'd':dev = optarg;break;case 'r':mode = READ;break;case 'w':mode = WRITE;break;case 'l':mode = LOOPBACK;break;case 's':size = atoi(optarg);break;case 'v':/* Display the version */printf("version : 1.0\n");exit(0);case 'h':usage(stdout, argc, argv);exit(0);default :flag = 1;break;}}opt_parsing_err_handle(argc, argv, flag);/* Ctrl+c handler */signal(SIGINT, sig_handle);switch (mode) {case READ:if(run_read_mode(dev, size) < 0) {return INADEQUATE_CONDITIONS;}break;case WRITE:if(run_write_mode(dev, size) < 0) {return INADEQUATE_CONDITIONS;}break;case LOOPBACK:ret = run_loopback_test(dev, size);if(ret < 0) {return INADEQUATE_CONDITIONS;} else if(ret == NOPASS_CONDITIONS) {return NOPASS_CONDITIONS;}break;default:break;}return 0;
}
解析代码部分
不深究可以不看,了解函数啥功能即可。
1. usage
函数
- 作用:打印帮助信息给用户。
- 参数:
FILE *fp
: 输出流,可以是标准输出(stdout)或标准错误(stderr)。argc, argv[]
: 命令行参数的数量和值,用于在示例中显示程序名。
- 行为:当用户请求帮助(
-h
或--help
)时调用,向用户提供如何使用该工具的信息。
2. opt_parsing_err_handle
函数
- 作用:处理命令行选项解析过程中的错误。
- 参数:
argc, argv[]
: 命令行参数的数量和值。flag
: 标记是否有未知选项被识别。
- 行为:如果命令行参数为空或者存在无法识别的选项,则打印错误信息并提示用户使用
-h
获取帮助,然后退出程序。
3. sig_handle
函数
- 作用:信号处理器,用来响应中断信号(如Ctrl+C)。
- 参数:
int arg
,传递给信号处理器的信号编号。 - 行为:设置全局变量
g_quit
为真,通知其他部分停止工作。
4. init_serial
函数
- 作用:初始化串行端口配置。
- 参数:
fd
: 文件描述符指针,将被设置为打开的串行端口。dev
: 设备路径字符串,例如/dev/ttyS0
。
- 行为:根据提供的设备路径打开串行端口,并配置波特率、数据位、停止位等参数。它还会清除终端模式并禁用硬件流控制。
5. serial_write
函数
- 作用:向串行端口写入数据。
- 参数:
fd
: 文件描述符指针。data
: 指向要发送的数据的指针。size
: 要发送的数据大小。
- 行为:尝试将指定数量的字节写入到串行端口,失败时刷新输出缓冲区并报告错误。
6. serial_read
函数
- 作用:从串行端口读取数据。
- 参数:
fd
: 文件描述符指针。data
: 指向存储接收到的数据的缓冲区。size
: 预期接收的数据量。
- 行为:使用
select
函数等待数据到达,然后尽可能多地读取数据直到达到预期大小或超时。如果发生错误或超时,会给出相应的错误信息。
7. run_read_mode
函数
- 作用:执行读取模式操作。
- 参数:
dev
: 设备路径。size
: 期望读取的数据大小。
- 行为:以非阻塞方式读取指定大小的数据,并将其打印出来。如果指定大小无效,则报错退出。
8. run_write_mode
函数
- 作用:执行写入模式操作。
- 参数:
dev
: 设备路径。size
: 要写入的数据大小。
- 行为:循环地写入字符到串行端口,直到写入了指定大小的数据。每次写入后,字符递增,模拟连续的数据流。
9. run_loopback_test
函数
- 作用:执行回环测试。
- 参数:
dev
: 设备路径。size
: 测试过程中使用的数据大小。
- 行为:生成随机数据写入串行端口,然后立即尝试读回相同的数据,比较两者是否一致。如果不一致,则认为测试失败;否则,测试通过。
进行测试
第一步编译
用交叉编译工具进行编译。
不会配置交叉编译链的,请参考:(二)编译原生SDK以及配置交叉编译链中配置交叉编译链的部分。
arm-linux-gnueabi-gcc uart_rw.c -o uart_rw
查看一下可执行文件类型,避免错误。
第二步发送到板子
借助基于ssh的scp工具,不会的可以参考(四)配置有线网口、SSH登陆、文件传输以及运行交叉编译程序测试中SHH登陆以及文件传输部分。
scp ./uart_rw root@192.168.1.101:/root/zhua
出现问题:
根据提示,解决问题,并再次发送:
第三步调试
测试前注意
如何运行可执行文件,查看如何运行
./uart_rw -h
当然直接读代码也是可以的,参考这部分:
注意一下波特率是115200,可以从代码中了解到:
最后查看用的串口4是否开启(可以自行指定),注意创龙的是ttyAS4,跟传统的名称还是有区别的
ls /dev
可以在设备文件夹下看到,说明串口的设备是成功加载到了系统中。如果看不到,请进一步修改设备树,书写设备驱动文件(不会的,请参考后面的章节),再次编译镜像,进行烧录。
先测回环
./uart_rw -d /dev/ttyAS4 -l -s 1024
记得要把串口4的TX和RX短接。另外我开启的是串口4。
再测写
注意这里写的内容就是0-7 来回循环,看代码便知。
./uart_rw --device /dev/ttyAS4 --write --size 16
或者简写参数
./uart_rw -d /dev/ttyAS4 -w -s 16
最后测读
这里我读8个长度,用串口助手发送87654321。
./uart_rw --device /dev/ttyAS4 --read --size 8
或者简写
./uart_rw -d /dev/ttyAS4 -r -s 8
中间提示的,timeout and retry: Success应该是一帧数据的帧检测,可以参考蓝桥杯专栏的(十六)串口UART进行学习。
基于原生Linux串口开发
功能简单,借助线程操作,支持读写同步。
步骤:初始化串口,开启父子线程,父线程读操作,子线程写操作。
代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/select.h>
#include <sys/time.h>
#include <fcntl.h>
#include <termios.h>
#include <string.h>
#include <errno.h>
#include <stdbool.h>
#include <libgen.h>
#include <signal.h>int init_serial(int *fd, const char *dev) {struct termios opt;/* open serial device */if ((*fd = open(dev, O_RDWR)) < 0) {perror("open()");return -1;}/* define termois */if (tcgetattr(*fd, &opt) < 0) {perror("tcgetattr()");return -1;}opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);opt.c_oflag &= ~OPOST;/* Character length, make sure to screen out this bit before setting the data bit */opt.c_cflag &= ~CSIZE;/* No hardware flow control */opt.c_cflag &= ~CRTSCTS;/* 8-bit data length */opt.c_cflag |= CS8;/* 1-bit stop bit */opt.c_cflag &= ~CSTOPB;/* No parity bit */opt.c_iflag |= IGNPAR;/* Output mode */opt.c_oflag = 0;/* No active terminal mode */opt.c_lflag = 0;/* Input baud rate */if (cfsetispeed(&opt, B115200) < 0)return -1;/* Output baud rate */if (cfsetospeed(&opt, B115200) < 0)return -1;/* Overflow data can be received, but not read */if (tcflush(*fd, TCIFLUSH) < 0)return -1;if (tcsetattr(*fd, TCSANOW, &opt) < 0)return -1;return 0;
}int serial_write(int *fd, const char *data, size_t size) {int ret = write(*fd, data, size);if ( ret < 0 ) {perror("write");tcflush(*fd, TCOFLUSH);}return ret;
}int serial_read(int *fd, size_t size)
{int read_size = 0;char data[128] = {'\0'};while(1){read_size = read(*fd, data, size);if(read_size!=0){printf("read_size = %d,context = %s\n",read_size,data);memset(data,'\0',128);read_size = 0;}}return 0;
}int main(int argc ,char *argv[])
{__pid_t pid = 0;char *writedata = "write from root\n";int ret= -1;int fd = -1;if(argc<2){printf("tips:./myuart /dev/xxx\n");printf("argc = %d,argv[0] = %s,,argv[1] = %s\n",argc,argv[0],argv[1]);}ret = init_serial(&fd, argv[1]);if(ret == -1){return -1;}//开启2个线程pid = fork();if(pid>0){ //父进程 就是父进程的pid号 serial_read(&fd,128);}else if(pid==0){ //子进程while(1){serial_write(&fd,writedata,strlen(writedata));sleep(3);}}else{ //fork线程错误错误perror("fork faild\n");return -1;}return 0;
}
测试
执行指令:
./myuart /dev/ttyAS4
注意使用的是串口4,波特率115200。
优化基于Linux原生串口开发
向官方牛x的功能靠近一点点!
实现指定长短的发送,可以双方互不干扰。
这里是开启两个线程,一个是发送线程,一个是接收线程。在原有的Linux原生串口代码的基础上改进,之前使用的fork函数,创建的父子线程有局限性,资源争夺问题,数据共享等问题,所以这里借助pthread_create直接创建两个新的线程。
可以参考(十四)基于Linux的串口开发中基于Linux库的开发,几乎一样。
代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/select.h>
#include <sys/time.h>
#include <fcntl.h>
#include <termios.h>
#include <string.h>
#include <errno.h>
#include <stdbool.h>
#include <libgen.h>
#include <signal.h>
#include <pthread.h>int fd = -1;int init_serial(int *fd, const char *dev) {struct termios opt;/* open serial device */if ((*fd = open(dev, O_RDWR)) < 0) {perror("open()");return -1;}/* define termois */if (tcgetattr(*fd, &opt) < 0) {perror("tcgetattr()");return -1;}opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);opt.c_oflag &= ~OPOST;/* Character length, make sure to screen out this bit before setting the data bit */opt.c_cflag &= ~CSIZE;/* No hardware flow control */opt.c_cflag &= ~CRTSCTS;/* 8-bit data length */opt.c_cflag |= CS8;/* 1-bit stop bit */opt.c_cflag &= ~CSTOPB;/* No parity bit */opt.c_iflag |= IGNPAR;/* Output mode */opt.c_oflag = 0;/* No active terminal mode */opt.c_lflag = 0;/* Input baud rate */if (cfsetispeed(&opt, B115200) < 0)return -1;/* Output baud rate */if (cfsetospeed(&opt, B115200) < 0)return -1;/* Overflow data can be received, but not read */if (tcflush(*fd, TCIFLUSH) < 0)return -1;if (tcsetattr(*fd, TCSANOW, &opt) < 0)return -1;return 0;
}int serial_write(int *fd, const char *data, size_t size) {int ret = write(*fd, data, size);if ( ret < 0 ) {perror("write");tcflush(*fd, TCOFLUSH);}return ret;
}int serial_read(int *fd, size_t size)
{int read_size = 0;char data[128] = {'\0'};while(1){read_size = read(*fd, data, size);if(read_size!=0){printf("read_size = %d,context = %s\n",read_size,data);memset(data,'\0',128);read_size = 0;}}return 0;
}void* recive()
{printf("recive pthread========ok========\n");while(1){serial_read(&fd,128);}}char *writedata = NULL;
int nwrite = 0;void* send()
{printf("send pthread========ok========\n");while(1){printf("please enter n size what you want to write and press Enter to end \n");scanf("%d",&nwrite);writedata = (char *)malloc(nwrite*sizeof(char));scanf("%s",writedata);serial_write(&fd,writedata,strlen(writedata));free(writedata);writedata = NULL;}
}int main(int argc ,char *argv[])
{pthread_t recivet;pthread_t sendt;int ret= -1;if(argc<2){printf("tips:./myuart /dev/xxx\n");printf("argc = %d,argv[0] = %s,,argv[1] = %s\n",argc,argv[0],argv[1]);}ret = init_serial(&fd, argv[1]);if(ret == -1){return -1;}pthread_create(&recivet,NULL,recive,NULL);//接收线程pthread_create(&sendt,NULL,send,NULL);//发送进程while(1){//啥事也不干 3秒睡一次sleep(3);}return 0;
}
测试
注意这里因为用到的pthread_create函数是POSIX线程(pthreads)库的一部分,因此在编译和链接程序时需要链接到这个库,可以通过在编译命令中添加 -lpthread 选项来实现。否则会失败。
必须链接库编译
arm-linux-gnueabi-gcc myuart.c -o myuart -lpthread
输入数据格式一定要注意,因为使用的scanf这个函数,严格遵守它的规范,用回车或者空格断开数据。
相关文章:
(七)Linux库的串口开发
文章目录 基于官方提供的串口测试代码部分解析代码部分1. usage 函数2. opt_parsing_err_handle 函数3. sig_handle 函数4. init_serial 函数5. serial_write 函数6. serial_read 函数7. run_read_mode 函数8. run_write_mode 函数9. run_loopback_test 函数 进行测试第一步编译…...
【git】在服务器使用docker设置了一个gogs服务器,访问和现实都不理想
以下问题应该都可以通过设置custom/conf/app.ini来解决 配置文档参考地址:https://www.bookstack.cn/read/gogs_zh/advanced-configuration_cheat_sheet.md domain显示的事localhost,实际上应该是一个IP地址。 关键字: DOMAIN ROOT_URL 因为是docker…...
ubuntu报错:没有在该文件夹中粘贴文件的权限
1 现象: 近期给ubuntu扩展了硬盘,但是在其中进行文件操作时提示“没有在该文件夹中粘贴文件的权限” 2 原因: 新增硬盘挂载地址为“/home/username/data/” 终端输入 ls -ld /home/username/data/输出 drwxr-xr-x 3 root root 4096 1月…...
JavaWeb开发(六)XML介绍
1. XML介绍 1.1. 什么是XML (1)XML 指可扩展标记语言(EXtensible Markup Language)XML 是一种很像HTML的标记语言。 (2)XML 的设计宗旨是传输数据(目前主要是作为配置文件),而不是显示数据。 (3&a…...
Vue 3 和 Electron 来构建一个桌面端应用
我们将使用 Vue 3 和 Electron 来构建一个桌面端应用,该应用可以通过 Websocket 与服务器进行通信,并实现心跳检测、客户端上线、获取资产信息以及修改资产状态的功能。以下是实现步骤的概述: 项目结构:创建一个 Vue 3 项目&…...
Python中的asyncio:高效的异步编程模型
随着互联网应用的快速发展,程序的响应性和处理效率成为衡量系统性能的重要指标。传统的同步编程模型在面对高并发和IO密集型任务时,常常显得捉襟见肘,难以满足现代应用的需求。Python的asyncio库作为一种高效的异步编程模型,为开发…...
《解锁鸿蒙系统AI能力,开启智能应用开发新时代》
在当今科技飞速发展的时代,鸿蒙系统以其独特的分布式架构和强大的AI能力,为开发者们带来了前所未有的机遇。本文将深入探讨开发者如何利用鸿蒙系统的AI能力开发更智能的应用,开启智能应用开发的新时代。 鸿蒙系统构筑了15系统级的AI能力&…...
安卓OCR使用(Google ML Kit)
OCR是一个很常用的功能,Google ML Kit提供了OCR能力,用起来也很简单,本文介绍一下使用方法。 1. 相关概念 名词概念解释TextBlock块一个段落Line行一行文本Element元素单词;对汉字来说,类似"开头 (分隔符)中间&…...
使用redis的5种常用场景
文章目录 1. 缓存热点数据2. 分布式锁3. 计数器和限流器4. 消息队列5. 会话管理总结 在日常开发工作中,Redis作为一款高性能的内存数据库,凭借其强大的功能特性和卓越的性能表现,已经成为了许多项目中不可或缺的组件。本文将详细介绍Redis在实…...
Extreme670和440的DHCP和vlan划分
1.网关配置 防火墙 USG 添加静态路由,也就是回指路由192.168.0.0 255.255.0.0 192.168.100.2 usg关闭DHCP192.168.100.0段的,usg接口的网关地址是192.168.100.1,防火墙策略启用192.168.100.0段到wan1段的内网和外网的NAT地址转换。 2…...
VTK知识学习(33)-交互问题2
1、前言 主要是针对前面有过实现不了交互的情况进行说明,经过一些尝试和分析调用API,总算实现RenderWindowControl函数回调正常串接,当然这个移动处理事件的效果目前也没有确认。 2、使用 vtkImageReslice reslice vtkImageReslice.New();p…...
c++ thread线程join、detach、joinable方法
(621条消息) 线程中断Thread的interrupt()方法_thread interrupt_萝卜阿咕咕的博客-CSDN博客 C/C编程:std::thread 详解-CSDN博客 #include <iostream> #include <thread>void do_some_work() {std::cout<<"Hello Concurrent World\n"…...
Transformer:深度学习的变革力量
深度学习领域的发展日新月异,在自然语言处理(NLP)、计算机视觉等领域取得了巨大突破。然而,早期的循环神经网络(RNN)在处理长序列时面临着梯度消失、并行计算能力不足等瓶颈。而 Transformer 的横空出世&am…...
【Python】__main__.py、__init__.py
文章目录 1. __init__.py作用:用法:示例:特点 2. __main__.py作用:用法:示例:特点: 3. 综合示例总结: 1. init.py 作用: __init__.py 文件的主要作用是标识一个目录是一…...
springboot集成整合工作流,activiti审批流,整合实际案例,流程图设计,流程自定义,表单配置自定义,代码demo流程
前言 activiti工作流引擎项目,企业erp、oa、hr、crm等企事业办公系统轻松落地,一套完整并且实际运用在多套项目中的案例,满足日常业务流程审批需求。 一、项目形式 springbootvueactiviti集成了activiti在线编辑器,流行的前后端…...
代码随想录算法【Day16】
Day16 513.找二叉树左下角的值 本题使用迭代法更简单,使用迭代法和递归法的区别是什么 递归法 目标就是找深度最大的叶子结点 无论前中后序遍历,都是左节点先被遍历到,所以一旦得到深度最大的节点,就是最后一行最靠左侧的节点…...
从光子到图像——相机如何捕获世界?
引言 你是否想过为何我们按一下相机快门就可以将眼前广袤多彩的世界显示于一个小小的相机屏幕上?本期推文中将带着大家重现从光子转换为电子、电子转换为图像中数字驱动值的整个流程。 ▲人们通过相机捕获眼前的场景 从光子到电子的转换 光线首先通过光学镜头进入相…...
Harmony开发【笔记1】报错解决(字段名写错了。。)
在利用axios从网络接收请求时,发现返回obj的code为“-1”,非常不解,利用console.log测试,更加不解,可知抛出错误是 “ E 其他错误: userName required”。但是我在测试时,它并没有体现为空,…...
Ubuntu 下载安装 elasticsearch7.17.9
参考 https://blog.csdn.net/qq_26039331/article/details/115024218 https://blog.csdn.net/mengo1234/article/details/104989382 过程 来到 Es 的版本发布列表页面:https://www.elastic.co/downloads/past-releases#elasticsearch 根据自己的系统以及要安装的…...
8. LINUX 用户和组
文章目录 8.1 密码文件:/etc/passwd1. 登录名(Login Name)2. 经过加密的密码(Encrypted Password)3. 用户 ID(User ID, UID)4. 组 ID(Group ID, GID)5. 注释(…...
vue监听中的watch监听(详解)
1、watch 选项用于监听数据的变化并执行相应的回调函数。watch 选项提供了两个重要的属性:deep 和 immediate。1.1、深度监听 (deep: true) 当你需要监听一个对象或数组内部的变化时,可以使用 deep: true。 这会使得 watch 监听器递归地监听对象或数组内…...
微信小程序中 隐藏scroll-view 滚动条 网页中隐藏滚动条
在微信小程序中隐藏scroll-view的滚动条可以通过以下几种方法实现: 方法一:使用CSS隐藏滚动条 在小程序的样式文件中(如app.wxss或页面的.wxss文件),添加以下CSS代码来隐藏滚动条: scroll-view ::-webkit…...
K8s Pod OOMKilled,监控却显示内存资源并未打满
1. 问题现象 pod一直重启,通过grafana查看,发现内存使用率并没有100%。 2. 排查过程 2.1 describe查看pod最新一次的状态 可以明显看到,最近一次的重启就是因为内存不足导致的。 2.2 describe 查看node节点状态 找到原因了,原来…...
对话|全年HUD前装将超330万台,疆程技术瞄准人机交互“第一屏”
2024年,在高阶智驾进入快速上车的同时,座舱人机交互也在迎来新的增长点。Chat GPT、AR-HUD、车载投影等新配置都在带来新增量机会。 高工智能汽车研究院监测数据显示,2024年1-10月,中国市场(不含进出口)乘用…...
【HTML+CSS+JS+VUE】web前端教程-10-列表标签之无序列表
无序列表实现 无序列表是一个项目的列表,此列项目使用粗体圆点(典型的小黑圆圈)进行标记 无序列表始于<ul>标签,每个列表项始于<li>标签。<ul><li>苹果...
基于V2X的无人机与特种车辆战地智能通信:技术融合与实战应用
一、引言 1.1 研究背景与意义 在现代战争的复杂环境中,通信系统的高效与可靠已然成为决定胜负的关键因素。随着军事技术的飞速发展,战争形态发生了深刻变革,作战空间不断拓展,从陆地、海洋、天空延伸至电磁、网络、太空等多维领…...
20250109下载JDK17的方法链接
20250109下载JDK17的方法&链接 2025/1/9 16:20 缘起:编译地面站应用程序QGC,需要安装QT和【旧版本的】JDK17。 当时在网上没有找到JDK17,就安装了比较接近的JDK21。反正最后的QT for Android最后就是没有编译通过。 到底是谁的问题&#…...
杭州铭师堂的云原生升级实践
作者:升学e网通研发部基建团队 公司介绍 杭州铭师堂,是一个致力于为人的全面发展而服务的在线教育品牌。杭州铭师堂秉持“用互联网改变教育,让中国人都有好书读”的使命,致力于用“互联网教育”的科技手段让更多的孩子都能享有优…...
chrome浏览器的更新提示弹窗无法更新Chrome解决方法
使用组策略编辑器 此方法适用于 Windows 系统且系统为专业版及以上版本,家庭版系统没有组策略功能。 按下Win R键,打开 “运行” 对话框,输入gpedit.msc并回车,打开组策略编辑器。 在组策略编辑器中,依次展开 “计算机…...
LLM prompt提示构造案例:语音回复内容;o1思维链
1、语音回复内容 目的: 语音聊天助手的prompt,让大模型来引导聊天内容,简短和友好,从而文字转语音时候也比较高效。 ## 角色设定与交互规则 ### 基本角色 你是用户的好朋友. 你的回答将通过逼真的文字转语音技术阅读. ### 回答规则…...
OceanBase 学习计划全攻略:开启分布式数据库探索之旅
《OceanBase 学习计划全攻略:开启分布式数据库探索之旅》 在当今数字化浪潮汹涌澎湃的时代,数据库作为企业信息存储与管理的核心基础设施,其性能、可靠性和扩展性至关重要。OceanBase 作为一款具有卓越分布式特性的国产数据库,正…...
Linux 虚拟机与windows主机之间的文件传输--设置共享文件夹方式
Linux 虚拟机与windows主机之间的文件传输 设置共享文件夹方式 在虚拟机中打开终端查看是否已经新建完成,到文件夹中找到它看一下,这个位置就能存储东西啦...
React Context用法总结
1. 基本概念 1.1 什么是 Context Context 提供了一种在组件树中共享数据的方式,而不必通过 props 显式地逐层传递。它主要用于共享那些对于组件树中许多组件来说是"全局"的数据。 1.2 基本用法 // 1. 创建 Context const ThemeContext React.createC…...
Linux好用软件
力荐软件 apt-fast:更快速的软件管理安装过程会进入一个图形界面,配置线程数等信息,全部默认即可 sudo add-apt-repository ppa:apt-fast/stable sudo apt-get update sudo apt-get -y install apt-fast 以后安装应用,把apt-get直接替换成apt-fast即可,例如安装vlc sudo…...
【MYSQL】
文章目录 1.DDL 1.DDL --添加字段 ALTER TABLE table_name add COLUMN embed_model VARCHAR(32) NOT NULL COMMENT 名称备注 COLLATE utf8mb4_bin AFTER config_code;--修改字段 ALTER TABLE table_name CHANGE COLUMN column_a column_b VARCHAR(500) NOT NULL COMMENT 配置信…...
webrtc之rtc::ArrayView<const uint8_t>
rtc::ArrayView<const uint8_t> 是 WebRTC(或其他基于 rtc 命名空间的库)中常见的一个类型,它通常用于表示一块 只读的内存区域,该内存区域由一系列 uint8_t 类型(无符号 8 位整数)元素组成。 1. rt…...
深入理解 MySQL 的 EXPLAIN 工具
1. 什么是 EXPLAIN 工具? EXPLAIN 是 MySQL 中用来分析 SQL 查询执行计划的命令,它能够显示查询在执行时会如何访问表、使用哪些索引、扫描多少行等信息。通过 EXPLAIN 工具,开发者可以直观地了解查询的执行过程,从而进行针对性的…...
谷歌Google、紫鸟浏览器插件开发
对于跨境电商行业的IT部门来说,经常需要获取各种店铺相关数据,但是仅靠官方提供的接口来获取数据远远不够,这个时候我们就需要插件或者RPA的方式来获取数据。 以下是关于自研紫鸟插件的简单demo,紫鸟浏览器使用的是火狐和谷歌的插…...
HTML 显示器纯色亮点检测工具
HTML 显示器纯色亮点检测工具 相关资源文件已经打包成html等文件,可双击直接运行程序,且文章末尾已附上相关源码,以供大家学习交流,博主主页还有更多Html相关程序案例,秉着开源精神的想法,望大家喜欢&#…...
Win32汇编学习笔记09.SEH和反调试
Win32汇编学习笔记09.SEH和反调试-C/C基础-断点社区-专业的老牌游戏安全技术交流社区 - BpSend.net SEH - structed exception handler 结构化异常处理 跟筛选一样都是用来处理异常的,但不同的是 筛选器是整个进程最终处理异常的函数,但无法做到比较精细的去处理异常(例如处理…...
计算机组成原理(九):乘法器
乘法器原理 乘法器的工作原理可以用二进制乘法来说明。二进制乘法和十进制乘法类似,通过部分积的累加得到结果。 部分积的生成 在二进制乘法中,每一位的乘积是两个二进制数位的 与运算(0 0 0,1 0 0,0 1 0&…...
前端开发中常用的插件库
ahooks 一个高质量且可靠的React Hooks库。class-variance-authority(CVA) 是一个专注于解决CSS类管理问题的库。classnames 是一个在React开发中非常流行的JavaScript工具库,它可以帮助开发者有条件地连接类名字符串。copy-to-clipboard 一个…...
认识+安装ElasticSearch
1. 为什么要学习ElasticSearch? 一般的来说,项目中的搜索功能尤其是电商项目,商品的搜索肯定是访问频率最高的页面之一。目前搜索功能是基于数据库的模糊搜索来实现的,存在很多问题。 1.1 数据库搜索所存在的问题 1.1.1 查询效率较低 由于数据库模糊查询不走索引&…...
Nginx | 解决 Spring Boot 与 Nginx 中的 “413 Request Entity Too Large“ 错误
关注:CodingTechWork 引言 在 Web 开发中,413 Request Entity Too Large 是一种常见的 HTTP 错误,它指示客户端请求的实体(例如文件或数据)超出了服务器允许的最大大小。对于使用 Spring Boot 和 Nginx 的应用程序来说…...
CAD批量打印可检索的PDF文件
本文虽介绍CAD使用方法,但还是劝告大家尽早放弃使用CAD软件。。。。太TM难用了 当你打开CAD时发现如下一堆图纸,但是不想一个一个打印时。你可以按照下面操作实现自动识别图框实现批量打印。 1.安装批量打印插件 2.安装后打开CAD,输入命令Bp…...
理解Unity脚本编译过程:程序集
https://docs.unity3d.com/Manual/script-compilation.html 关于Unity C#脚本编译的细节,其中一个比较重要的知识点就是如何自定义Assembly。 预定义的assembly 默认情况下,Unity会按照这个规则进行编译。 PhaseAssembly nameScript files1Assembly-…...
Linux-Ubuntu之SPI串行通信陀螺仪和加速度计
Linux-Ubuntu之SPI串口通信陀螺仪和加速度计 一,SPI通信原理二,ICM-20608六轴传感器控制三,代码1.小tip 一,SPI通信原理 SPI:串行全双工通信,最高能达到百MHZ,通常一个主设备跟多个从设备&…...
【C++/控制台】2048小游戏
源代码: #include <iostream> #include <windows.h> #include <stdio.h> #include <math.h> #include <stdlib.h> #include <conio.h> #include <time.h>// #define KEY_DOWN(VK_NONAME) ((GetAsyncKeyState(VK_NONAME)…...
github gitbook写书
github创建新的仓库 在仓库中添加目录 ‘SUMMARY.md # Summary * [简介](README.md)gitbook 新建一个site https://www.gitbook.com/ 注册账号 取名字 一路 next,注意选免费版 最后 gitbook同步到github 你在主页可以看到 刚刚的test网站 点击右上角圈出来…...
鸿蒙中调整应用内文字大小
1、ui Stack() {Row() {ForEach([1, 2, 3, 4], (item: number) > {Text().width(3).height(20).backgroundColor(Color.Black).margin(item 2 ? { left: 8 } : item 3 ? { left: 7 } : { left: 0 })})}.width(97%).justifyContent(FlexAlign.SpaceBetween).padding({ ri…...