当前位置: 首页 > news >正文

Day7 FIFO与鼠标控制

文章目录

      • 1. harib04a例程(获取按键编码)
      • 2. harib04b例程(加快中断处理)
      • 3. harib04c例程(FIFO缓冲区)
      • 4. harib04d例程(改善FIFO缓冲区)
      • 5. harib04e例程(整理FIFO缓冲区)
      • 6. harib04f例程(激活鼠标)
      • 7. harib04g例程(从鼠标接收数据)

1. harib04a例程(获取按键编码)

上一章的例程中可以获取到键盘按下一次按键的状态,但是没办法使鼠标移动,其原因主要还是对于鼠标的设定不充足。
程序改善为,按下一个键后不结束,而是把所按键的编码显示在屏幕中。于是,修改int.c中的inthandler21函数:

#define PORT_KEYDAT 	0x0060
void inthandler21(int *esp)
{struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO;unsigned char data, s[4];io_out8(PIC0_OCW2, 0x61);	// 通知PIC,已知发生了IRQ01中断data = io_in8(PORT_KEYDAT);sprintf(s, "%02X", data);boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 0, 16, 15, 31);putfonts8_asc(binfo->vram, binfo->scrnx, 0, 16, COL8_FFFFFF, s);return;
}

在代码中,io_out8(PIC0_OCW2, 0x61);用来通知PIC,已经知道发生了IRQ1中断,如果是IRQ3,则写为0x63,即将0x60+IRQ号码输出给OCW2。执行完这行代码之后,PIC会继续监视IRQ1中断是否发生。反过来如果忘记执行这句话,键盘下次再有动作,操作系统就无法感知到了。
在这里插入图片描述
如此以来,按下键和松开键,屏幕上就会显示不同的东西。

2. harib04b例程(加快中断处理)

所谓中断处理,就是打断CPU正在手头的工作,加塞处理另一个事情,所以必须完成的干净利索,而且中断处理进行期间,不再接受其他的中断。如果处理键盘的中断速度太慢就会导致鼠标的运动不连贯或不能从网络中获取数据等情况。
因此,字符显示最好不要出现在在中断处理函数中。字符显示需要花费较大的时间,显示一个字符首先需要做128次if判断,来决定是否往VRAM里描绘该像素;如果需要进行描绘,就会接着执行内存写入指令;为确认往内存哪个地方写,还需要计算地址。
将按键的编码缓存在一个变量中,然后由HariMain偶尔去查看这个变量,如果发现有数据,就把他显示出来。

/*bootpack.h*/
struct KEYBUF {unsigned char data, flag;
};/*int.c*/
struct KEYBUF keybuf;
void inthandler21(int *esp)
{unsigned char data;io_out8(PIC0_OCW2, 0x61);	/* 通知PIC,已知发生了IRQ01中断 */data = io_in8(PORT_KEYDAT);if (keybuf.flag == 0) {keybuf.data = data;keybuf.flag = 1;}return;
}

其中,flag变量用于表示缓冲区是否为空(0为空,1为缓冲区中有数据)。如果缓冲区中有数据,而此时又来了一个中断,则不做处理,把这个数据丢掉。
在HariMain中偶尔去查看这个变量:

/*bootpack.h*/
for (;;) {io_cli();if (keybuf.flag == 0) {io_stihlt();} else {i = keybuf.data;keybuf.flag = 0;io_sti();sprintf(s, "%02X", i);boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 0, 16, 15, 31);putfonts8_asc(binfo->vram, binfo->scrnx, 0, 16, COL8_FFFFFF, s);}
}

首先使用io_cli屏蔽中断,防止在查看已保存的全局变量时,有其他中断进来。如果flag为0,则表示没有中断发生,由于此时已经执行完了io_cli屏蔽中断,所以需要执行STI用于解除中断屏蔽,并HLT,因此可以使用io_stihlt表示同时执行STI和HLT。(根据CPU规范,在STI和HLT两个指令之间的中断,不做处理,因此只能执行io_stihlt,而不能执行io_sti + io_hlt)。
else,即如果flag为1时,把data缓存到变量i中,并把flag清零,最后再通过io_sti取消中断的屏蔽。
但是当前还存在一个有问题的现象,例如,右Ctrl键会产生两个字节的键码,按下时为“E0 1D”,松开时为“E0 9D”,在这种情况下,因为键盘的内部电路,一次只能发送一个字节,所以一次按下就会产生两次中断,第一次中断发送E0,第二次发送1D。在harib04b中,对这种情况的处理,就会只显示一个E0,因为它会先屏蔽中断,再去检查flag。
在这里插入图片描述

3. harib04c例程(FIFO缓冲区)

制作一个先进先出的缓冲区,缓存多个中断。

/* bootpack.h */
struct KEYBUF {unsigned char data[32];int next;
};/* int.c */
void inthandler21(int *esp)
{unsigned char data;io_out8(PIC0_OCW2, 0x61);data = io_in8(PORT_KEYDAT);if (keybuf.next < 32) {keybuf.data[keybuf.next] = data;keybuf.next++;}return;
}/* bootpack.c */
for (;;) {io_cli();if (keybuf.next == 0) {io_stihlt();} else {i = keybuf.data[0];keybuf.next--;for (j = 0; j < keybuf.next; j++) {keybuf.data[j] = keybuf.data[j + 1];}io_sti();sprintf(s, "%02X", i);boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 0, 16, 15, 31);putfonts8_asc(binfo->vram, binfo->scrnx, 0, 16, COL8_FFFFFF, s);}
}

在inthandler21函数中,对每次中断都记录到缓冲区data中;然后在HariMain中每次访问下标为0的那一个,并把后面的元素往前移。这样就可以在按下右Ctrl时显示1D,松开时显示9D。
在这里插入图片描述
但现在存在的一个问题就是,数据往前移动的这个动作,发生在屏蔽中断的时候,如果数据比较多,这也是一个需要花费大时间的操作。

4. harib04d例程(改善FIFO缓冲区)

双指针+循环buffer思想,一个表示读操作的下标,一个表示写操作的下标,并添加一个字段len用于记录缓冲区中当前存在多少个未读取的数据。

/* bootpack.h */
struct KEYBUF {unsigned char data[32];int next_r, next_w, len;
};/* int.c */
void inthandler21(int *esp)
{unsigned char data;io_out8(PIC0_OCW2, 0x61);data = io_in8(PORT_KEYDAT);if (keybuf.len < 32) {keybuf.data[keybuf.next_w] = data;keybuf.len++;	// data写入buf时,len+1keybuf.next_w++;if (keybuf.next_w == 32) {keybuf.next_w = 0;}}return;
}/* bootpack.c */
for (;;) {io_cli();if (keybuf.len == 0) {io_stihlt();} else {i = keybuf.data[keybuf.next_r];keybuf.len--;	// data读出buf时,len-1keybuf.next_r++;if (keybuf.next_r == 32) {keybuf.next_r = 0;}io_sti();sprintf(s, "%02X", i);boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 0, 16, 15, 31);putfonts8_asc(binfo->vram, binfo->scrnx, 0, 16, COL8_FFFFFF, s);}
}

5. harib04e例程(整理FIFO缓冲区)

实际上,鼠标动一下,会发出3个字节的数据。修改FIFO缓冲区,使它称为一个更加通用的先进先出缓冲区。

/* bootpack.h */
/*
* buf  	: 缓冲区地址
* p		: 可写入位置
* q		: 可读出位置
* size	: 缓冲区总字节数大小
* free	: 可写入的缓冲区字节数大小
* flags	: 记录是否溢出(free == 0)
*/
struct FIFO8 {unsigned char *buf;int p, q, size, free, flags;
};/* fifo.c */
#define FLAGS_OVERRUN		0x0001
void fifo8_init(struct FIFO8 *fifo, int size, unsigned char *buf)
{fifo->size = size;fifo->buf = buf;fifo->free = size;fifo->flags = 0;fifo->p = 0;fifo->q = 0;return;
}/*
* ret	:0, 无溢出;1, 溢出。
*/
int fifo8_put(struct FIFO8 *fifo, unsigned char data)
{	// 往缓冲区中写数据if (fifo->free == 0) {/* 读出速度小于写入速度,缓冲区溢出 */fifo->flags |= FLAGS_OVERRUN;return -1;}fifo->buf[fifo->p] = data;fifo->p++;if (fifo->p == fifo->size) {fifo->p = 0;}fifo->free--;return 0;
}int fifo8_get(struct FIFO8 *fifo)
{	// 从缓冲区中读出数据int data;if (fifo->free == fifo->size) {/* 缓冲区无数据 */return -1;}data = fifo->buf[fifo->q];fifo->q++;if (fifo->q == fifo->size) {fifo->q = 0;}fifo->free++;return data;
}int fifo8_status(struct FIFO8 *fifo)
{	/* 缓冲区存在数据的个数 */return fifo->size - fifo->free;
}

如此以来,inthandler21则只需要调用fifo8_put即可。HariMain函数中调用fifo8_init初始化fifo,并fifo8_get即可。

/* int.c */
#define PORT_KEYDAT		0x0060
struct FIFO8 keyfifo;
void inthandler21(int *esp)
{unsigned char data;io_out8(PIC0_OCW2, 0x61);	/* IRQ-01��t�����PIC���m */data = io_in8(PORT_KEYDAT);fifo8_put(&keyfifo, data);return;
}/* bootpack.c */
extern struct FIFO8 keyfifo;char s[40], mcursor[256], keybuf[32];
fifo8_init(&keyfifo, 32, keybuf);
for (;;) {io_cli();if (fifo8_status(&keyfifo) == 0) {io_stihlt();} else {i = fifo8_get(&keyfifo);io_sti();sprintf(s, "%02X", i);boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 0, 16, 15, 31);putfonts8_asc(binfo->vram, binfo->scrnx, 0, 16, COL8_FFFFFF, s);}
}

6. harib04f例程(激活鼠标)

鼠标作为外设接入计算机是较靠后的事情了。最初,如果期望使用鼠标,需要先执行激活鼠标的指令,才能产生鼠标的中断。所谓不产生鼠标中断,就是说即使鼠标发来数据,CPU也不会接收,所以,处于初期状态的鼠标,无论怎么操作,都不会有反应。
在这里插入图片描述
因此,如果期望正常使用鼠标,需要先让鼠标控制电路生效,再让鼠标生效。事实上,鼠标控制电路被包含在键盘控制电路中,如果键盘控制电路初始化完成,则鼠标电路控制器的激活也完成了。

	/* bootpack.c节选 */
#define PORT_KEYDAT				0x0060
#define PORT_KEYSTA				0x0064
#define PORT_KEYCMD				0x0064
#define KEYSTA_SEND_NOTREADY	0x02
#define KEYCMD_WRITE_MODE		0x60
#define KBC_MODE				0x47void wait_KBC_sendready(void)
{	/* 等待键盘控制电路准备完毕 */for (;;) {if ((io_in8(PORT_KEYSTA) & KEYSTA_SEND_NOTREADY) == 0) {break;}}return;
}void init_keyboard(void)
{	/* 初始化键盘控制电路 */wait_KBC_sendready();io_out8(PORT_KEYCMD, KEYCMD_WRITE_MODE);wait_KBC_sendready();io_out8(PORT_KEYDAT, KBC_MODE);return;
}#define KEYCMD_SENDTO_MOUSE		0xd4
#define MOUSECMD_ENABLE			0xf4void enable_mouse(void)
{	/* 激活鼠标 */wait_KBC_sendready();io_out8(PORT_KEYCMD, KEYCMD_SENDTO_MOUSE);wait_KBC_sendready();io_out8(PORT_KEYDAT, MOUSECMD_ENABLE);return;
}

wait_KBC_sendready函数(keyboard controller)的作用是使键盘控制电路做好准备,以等待控制指令的到来(因为键盘控制电路的速度不如CPU电路快)。如果控制电路可以接收CPU指令了,CPU从0x0064设备读到的低第2bit应该为0,在等到0之前,函数一直在for循环。
init_keyboard函数,一边确认键盘控制电路是否准备好,一边发送指令用于设定模式。设定模式的指令是0x60,使用鼠标模式的指令是0x47。通过在HariMain中调用init_keyboard就可以等待鼠标模式设定完成。
enable_mouse函数,向键盘控制电路中发送0xd4和0xf4,用于激活鼠标(如果向键盘控制电路中发送0xd4,则下一条指令(0xf4)会自动发送给鼠标)。鼠标收到激活指令后会回复0xfa给CPU,表示后续会一直发送鼠标信息。鼠标回复的0xfa是自动回复,也会产生一个中断。
在这里插入图片描述
如图,鼠标中断来了。

7. harib04g例程(从鼠标接收数据)

/* int.c节选 */
struct FIFO8 mousefifo;void inthandler2c(int *esp)
{unsigned char data;io_out8(PIC1_OCW2, 0x64);	/* 通知PIC1(slave),IRQ-12的受理已经完成 */io_out8(PIC0_OCW2, 0x62);	/* 通知PIC0(master),IRQ-02的受理已经完成 */data = io_in8(PORT_KEYDAT);fifo8_put(&mousefifo, data);return;
}

首先通知slavePIC,IRQ12已受理完成(IRQ12是slavePIC的第4号);再通知masterPIC,IRQ02已受理完成。
获取鼠标数据的代码与获取键盘数据的代码完全一样:

/* bootpack.c节选 */
fifo8_init(&keyfifo, 32, keybuf);
fifo8_init(&mousefifo, 128, mousebuf);for (;;) {io_cli();if (fifo8_status(&keyfifo) + fifo8_status(&mousefifo) == 0) {io_stihlt();} else {if (fifo8_status(&keyfifo) != 0) {i = fifo8_get(&keyfifo);io_sti();sprintf(s, "%02X", i);boxfill8(binfo->vram, binfo->scrnx, COL8_008484,  0, 16, 15, 31);putfonts8_asc(binfo->vram, binfo->scrnx, 0, 16, COL8_FFFFFF, s);} else if (fifo8_status(&mousefifo) != 0) {i = fifo8_get(&mousefifo);io_sti();sprintf(s, "%02X", i);boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 32, 16, 47, 31);putfonts8_asc(binfo->vram, binfo->scrnx, 32, 16, COL8_FFFFFF, s);}}
}

由于鼠标会比键盘更快的发出大量数据,所以初始化鼠标的缓冲区为128字节。
当前的逻辑是,如果判断鼠标缓冲区和键盘缓冲区都为空则执行HLT;否则就先检查键盘缓冲区,再检查鼠标缓冲区。
在这里插入图片描述

相关文章:

Day7 FIFO与鼠标控制

文章目录 1. harib04a例程&#xff08;获取按键编码&#xff09;2. harib04b例程&#xff08;加快中断处理&#xff09;3. harib04c例程&#xff08;FIFO缓冲区&#xff09;4. harib04d例程&#xff08;改善FIFO缓冲区&#xff09;5. harib04e例程&#xff08;整理FIFO缓冲区&a…...

软件工程第一章习题

第1章软件与软件工程 1.选择题 (1)下列说法中正确的是( &#xff09;o A.20世纪50年代提出了软件工程的概念 B.20世纪60年代提出了软件工程的概念 C.20世纪70年代出现了客户机/服务器技术 D.20世纪80年代软件工程学科达到成熟 (2)软件危机的主要原因是( Do B.软件生产…...

Ollama 手动高速下载Win/Linux/Mac安装包及安装方法

前言 Ollama下载速度太慢&#xff0c;按这个方式&#xff0c;速度嘎嘎的快----下载地址 手动安装 如果要从以前的版本升级&#xff0c;则应删除旧库。比如&#xff1a;sudo rm -rf /usr/lib/ollama 解压 tar -C /usr -xzf ollama-linux-amd64.tgz # 解压到/usr文件夹# 如…...

Jmeter+Jenkins+Ant自动化持续集成环境搭建

一、安装准备 1.JDK:jdk-8u121-windows-x64 2.jmeter工具&#xff1a;apache-jmeter-2.13 3.ANT工具&#xff1a;apache-ant-1.9.7-bin 4.jenkins工具&#xff1a;jenkins-2.32.2 二、软件安装 1.JDK的安装 >双击JDK安装包&#xff0c;选择安装路径&#xff08;本人是…...

【11】Redis快速安装与Golang实战指南

文章目录 1 Redis 基础与安装部署1.1 Redis 核心特性解析1.2 Docker Compose 快速部署1.3 Redis 本地快速部署 2 Golang 与 Redis 集成实战2.1 环境准备与依赖安装2.2 核心操作与数据结构实践2.2.1 基础键值操作2.2.2 哈希结构存储用户信息 3 生产级应用场景实战3.1 分布式锁实…...

ISP算法.红外图像增强

在图像处理领域&#xff0c;常见的图像处理一般都是白光相机&#xff0c;实际红外相机也是常见的一种相机&#xff0c;它可以用来对发热的东西进行成像&#xff0c;也可以作为白光相机夜晚不可见的一种辅助手段&#xff0c;为白光相机赋能夜视能力。 红外相机的成像原理在于辐射…...

Spring Boot中使用RedisTemplate操作Redis的几种数据类型详解

Redis作为高性能的键值存储系统&#xff0c;在现代Java应用中扮演着重要角色。Spring Boot通过RedisTemplate为开发者提供了便捷的Redis操作方式。本文将详细介绍如何使用RedisTemplate操作Redis的五种主要数据类型。 一、RedisTemplate简介 RedisTemplate是Spring Data Redi…...

大数据与人工智能之大数据架构(Hadoop、Spark、Flink)

一、核心特性与架构设计 1. Hadoop&#xff1a;分布式批处理的基石 核心组件&#xff1a; HDFS&#xff1a;分布式文件系统&#xff0c;支持大规模数据存储。MapReduce&#xff1a;基于“分而治之”的批处理模型&#xff0c;适合离线分析。 架构特点&#xff1a; 批处理主导&…...

VSCode中Marp插件

VSCode神级插件Marp&#xff0c;用Markdown来做PPT 优秀教程&#xff1a;https://zhuanlan.zhihu.com/p/582872955...

C++20 数学常数:<numbers> 头文件的革新

文章目录 一、<numbers> 头文件中的数学常数二、使用示例三、优势与应用场景&#xff08;一&#xff09;提高代码可读性&#xff08;二&#xff09;提高精度&#xff08;三&#xff09;适用于多种数据类型&#xff08;四&#xff09;简化数学计算 四、总结 C20 标准引入了…...

OpenCV--图像平滑处理

在数字图像处理领域&#xff0c;图像平滑处理是一项极为重要的技术&#xff0c;广泛应用于计算机视觉、医学影像分析、安防监控等多个领域。在 OpenCV 这一强大的计算机视觉库的助力下&#xff0c;我们能便捷地实现多种图像平滑算法。本文将深入探讨图像平滑的原理&#xff0c;…...

【KMP】P7114 [NOIP2020] 字符串匹配|省选-

本文涉及知识点 较难理解的字符串查找算法KMP P7114 [NOIP2020] 字符串匹配 题目描述 小 C 学习完了字符串匹配的相关内容&#xff0c;现在他正在做一道习题。 对于一个字符串 S S S&#xff0c;题目要求他找到 S S S 的所有具有下列形式的拆分方案数&#xff1a; S A …...

C++20 统一容器擦除:std::erase 和 std::erase_if

文章目录 一、std::erase 的用法1.1 语法1.2 参数1.3 返回值1.4 示例 二、std::erase_if 的用法2.1 语法2.2 参数2.3 返回值2.4 示例 三、优势与应用场景3.1 统一的接口3.2 简化代码3.3 适用范围广 四、总结 C20 引入了两个非常实用的函数模板&#xff1a; std::erase 和 std…...

阿里云oss视频苹果端无法播放问题记录

记录一下苹果端视频不可以播放的原因. 看了一下其他视频可以正常播放,但是今天客户发来的视频无法正常播放.咨询过阿里云售后给出的原因是编码格式过高. 需要调整编码格式为:baseline, 下面记录如何使用ffmpeg修改视频的编码格式. 下载文件(可从官方下载) 配置环境变量(系统变…...

10-MySQL-性能优化思路

1、优化思路 当我们发现了一个慢SQL的问题的时候&#xff0c;需要做性能优化&#xff0c;一般我们是为了提高SQL查询更快&#xff0c;一个查询的流程由下图的各环节组成&#xff0c;每个环节都会消耗时间&#xff0c;要减少消耗时候需要从各个环节都分析一遍。 2 连接配置优化…...

Postman之参数化详解

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 小伙伴们&#xff0c;好久不见呀&#xff0c;今天呢笔者想和大家聊聊postman参数化&#xff0c;在接口测试中&#xff0c;部分参数每次发送请求是唯一的数值&a…...

【c++深入系列】:类和对象详解(下)

&#x1f525; 本文专栏&#xff1a;c &#x1f338;作者主页&#xff1a;努力努力再努力wz &#x1f4aa; 今日博客励志语录&#xff1a; 你的人生剧本&#xff0c;不是父母的续集&#xff0c;不是子女的前传&#xff0c;更不是朋友的外传——你是自己故事的主角 ★★★ 本文前…...

浅谈「分词」:原理 + 方案对比 + 最佳实践

在文本搜索、自然语言处理、智能推荐等场景中&#xff0c;「分词」 是一个基础但至关重要的技术点。无论是用数据库做模糊查询&#xff0c;还是构建搜索引擎&#xff0c;分词都是提高效率和准确度的核心手段。 &#x1f50d; 一、什么是分词&#xff1f; 分词&#xff08;Tok…...

第十八:GC 垃圾回收

2.1 三色标记# 灰色&#xff1a;对象已被标记&#xff0c;但这个对象包含的子对象未标记黑色&#xff1a;对象已被标记&#xff0c;且这个对象包含的子对象也已标记&#xff0c;gcmarkBits对应的位为1&#xff08;该对象不会在本次GC中被清理&#xff09;白色&#xff1a;对象…...

【微机及接口技术】- 第七章 可编程定时/计数器

文章目录 第一节 定时/计数器的概述一、定时与计数二、定时方法 第二节 可编程定时/计数器8254一、8254-2的基本功能二、8254的内部结构和外部引脚三、8254 的工作方式1. 方式0&#xff1a;计数到零产生中断方式2. 方式1&#xff1a;硬件可重触发单稳方式3. 方式2&#xff1a;速…...

MES生产工单管理系统,Java+Vue,含源码与文档,实现生产工单全流程管理,提升制造执行效率与精准度

前言&#xff1a; MES生产工单管理系统是制造业数字化转型的核心工具&#xff0c;通过集成生产、数据、库存等模块&#xff0c;实现全流程数字化管理。以下是对各核心功能的详细解析&#xff1a; 一、生产管理 工单全生命周期管理 创建与派发&#xff1a;根据销售订单或生产计…...

【区块链安全 | 第三十五篇】溢出漏洞

文章目录 溢出上溢示例溢出漏洞溢出示例漏洞代码代码审计1. deposit 函数2. increaseLockTime 函数 攻击代码攻击过程总结修复建议审计思路 溢出 算术溢出&#xff08;Arithmetic Overflow&#xff09;&#xff0c;简称溢出&#xff08;Overflow&#xff09;&#xff0c;通常分…...

【自记录】ubuntu命令行下禁用指定声卡

设备上内置了一块声卡&#xff0c;出于某些原因我希望禁用他。 通过arecord -l可以查看到该设备 $ arecord -l **** List of CAPTURE Hardware Devices **** card 0: Device [USB PnP Sound Device], device 0: USB Audio [USB Audio]Subdevices: 1/1Subdevice #0: subdevice…...

设计模式 Day 4:观察者模式(Observer Pattern)深度解析

在经历了前三天的对象创建型设计模式学习之后&#xff0c;今天我们开始进入行为型设计模式的探索之旅。行为型模式聚焦于对象之间的通信机制与协作方式&#xff0c;其中最经典且应用最广泛的就是——观察者模式&#xff08;Observer Pattern&#xff09;。本文将用8000字篇幅&a…...

`QTabWidget` 的标签页头设置样式,可以通过在 QSS 文件中定义 `QTabBar::tab` 的样式

要为 QTabWidget 的标签页头设置样式&#xff0c;可以通过在 QSS 文件中定义 QTabBar::tab 的样式来实现。以下是完整的代码示例和 QSS 文件内容&#xff0c;展示如何为标签页头设置背景颜色、文本颜色、悬停效果和选中效果。 ### **代码示例** cpp #include <QApplication…...

低代码开发革命:用 ZKmall开源商城可视化逻辑编排实现业务流程再造

ZKmall开源商城通过可视化逻辑编排引擎与低代码开发范式&#xff0c;重新定义了企业级电商业务流程的构建与优化方式。本文将从技术架构、核心能力、实践案例及行业价值等维度&#xff0c;解析其如何以"低代码流程引擎"组合拳实现业务流程再造的革命性突破。 一、低代…...

CAN外设

目录 1. CAN外设结构 1.1 CAN外设发送流程 1.2 CAN外设接收流程 1.3 发送接受配置位 2. CAN外设过滤器 2.1 过滤器配置 2.2 测试模式 2.3 工作模式 2.4 过滤器对应中断 2.5 错误处理和离线恢复 1. CAN外设结构 以STM32F103为例。以下是它的内部结构框图。 其具体发…...

(七)安卓开发中的状态列表图形(StateListDrawable)详解

在安卓开发中&#xff0c;**状态列表图形&#xff08;StateListDrawable&#xff09;**是一种非常实用的资源&#xff0c;它允许开发者根据视图的不同状态&#xff08;如按下、聚焦、选中等&#xff09;来动态显示不同的图像或颜色。这种机制在创建交互式用户界面时尤为重要&am…...

2023年蓝桥杯第十四届CC++大学B组真题及代码

目录 1A&#xff1a;日期统计 解析代码_暴力_正解 2B&#xff1a;01串的熵 解析代码_暴力_正解 3C&#xff1a;冶炼金属 解析代码_暴力_正解 4D&#xff1a;飞机降落 解析代码_暴力dfs_正解 5E&#xff1a;接龙数列 解析代码_dp_正解 6F&#xff1a;岛屿个数 解析代…...

odo18实施——销售-仓库-采购-制造-制造外包-整个流程自动化单据功能的演示教程

安装模块 安装销售 、库存、采购、制造模块 2.开启外包功能 在进入制造应用点击 配置—>设置 勾选外包&#xff0c;点击保存 添加信息 一、添加客户信息 点击到销售应用 点击订单—>客户 点击新建 创建客户1&#xff0c;及其他客户相关信息&#xff0c;点…...

c++造轮子之REACTOR实战

本文实现的为单reactor 多线程(base) 非核心库 InetAddress 这个库简单而言 无疑是设置ip地址和端口 class InetAddress { public:struct sockaddr_in addr;socklen_t addr_len;InetAddress();InetAddress(const char* ip, uint16_t port);~InetAddress(); };具体而言: Ine…...

【Easylive】Elasticsearch搜索组件详解

【Easylive】项目常见问题解答&#xff08;自用&持续更新中…&#xff09; 汇总版 一、Elasticsearch基础介绍 Elasticsearch(简称ES)是一个分布式、RESTful风格的搜索和分析引擎&#xff0c;基于Apache Lucene构建。在视频平台中&#xff0c;它主要用于&#xff1a; 全…...

基于AT89C51单片机的加减乘除液晶计算机设计

点击链接获取Keil源码与Project Backups仿真图&#xff1a; https://download.csdn.net/download/qq_64505944/90574816?spm1001.2014.3001.5503 功能介绍&#xff1a; 可进行最高四位数的加减乘除运算&#xff0c;除法运算保留小数点后四位&#xff1b;4*4矩阵按键输入&…...

先进制造aps专题三十三 开源aps产品,frepple和dream对比分析

开源的两个aps产品&#xff0c;frepple和dream对比分析 frepple开源的基本不能用&#xff0c;第一它甘特图没开源&#xff0c;而且甘特图不允许你手工个修改&#xff0c;你想把它当成手工甘特图用也不行&#xff0c;第二&#xff0c;算法强制倒排&#xff0c;很少企业是倒排 …...

Vue3.2 项目打包成 Electron 桌面应用

本文将详细介绍如何将基于 Vue3.2 的项目打包成 Electron 桌面应用。通过结合 Electron 和 Vue CLI 工具链&#xff0c;可以轻松实现跨平台桌面应用的开发与发布。 1. 项目结构说明 项目主要分为以下几个部分&#xff1a; electron/main.js&#xff1a;Electron 主进程文件。…...

第16届蓝桥杯单片机模拟试题Ⅰ

试题 代码 sys.h #ifndef __SYS_H__ #define __SYS_H__#include <STC15F2K60S2.H> //onewire.c float getT(); //sys.c extern unsigned char UI; extern bit touch_mode; extern float jiaozhun; extern float canshu; extern float temper; void init74hc138(unsigned…...

ES:geoip_databases

如何查看 .geoip_databases 的内容 在Elasticsearch中&#xff0c;.geoip_databases 是一个特殊的索引&#xff0c;用于存储GeoIP数据库文件。这些文件通常用于地理信息的丰富&#xff08;GeoIP enrichment&#xff09;。以下是如何查看和管理这些数据库文件的方法&#xff1a…...

企业级开发SpringBoost玩转Elasticsearch

案例 Spring Boot 提供了 spring-data-elasticsearch 模块&#xff0c;可以方便地集成 Elasticsearch。 下面我们将详细讲解如何在 Spring Boot 中使用 Elasticsearch 8&#xff0c;并提供示例代码。 1. 添加依赖: 首先&#xff0c;需要在 pom.xml 文件中添加 spring-data-e…...

边缘计算网关作用

一、数据采集与预处理 边缘计算网关作为物联网系统的“数据入口”&#xff0c;能够连接各种传感器和设备&#xff0c;实时采集数据。在数据传输到云端之前&#xff0c;它会对数据进行清洗、过滤和聚合&#xff0c;剔除重复、无效或冗余的信息&#xff0c;只将有价值的数据上传…...

利用本地 Express Web 服务解决复杂的 Electron 通信链路的问题

背景 Web 服务对前端同学来说并不陌生&#xff0c;你们开发其他前端界面请求的后端接口就是 Web 服务&#xff0c;你们 npm run dev启动的也是一个本地的 Web 服务&#xff0c;前端的 js&#xff0c;html&#xff0c;css 都有从这个服务上拉取到的资源。 我们在开发 Electron…...

《自然-计算科学》诚邀您投稿计算社会科学研究(computational social science)

李升伟 编译 近年来&#xff0c;运用计算方法和工具来深化对社会科学长期议题理解的"计算社会科学"发展迅猛。这一增长主要得益于社交媒体数据、移动通信数据、数字化图书与历史档案、医疗记录等海量数据的涌现&#xff0c;这些资源不仅为验证现有社会科学理论提供了…...

【SPSS/EXCEl】主成分分析构建__综合评价指数

学习过程中实验操作的记录 1.数据准备和标准化&#xff1a; (1)区分正负相关性:判断每个因子是正向指标还是负向指标,计算每个的最大值和最小值 (2) 标准化: Min-Max标准化 Min-Max标准化&#xff08;最大最小值法&#xff09;&#xff1a; 将数据映射到指定的区间&#xff…...

#node.js后端项目的部署相关了解

熟悉 Spring Boot 的 java -jar 启动方式&#xff0c;那咱们就用类比 实战方式&#xff0c;来彻底搞懂&#xff1a; &#x1f680; Node.js 后端项目的 部署 & 启动方式 ✅ 和 Spring Boot 的 java -jar xxx.jar 一样&#xff0c;Node.js 也可以一句命令启动&#xff0c;而…...

程序化广告行业(69/89):DMP与PCP系统核心功能剖析

程序化广告行业&#xff08;69/89&#xff09;&#xff1a;DMP与PCP系统核心功能剖析 在数字化营销浪潮中&#xff0c;程序化广告已成为企业精准触达目标受众的关键手段。作为行业探索者&#xff0c;我深知其中知识的繁杂与重要性。一直以来&#xff0c;都希望能和大家一同学习…...

基于Python的二手房数据挖掘与可视化深度分析

一、技术框架与数据概况 1.1 技术栈构成 import pandas as pd # 数据操作(v1.3.5) import numpy as np # 数值计算(v1.21.6) from pyecharts.charts import * # 交互式可视化(v1.9.1) from sklearn.preprocessing import StandardScaler # 数据标准化(可选扩展) …...

linux第三次作业

1、将你的虚拟机的网卡模式设置为nat模式&#xff0c;给虚拟机网卡配置三个主机位分别为100、200、168的ip地址 2、测试你的虚拟机是否能够ping通网关和dns&#xff0c;如果不能请修改网关和dns的地址 3、将如下内容写入/etc/hosts文件中&#xff08;如果有多个ip地址则写多行&…...

C#编写HttpClient爬虫程序示例

要写一个使用C#和HttpClient的爬虫程序。首先&#xff0c;我需要了解HttpClient的基本用法。HttpClient是用来发送HTTP请求和接收响应的类&#xff0c;对吧&#xff1f;我记得在C#中使用它的时候需要注意一些事情&#xff0c;比如最好使用单例实例&#xff0c;而不是频繁创建和…...

关于Spring MVC在无注解情况下通过参数名匹配获取请求参数的详细说明,包含代码示例和总结表格

以下是关于Spring MVC在无注解情况下通过参数名匹配获取请求参数的详细说明&#xff0c;包含代码示例和总结表格&#xff1a; 1. 核心机制 Spring MVC通过参数名匹配实现无注解参数绑定&#xff1a; 条件&#xff1a;方法参数名需与请求参数&#xff08;查询参数、表单参数&a…...

数智读书笔记系列027:《医疗健康大数据治理》构建智慧医疗的核心基石

一、图书介绍: 1.1 书籍基本信息 在当今数字化技术飞速发展的背景下,医疗行业正经历着前所未有的变革。信息化、智能化、数据驱动的趋势正在深入到医疗服务的各个环节,推动着医疗健康大数据成为医疗行业发展的核心资产。在这样的时代背景下,《医疗健康大数据治理》这本书应…...

Wayland介绍

Wayland 是一种现代化的显示服务器协议&#xff0c;旨在替代传统的 X Window System&#xff08;X11&#xff09;&#xff0c;为 Linux 和类 Unix 系统提供更高效、安全的图形显示管理。以下是其核心要点&#xff1a; 1. 基本概念 显示服务器协议&#xff1a;Wayland 定义了客户…...