#网络高级 笔记

news2024/9/24 9:25:23

modbus_tcp协议
modbus_rtu协议和modbus库
http协议和web服务器搭建
服务器原码分析和基于WebServer的工业数据采集项目
第H5,即网页制作,项目完善

一、modbus起源

1.起源

Modbus由Modicon公司于1979年开发,是一种工业现场总线协议标准
Modbus通信协议具有多个变种,其中有支持串口,以太网多个版本
其中最著名的是Modbus RTU、Modbus ASCII和Modbus TCP三种
其中Modbus TCP是在施耐德收购Modicon后1997年发布的

2. 分类

Modbus RTU

运行在串口上的协议
采用二进制表现形式以及紧凑的数据结构,通信效率较高,应用比较广泛

Modbus ASCII

运行在串口上的协议
采用ASCII码进行传输,并且每个字节的开始和结束都有特殊字符作为标志,传输效率远远低于Modbus RTU,一般只有通讯量比较少时才会考虑它。
注:在ASCII模式下,每个8位的字节被拆分成两个ASCII字符进行发送,比如十六进制0xAF(1010 1111),会被分解成ASCII字符“A”(0100 0001)和”F”(0100 0110)进行发送,其发送量显然比RTU增加一倍。

Modbus TCP

运行在以太网上的协议

3. 优势

免费、简单、容易使用

4. 应用场景

Modbus协议是现在国内工业领域应用最多的协议,不只PLC设备,各种终端设备,比如水控机、水表、电表、工业秤、各种采集设备。

5. ModbusTCP特点(掌握)

1)采用主从问答式通信
2)Modbus TCP是应用层协议基于传输层的TCP进行通信的
3)Modbus TCP端口号默认502
注:更好的理解网络模型的分层特点:
各层之间独立,每一层不需要知道下一层如何实现
当任何一层发生变化时,只要层间接口关系保持不变,则这层以上或以下层不受影响。

二、ModbusTCP的协议格式

ModbusTcp协议包含三部分:报文头、功能码、数据
MBAP:Modbus Application Protocol (modbus报文头)
PDU:Protocol Data Unit(协议数据单元)
Modbus TCP/IP协议最大数据帧长度为260字节

1.报文头

包含7个字节

2. 寄存器

一共有四种类型的寄存器

线圈寄存器支持读也支持写,对应3个功能码
写在功能码里面又分为写单个线圈寄存器和写多个线圈寄存器。

离散输入寄存器,离散输入寄存器就相当于线圈寄存器的只读模式,也是每个bit表示一个开关量,而他的开关量只能读取输入的开关信号,是不能够写的。对应功能码1个。
比如我读取外部按键的按下还是松开。

保持寄存器,这个寄存器的单位不再是bit而是两个byte,也就是可以存放具体的数据量的,并且是可读写的。功能码有对应的三个。
比如空调检测到的室温,这是不可以修改的,因为室温是根据实际的物理环境决定的。

输入寄存器,这个和保持寄存器类似,但是只支持读而不能写。一个寄存器也是占据两个byte的空间,对应的功能码就一个。
类比通过读取输入寄存器获取现在的温度传感器的值

总结:
读都是可以一个功能码读多个或单个的。而写是分为写单个和写多个,需要两个功能码。
所以对于只读的寄存器都只有一个功能码,而可读可写的寄存器都有三个功能码。

3. 功能码

功能码占一个字节

读数据:
主机→从机
报文头----功能码---起始地址---数量
从机→主机
报文头----功能码---字节计数---数据

写单个:
主机--》从机
报文头---功能码---地址--- 通/断标志 /数据
从机--》主机
原文返回

写多个
主机-->从机
报文头---功能码--起始地址--数量--字节计数--数据
从机-->主机
报文头---功能码--起始地址--数量

主机询问数据流
00 00 00 00 00 06 0103 00 6300 02
03:功能码
0x0063:起始地址 6*16+3=99 ,40100
0002:个数 40100 40101
从机应答数据流
00 00 00 00 00 07 01 030402 1330 08
03:功能码
04:字节计数
0213 :40100数据
3008: 40101数据

练习:
1. 读传感器数据,读1个寄存器数据,写出主从数据收发协议。
00 00 00 00 00 06 11 0100 0100 01
00 00 00 00 00 04 11  01 01 00
2. 写出控制IO设备开关的协议数据,操作1个线圈,置1。
00 00 00 00 00 06 11 05 00 63 ff 00
00 00 00 00 00 06 11 0500 63 ff 00

三、工具软件的使用

1. Modbus Slave/Poll

1) 软件默认安装
2) 破解 点击connection->connect ,输入序列号即可
3) 使用 先设置从机 从机相当于服务器

image.png

image.png


C/S Client /Server
B/S Browser /Server
 

image.png




image.png

2. 网络调试助手

02 2B      555

3. wireshark的使用

4. 网络恢复

保证虚拟机关机

image.png


点击更改设置,如果此时你可以点还原默认设置,直接点还原默认设置

image.png

点击还原默认设置

image.png


等待即可
重置完后重启虚拟机

然后进入虚拟机

如何确认网络可以了
1. ping命令,ping www.baidu.com
如果ping通了则调试成功
2. 打开浏览器看一看能不能打开网页
3. ifconfig看一看网段和windows的网段一不一样

可以对多个从站地址进行排版

03功能码实现封装

05功能码实现

整体代码

//客户端架构
#include <stdio.h>
#include <stdlib.h> // atoi
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <unistd.h>
int sockfd;
void set_slave_id(uint8_t*p,uint8_t id);
void read_registers(uint8_t *p,uint16_t addr,uint16_t nb,uint8_t* dest);
void write_coil(uint8_t *p,uint16_t addr,int op,uint8_t *dest);
int main(int argc, char const *argv[])
{
    
    //1.创建套接字

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {
        perror("socket err");
        return -1;
    }
    socklen_t len = sizeof(struct sockaddr_in);
    struct sockaddr_in s;
    //2.填充结构体
    s.sin_family = AF_INET;
    s.sin_port = htons(atoi(argv[2]));
    s.sin_addr.s_addr = inet_addr(argv[1]);

     //3.连接
    if (connect(sockfd, (struct sockaddr *)&s, len) < 0)
    {
        perror("connect err");
        return -1;
    }

    //实现03功能码 
    uint8_t buf[32]={0};
    uint8_t data[32]={0};
    set_slave_id(buf,0x02);
//     read_registers(buf,0x0000,0x0002,data);
// //  buf 00 00 00 00 00 06 01 03 00 00 00 02   
//     for (int i = 0; i < data[8]; i++)
//     {
//         printf("%02x ",data[9+i]);
//     }
//     printf("\n");
    write_coil(buf,0x0000,0,data);
    close(sockfd);
    return 0;
}
//buf 00 00 00 00 00 06 xx 03 00 00 00 00
//  buf 00 00 00 00 00 06 xx 03 xx xx xx xx
//设置从站地址
void set_slave_id(uint8_t*p,uint8_t id)
{
    p[6]=id;
}
//03功能码  读保持寄存器 发送的数组地址 指定其起始地址 指定数量 接收地址
void read_registers(uint8_t *p,uint16_t addr,uint16_t nb,uint8_t* dest)
{
    p[5]=0x06;
    p[7]=0x03;
    p[8]=addr >> 8; // 0000 0000 0000 0001
    p[9]=addr ;

    p[10]=nb >> 8;
    p[11]=nb ;

    //主机发送请求数据
    send(sockfd,p,32,0);
    //接收从机的回复
    recv(sockfd,dest,32,0);    
}

//05功能码函数
}

四、Modbus RTU

1.与Modbus TCP的区别

在一般工业场景使用modbus RTU的场景还是更多一些,modbus RTU基于串行协议进行收发数据,包括RS232/485等工业总线协议。
与modbus TCP不同的是RTU没有报文头MBAP字段,但是在尾部增加了两个CRC检验字节(CRC16),因为网络协议中自带校验,所以在ModbusTCP协议中不需要使用CRC校验码。
RTU和TCP的总体使用方法基本一致,只是在创建modbus对象时有所不同,TCP需要传入网络socket信息;而RTU需要传入串口相关信息。
2、 Modbus RTU特点
Modbus RTU也是主从问答协议,由主机发起,一问一答
设置串口参数:
波特率为9600,8位数据位,1位停止位,无流控

当两台设备进行串口通信,假如他们对数据的处理速度不同。如果接收端数据缓冲区已满,则此时继续发送来的数据就会丢失。使用流控机制时,当接收端数据处理能力饱和时,就发出“不再接收”的信号,发送端就停止发送,直到接收端处理能力释放,发送“可以继续发送”的信号给发送端时,发送端才继续发送数据;

3、 Modbus RTU协议格式
ModbusRTU数据帧包含:地址码 功能码 数据 校验码
地址码:从机ID
功能码:同TCP
数据: 起始地址
校验码:2个字节,对地址码 功能码 数据进行校验,可以通过函数自动生成
4、 报文详解
03功能码为例
主机→从机
        01 03 00 00 00 01 84 0A
01:地址码 从机id
03:功能码 读保持寄存器
00 00:起始地址
00 01:数量
84 0A:校验码
从机→主机
        01 03 02 00 14 B4 44
01:地址码 从机地址
03:功能码
02:字节计数
00 14:数据
B4 44:校验码

五、模拟器的使用

由于实际硬件产品成本较高,我们这里可以使用Modbus软件模拟器,进行数据模拟从而分析Modbus协议。
使用工具:
1. ModbusPoll(模拟主机)和ModbusSlave(模拟从机)服务器
2. vspd虚拟串口
3. UartAssist串口调试工具
设置串口参数要求:波特率为9600 8位数据位 1位停止位 无流控 无校验
虚拟串口的使用:
一、 虚拟串口的安装
1. 将压缩包解压后,双击vspd.exe文件进行安装

2.安装完成后,找到安装目录,将Cracked下的文件复制到软件安装目录
3. 打开软件

添加COM1和COM2端口(用完之后记得删除端口)
4.添加完端口后,打开设备管理器,这里出现如下图所示即可。






二、虚拟机绑定端口
1. 将虚拟机在系统关机(必须是关机状态,挂起不行)状态下,点击虚拟机->设置->硬件->添加串行端口,添加COM1
2. 添加完成后,第一次使用需要将电脑重启
3. 重启之后,打开虚拟机,点击虚拟机->可移动设备->串行端口->连接
4. 当连接上虚拟串口后,在终端输入dmesg | grep tty,可以查看到对应的设备文件,其中默认的会有ttyS0文件,剩下的就是虚拟串口对应的设备文件

三、 测试通信
1.Windows打开串口调试工具,选择好串口COM2->COM1,设置对应的波特率

2. 在虚拟机运行minicom
在虚拟机安装minicom软件
sudo apt-get install minicom
在终端执行sudo minicom -s
1)选择serial port setup,回车

2)设置设备文件,波特率,关闭流控,按如下图设置(文件改成自己的)

\3)修改完成后,回车,保存修改,选择save setup as dfl,敲回车,再次选择exit回车

4)退出后就可以和windows下的串口调试工具进行通信测试
5)也可以在这个界面输入字符,查看串口助手的显示情况。

6)退出:ctrl+A、Z,在弹出的界面里输入X,即可退出。
将Modbus Slave模拟器作为RTU设备的从机
虚拟机绑定COM1端口,slave连接COM2端口,虚拟机通过编程测试串口通信
Modbus Slave端的配置如下:

五、可能会遇到的问题
1. 虚拟串口完成主机与vmware下虚拟机进行串口通信
https://blog.csdn.net/baidu_33232390/article/details/54954931
2. VSPD虚拟串口工具——从此告别硬件串口调试
https://blog.csdn.net/qq_34202873/article/details/88391265
3. vmware虚拟机检测不到vspd虚拟串口问题
https://blog.csdn.net/readnap/article/details/116659657
实现03功能码

#include "Crc_Calc.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
//串口实现ModbusRtu 并完成03功能码某一功能
int main(int argc, char const *argv[])
{
    //1.打开串口文件

    //2.初始化串口

    //3.创建要发送的03功能码数组
    // 01 03 00 00 00 01

    //4.根据创建的数组产生CRC校验,大小两个字节

    //5.把生成的CRC校验码放到要发送的03功能码数组中

    //6.往串口文件中写入拼好的03功能码数组

    //7.接收从机回应--即往串口文件中读取信息

    //8.打印从机回应

    //9.关闭文件

    return 0;
}

六、 Modbus库

库的安装
1. 在linux中解压压缩包
tar -xvf libmodbus-3.1.7.tar.gz
2. 进入源码目录,创建文件夹(存放头文件、库文件)
cd libmodbus-3.1.7
mkdir install
3. 执行脚本configure,进行安装配置(指定安装目录)
./configure--prefix=$PWD/install
4. 执行make和make install
make //编译
make install //安装
执行完成后会在install文件夹下生产对应的头文件、库文件件夹install,用于存放产生的头文件、库文件等
库的使用
要想编译方便,可以将头文件和库文件放到系统路径下
sudo cp install/include/modbus/*.h /usr/include
sudo cp install/lib/* -r /lib -d
后期编译时,可以直接gcc xx.c -lmodbus
头文件默认搜索路径:/usr/include 、/usr/local/include
库文件默认搜索路径:/lib、/usr/lib

函数接口

modbus_t*   modbus_new_tcp(const char *ip, int port)
功能:以TCP方式创建Modbus实例,并初始化
参数:
    ip   :ip地址
    port:端口号
返回值:成功:Modbus实例
      失败:NULL
    
int modbus_set_slave(modbus_t *ctx, int slave)
功能:设置从机ID
参数:
    ctx   :Modbus实例
    slave:从机ID
返回值:成功:0
       失败:-1
       
int   modbus_connect(modbus_t *ctx)
功能:和从机(slave)建立连接
参数:
    ctx:Modbus实例
返回值:成功:0
       失败:-1

void   modbus_free(modbus_t *ctx)
功能:释放Modbus实例

参数:ctx:Modbus实例
void   modbus_close(modbus_t *ctx)

功能:关闭套接字
参数:ctx:Modbus实例

int modbus_read_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest)
功能:读取线圈状态,可读取多个连续线圈的状态(对应功能码为0x01)
参数:
    ctx   :Modbus实例
    addr :寄存器起始地址
    nb    :寄存器个数
    dest :得到的状态值
int  modbus_read_input_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest)
功能:读取输入状态,可读取多个连续输入的状态(对应功能码为0x02)
参数:
    ctx   :Modbus实例
    addr :寄存器起始地址
    nb   :寄存器个数
      失败:-1

编程流程

1. 创建实例
modbus_new_tcp
2. 设置从机ID
modbus_set_slave
3. 建立连接
modbus_connect
4. 寄存器操作
功能码所对应的函数
5. 关闭套接字
modbus_close
6. 释放实例
modbus_free

练习:通过库函数实现03功能码采集数据
注意:编译不要忘了链接库、查看网络是否能用,查看slave端协议是否正确,查看slave端是否有对应的寄存器类型,查看slave id是否一致
gcc modbus.c -lmodbus


完成以下任务:
1.任务:编程实现采集传感器数据和控制硬件设备(传感器和硬件通过slave模拟)
传感器:2个,光线传感器、加速度传感器
硬件设备:2个,led灯、蜂鸣器
要求:
1.多任务编程:多线程
2.循环1s采集一次数据,并将数据打印至终端
3.同时从终端输入指令控制硬件设备
0 1 :led灯打开
0 0:led灯关闭
1 1:蜂鸣器开
1 0 : 蜂鸣器关
记得链接库 -lmodbus -lpthread

基于WebServer的工业数据采集项目

一、 http简介
HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于Web Browser(浏览器)到Web Server(服务器)进行数据交互的传输协议。
HTTP是应用层协议,基于TCP通信协议传输来传递数据(HTML 文件, 图片文件, 查询结果等)
HTTP协议工作于B/S架构上,浏览器作为HTTP客户端通过URL主动向HTTP服务端即WEB服务器发送所有请求,Web服务器根据接收到的请求后,向客户端发送响应信息。
HTTP默认端口号为80,但是你也可以改为8080或者其他端口
二、 http特点
HTTP是短连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
HTTP是媒体独立的:这意味着,只要客户端和服务器知道如何处理的数据内容,任何类型的数据都可以通过HTTP发送。客户端以及服务器指定使用适合的MIME-type内容类型。
HTTP是无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。

三、 Http协议格式

1)客户端请求消息格式
客户端发送一个HTTP请求到服务器的请求消息包括以下格式:请求行、请求头部、空行和请求数据四个部分组成,下图给出了请求报文的一般格式。

请求行是由请求方法字段、url字段、http协议版本字段3个部分组成。请求行定义了本次请求的方式,格式如下:GET /example.html HTTP/1.1(CRLF)。
5、对于参数的数据类型,get只接受ASCII字符,而post没有限制。
b. 请求头:
也被称作消息报头,请求头是由一些键值对组成,每行一对,关键字和值用英文冒号“:”分隔。允许客户端向服务器发送一些附加信息或者客户端自身的信息,典型的请求头如下:
Accept:作用:描述客户端希望接收的 响应body 数据类型;示例:Accept:text/html
Accept-Charset:作用:浏览器可以接受的字符编码集;示例:Accept-Charset:utf-8
Accept-Language:作用:浏览器可接受的语言;示例:Accept-Language:en
Connection:作用:表示是否需要持久连接,注意HTTP1.1默认进行持久连接;示例:Connection:close
Content-Length:作用:请求的内容长度:示例:Content-Length:348
Content-Type:作用:描述客户端发送的 body 数据类型
c. 空行:最后一个请求头之后是一个空行,发送回车符和换行符,通知服务器以下不再有请求头。
d. 请求体:请求数据:请求数据不在GET方法中使用,而是在POST方法中使用。POST方法适用于需要客户填写表单的场合。与请求数据相关的最常使用的请求头是Content-Type和Content-Length。
2)服务器响应消息格式
HTTP响应也由四个部分组成,分别是:状态行、消息报头、空行和响应正文。
状态行:由三部分组成,HTTP协议的版本号、状态码、以及对状态码的文本描述。例如:HTTP/1.1 200 OK(CRLF) 。(200表示请求已经成功)

HTML

开发环境:vscode

可以在 www/root下面新建一个文件,例如:example.html

安装库open in browser

库安装完成后,在编写文本位置右击->open in other browser->选择合适的浏览器即可在网页显示html标签内容

输入html,选择html:5或者!回车可以将框架进行搭建

2. Html简介

HTML(英文Hyper Text Markup Language的缩写)中文译为“超文本标记语言”。是用来描述网页的一种语言。

所谓超文本,因为它可以加入图片、声音、动画、多媒体等内容,不仅如此,它还可以从一个文件跳转到另一个文件,与世界各地主机的文件连接。

HTML 不是一种编程语言,而是一种标记语言 (markup language)

Web 浏览器的作用是读取 HTML 文档,并以网页的形式显示出它们。浏览器不会显示 HTML 标签,而是使用标签来解释页面的内容

3.html标签

1.标签格式:

(1)有尖括号包围的关键字,如:<html>

(2)通常成对存在,如:<body> </body>

(3)上面的标签前面是开始标签,后面是结束标签

2.标签分类:

(1)单标签:也称空标签 <标签名 /> 如:<br/>

(2)双标签:成对存在 <标签名> 内容 </标签名>

常用标签:

1)h1-h6标题标签

格式:<hn> 标题文本 </hn>

举例:

<h1>这是标题标签</h1>

<h2>这是标题标签</h2>

<h3>这是标题标签</h3>

<h4>这是标题标签</h4>

<h5>这是标题标签</h5>

<h6>这是标题标签</h6>

2)p段落标签:

一个段落中会根据浏览器窗口的大小自动换行

格式:<p> 文本内容 </p>

3)br换行标签:

格式:<br />

4)div标签:

是一个块级元素,可以把文档分割为独立的、不同的部分,可以在div中嵌套标签

举例:

<div class="news">

<h2>News headline 1</h2>

<p>some text. some text. some text...</p>

</div>

注:可以给div设置class或id,通过选择器设置属性,则内部成员具有相同属性

5)Input表单标签:

表示输入意思,是单标签

格式:<input type=”” name=”” value=”” id=””.....>

属性有多种:

这里重点讲type为text、radio
当type为text,表示是文本输入框
        用法:<input type=”text” value=”文本框默认值” >

当type为radio,表示是单选框

        用法:<input type=”radio” name=”控件名称” value=”提交的数值” οnclick=”处理函数” checked=”checked”>

        解释:name:控件名称,同一组单选框设置相同名称

                //Value:必须要有,是当点击时会提交的数据

                Onclick:点击时会执行双引号中的处理函数

                Checked:默认选中,同一组中只设置一个即可

用‘,’拆分响应的字符串

var rep=response.split(',');

600,700

rep[0]=600

rep[1]=700

WebServer

基础服务器

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <unistd.h>

#define PORT 80
#define BUFFER_SIZE 1024

void handle_request(int client_socket) {

    char buffer[BUFFER_SIZE];
    char response[] = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<html><body><h1>Hello, World!</h1></body></html>";

    // 从客户端读取请求
    ssize_t bytes_read = read(client_socket, buffer, BUFFER_SIZE - 1);
    if (bytes_read == -1) {
        perror("读取请求失败");
        return;
    }
    buffer[bytes_read] = '\0';

    // 打印请求内容
    printf("收到请求:\n%s\n", buffer);

    // 发送响应给客户端
    ssize_t bytes_written = write(client_socket, response, strlen(response));
    if (bytes_written == -1) {
        perror("发送响应失败");
    }

}

int main() {
}

强化服务器原码分析

web服务器原码分析 (qq.com)
1. 初始化服务器
2. 循环等待连接,连接后创建线程,调用msg_request函数,并在该函数中继续调用handler_msg函数分析数据
3. handler_msg中,首先查看协议内容,其次获取请求方法、url、参数,判断方法是什么并对need_handler赋值,确定请求资源路径,如果请求地址没有携带任何资源,那么默认返回index.html,如果资源不存在就返回404.如果需要处理(post请求或get请求带参数),调用handle_request函数,如果不需要(get请求不带参数)echo_www,直接返回资源
4. handle_request主要用来获取post请求消息正文,调用parse_and_process函数处理正文内容(需要自己添加需要功能)

安装使用postman

结合Modbus部分整体流程分析

通过postman模拟浏览器,实现Modbus Slave端数据采集和设备控制

注意:

存在共享内存和消息队列数据收发问题时。

解决方案:

  1. 在代码中加打印语句,确保两个进程用的是同一个id
  2. 由于程序是强制结束,再下次运行代码时,将消息队列删除一下查看和删除共享内存和消息队列:

        ipcs -m :查看共享内存

        ipcrm -m shmid:删除共享内存

        ipcs -q:查看消息队列

        ipcrm -q semid:删除消息队列

key值的创建路径指定/目录下的某个新建文件

多使用打印语句,排查错误位置

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

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

相关文章

Harmony(鸿蒙)使用之Bugly的简单使用

Bugly环境&#xff1a;Bugly Harmony 版本&#xff0c;支持Harmony OS Next平台 开发工具版本&#xff1a;DevEco Studio NEXT Developer Beta1&#xff08;以上&#xff09;&#xff0c;API 12 步骤一、创建产品&#xff0c;填写产品相关信息 1、注册完成后&#xff0c;可在…

R 语言学习教程,从入门到精通,R 绘图 中文支持(25)

1、R 绘图 中文支持 不同系统的字体库目录&#xff1a; Linux 一般在 /usr/share/fonts 下&#xff0c;我们可以使用 fc-list 命令查看&#xff1a; # fc-list /usr/share/fonts/truetype/dejavu/DejaVuSerif-Bold.ttf: DejaVu Serif:styleBold /usr/share/fonts/truetype/de…

vue事件监听

我们可以使用 v-on 指令 (简写为 ) 来监听 DOM 事件&#xff0c;并在事件触发时执行对应的 1.回车事件&#xff08;点击回车触发&#xff09; confirm 适用uni-app keyup.enter 适用vue3 运用场景&#xff1a;通常在文本框输入的时候使用 2.点击事件&#xff08;鼠标左键…

基于ZYNQ FPGA+DSP C6678坚固型高性能数据采集与运动控制系统

基于FPGADSP的实时控制系统架构的坚固型高性能运动控制器&#xff0c;支持多通道并行同步实时高速采样&#xff0c;并直接通过底层逐点传递给DSP算法处理&#xff0c;以保证实时性&#xff0c;可以实现高速的逐点控制输出&#xff0c;确保了控制系统能够在多输入多输出高速控制…

PDF文件的读取与合并:使用PyPDF2与ReportLab

目录 一、PyPDF2库基础 1.1 PyPDF2简介 1.2 安装PyPDF2 1.3 读取PDF内容 1.4 合并PDF文件 二、ReportLab库基础 2.1 ReportLab简介 2.2 安装ReportLab 2.3 使用ReportLab生成PDF文本 2.4 ReportLab 与 PyPDF2 结合使用 三、注意事项与最佳实践 3.1 文本提取的局限性…

HW数通IA笔记2-网络参考模型

目录 零、本章主要内容 一、应用和数据 二、网络参考模型与标准协议 2.2 TCP/IP参考模型 2.3 TCP/IP常见协议 2.3.1 应用层 2.3.2 传输层 2.3.3 网络层 2.3.4 数据链路层 2.3.5 物理层 2.4 常见的协议标准化组织 三、数据的通信过程 零、本章主要内容 1、理解数据的…

高级MySQL数据库备份脚本

高级MySQL数据库备份脚本 主要功能项目构成credentials.txtsettings.confmysql-dump.sh SFTP备份配置&#xff1a;生成 SSH 密钥对将公钥复制到 SFTP 服务器测试无密码登录 邮件发送配置安装插件sendmail、mailx修改mail配置获取邮箱授权码 如何执行备份执行备份脚本计划每日的…

【数据结构-前缀异或和】力扣1371. 每个元音包含偶数次的最长子字符串

给你一个字符串 s &#xff0c;请你返回满足以下条件的最长子字符串的长度&#xff1a;每个元音字母&#xff0c;即 ‘a’&#xff0c;‘e’&#xff0c;‘i’&#xff0c;‘o’&#xff0c;‘u’ &#xff0c;在子字符串中都恰好出现了偶数次。 示例 1&#xff1a; 输入&…

PyCharm 自定义字体大小

常用编程软件自定义字体大全首页 文章目录 前言具体操作1. 打开设置对话框2. 设置编辑器字体3. 选择外观字体 前言 PyCharm 自定义字体大小&#xff0c;统一设置为 JetBrains Mono 具体操作 【File】>【Settings...】>【Editor】>【Font】 统一设置为字体样式 JetB…

JVM上篇:内存与垃圾回收篇-13-垃圾回收器

笔记来源&#xff1a;尚硅谷 JVM 全套教程&#xff0c;百万播放&#xff0c;全网巅峰&#xff08;宋红康详解 java 虚拟机&#xff09; 文章目录 13. 垃圾回收器13.1. GC 分类与性能指标13.1.1. 垃圾回收器概述13.1.2. 垃圾收集器分类13.1.3. 评估 GC 的性能指标吞吐量暂停时间…

X86架构(五)——栈操作与寻址操作

我们先采用 X86架构(四) 所学知识&#xff0c;在显示器上显示 123...100 ;代码清单7-1;文件名&#xff1a;c07_mbr.asm;文件说明&#xff1a;硬盘主引导扇区代码;创建日期&#xff1a;2011-4-13 18:02jmp near __startmessage db 123...100 __start:mov ax, 0x7c0 ;数据段基…

APP封装安装配置参考说明

APP封装安装配置参考说明 一, 环境准备 宝塔环境 nginx php5.6 mysql5.6 java-openjdk1.8 apktool 1,安装 nginx,php,mysql自行安装 java-openjdk1.8 安装 推荐使用命令行安装 1.1 yum install java-1.8.0-openjdk1.2 yum install -y java-1.8.0-openjdk-devel1.3 设置…

Intellij Idea + Git 完美实战!

环境准备 使用前需要安装一个远程的 Git 仓库和本地的 Git 客户端。由于IDEA中的Git插件需要依赖本地Git客户端&#xff0c;所以需要进行如下配置&#xff1a; 如果本地已有项目&#xff0c;直接通过如下操作&#xff0c;即可在远程自动创建仓库并关联 1. 克隆远程仓库代码&am…

halcon4

图像采集助手-Image Aequisition 1.配置相机IP 和巨型帧等 2.通过海康MVS软件 找到 对应halcon 版本 3. 找到对应halcon版本的 海康相机文件 4.找到Halocn文件目录 粘贴上图文件 通过halcon 助手 -Image Aequisition -自动检测 -找到MVision接口 连接相机 采集图像 实时…

一句话概括TMMi的每个PA

TMMi&#xff08;Test Maturity Model Integration&#xff0c;测试成熟度模型集成&#xff09;是一个由TMMi基金会开发的非商业化的测试成熟度模型&#xff0c;是对CMMI模型的一个补充。它可以帮助组织使测试过程从未管理的状态进化为已管理、已定义、已测量和优化的状态。 T…

网站建设完成后,视频类网站如何做seo

视频类网站的SEO优化是一个综合性的工作&#xff0c;涉及从内容优化、技术优化到外部链接建设等多个方面。由于视频类网站主要提供的是视频内容&#xff0c;其SEO优化不仅需要关注常规的网页优化技巧&#xff0c;还需要考虑视频特有的元素和用户行为模式。以下是针对视频类网站…

Xilinx高速接口之GTP

简介 开坑计划中&#xff0c;主要参考ug482 主要讲解结构以及原语 以及时钟路由和一些其他的 GTP_COMMON还好&#xff0c;需要设置的不多&#xff0c;原语也短&#xff0c; GTP_CHANNEL需要设置的东西真多&#xff0c;原语也长 还好有官方参考例程以及自动生成的原语例化 不然…

0基础学习Python路径(31)logging模块

Python logging 模块定义了为应用程序和库实现灵活的事件日志记录的函数和类。 程序开发过程中&#xff0c;很多程序都有记录日志的需求&#xff0c;并且日志包含的信息有正常的程序访问日志还可能有错误、警告等信息输出&#xff0c;Python 的 logging 模块提供了标准的日志接…

OpenCV绘图函数(4)绘制轮廓线的函数drawContours()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 函数会在图像中绘制轮廓线&#xff0c;如果 thickness ≥ 0&#xff0c;则绘制轮廓线&#xff1b;如果 thickness < 0&#xff0c;则填充由轮…

【JLINK】RTT Viewer 的使用

​​​​​​ 一、使用说明 1.1 查找 RTT 缓冲区的开始位置 echo off if exist .\Debug\%PRJ_NAME%.map (findstr /C:" _SEGGER_RTT" .\Debug\%PRJ_NAME%.map rem findstr /C:" __StackTop " .\Debug\%PRJ_NAME%.map rem findstr /C:" Reset_Handle…