【小黑嵌入式系统第六课】嵌入式系统软件设计基础——C语言简述、程序涉及规范、多任务程序设计、状态机建模(FSM)、模块化设计、事件触发、时间触发

本文主要是介绍【小黑嵌入式系统第六课】嵌入式系统软件设计基础——C语言简述、程序涉及规范、多任务程序设计、状态机建模(FSM)、模块化设计、事件触发、时间触发,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

上一课:
【小黑嵌入式系统第五课】嵌入式系统开发流程——开发工具、交叉开发环境、开发过程(生成&调试&测试)、发展趋势

文章目录

    • 一 单片机的C语言简述
      • 1、为什么要用C语言?
      • 2、单片机的C语言怎么学?
        • 之一:变量定义
        • 之二:特殊寄存器操作
        • 之三:位操作
        • 之四:中断
        • 之五:内部函数(intrinsic Function)
        • 之六:函数的可重入性
        • 讨论与总结:
    • 二 程序设计规范
      • 1、什么要学习程序设计规范?
      • 2、程序规范的基本原则?
        • (一)编程风格
        • (二)可移植性
        • (三)版本管理、可配置
    • 三 前后台多任务程序设计
      • (一)前后台程序的基本概念
      • (二)前后台程序的编写基本原则
        • (1)任何一个任务都不能阻塞CPU。
        • (2)关注函数重入问题
        • (3)临界代码保护(Critical Code Protection)
        • (4)临界代码的保护方法
      • 讨论与总结
    • 四 FSM:状态机建模
      • 1、什么是状态机?
      • 2、为什么要引入状态机?
      • 3、流程图无法描述的软件行为举例
      • 4、引入“状态机” 的优势
      • 5、状态机的表示方法:状态转移图
      • 6、由状态转移图生成代码
      • 7、状态机建模举例
    • 五 模块化程序设计
      • 1、模块化程序的原则
      • 2、键盘模块化程序
      • 3、带长短键识别的键盘模块化程序
      • 4、串口收发模块化程序
      • 5、数码管显示模块化程序
      • 6、时钟和日历程序
    • 六 事件触发多任务程序设计
      • 1、什么是事件触发程序?
      • 2、事件触发程序的程序架构
      • 3、事件触发程序设计范例
    • 七 时间触发系统


一 单片机的C语言简述

1、为什么要用C语言?

理由1:大幅减少编程劳动量

在这里插入图片描述
理由2:代码的通用性

在这里插入图片描述

  • C语言可以为世界上任何一款处理器编程 (包括所有单片机)
  • 在任何一款单片机上开发的程序,都可以移植到别的处理器上。
  • 代码的模块化、可复用性 => 减少重复劳动、加快开发速度。

2、单片机的C语言怎么学?

在这里插入图片描述
PSoC Creator集成开发环境所配备的PSoC 5LP编译器为GCC-ARM(GNU Compiler Collection for ARM Embedded Processors),是一款免费的C/C++编译器。其文档位于图中gcc目录内。
C预处理器、链接器、汇编器、调试器、函数库等相关软件工具的文档位于图中的pdf目录及其子目录内。

之一:变量定义

在这里插入图片描述

处理器、编译器类型的不同,在变量定义上与VC略有不同。

几个特殊关键词的含义:
 
const:定义常量。const关键字定义的常量被放在ROM中,常用于定义如系数表、显示段码表等。
static :相当于本地全局变量,在函数内使用,可以避免全局变量使用混乱。
volatile :定义“挥发性”变量。编译器将认为该变量的值会随时改变,对该变量的任何操作都不会被优化掉。

之二:特殊寄存器操作

在这里插入图片描述
结论:

(1)特殊寄存器经过定义之后,可以像变量一样操作。

(2)包含单片机头文件,就已经完成了变量定义工作。

之三:位操作

在这里插入图片描述
结论:若处理器不支持单个位的操作,则要用左边的方式实现。

之四:中断

在这里插入图片描述
结论:(1)C语言将中断作为特殊函数 (2)该函数由中断机制调用

之五:内部函数(intrinsic Function)

在这里插入图片描述
结论:
(1)内部函数是将该款单片机的一些特殊指令做成函数形式
(2)在使用前,要包含内部函数头文件。

之六:函数的可重入性

在这里插入图片描述
结论:
(1)低端单片机因资源少,函数用静态传递,不可重入。
(2)中高端单片机编译器,函数用栈传递,允许重入。

讨论与总结:

1、即使是初学者,也完全可以在不深入了解汇编指令系统的情况下直接开始C语言开发

2、任何一款处理器的C语言,都是在标准C语言 (ANSI-C) 上增加对相应处理器的特殊操作而构成。

3、C编译器的表现通常非常优秀。如果没有几年的手工汇编经验3很难写出比C编译器更高效的代码。
4、如果在编程过程中将硬件差异集中到某个很小的局部,整个程序通过很简单的修改就能编译成另一CPU的机器码。这就是所谓的“代码移植”,是嵌入式软件设计最重要的思想之一。
5、在一开始就树立可移植性、模块化的概念,养成好的编程习惯,这正是下一部分对减少重复劳动、加快开发速度有很大帮助的主要目的。

二 程序设计规范

1、什么要学习程序设计规范?

1、程序不仅要被计算机执行,还要给程序员阅读,以及被今后重复使用。
2、一个风格清爽而严谨、规范化的程序更容易被读懂,更容易被修改、排错和移植。
3、规范化编程、高度一致的风格和正确的习惯还有助于保持思维清晰,写出正确无误的代码。特别是一个开发团队共同工作时,规范一致化的编程尤其重要
4、每个初学者在项目初期都会因为不良编程习惯浪费大量时间,因此若能在开始写程序时就重视规范化问题,对顺利渡过提高阶段有很大帮助。

2、程序规范的基本原则?

原则:

(1)一致的代码风格,统一的变量名、函数名命名规则

(2)符合英语语法、可阅读的代码

(3)关键代码100%注释

(4)硬件有关、硬件无关代码分离,可移植性强

(5)每个对象都具有完善的封装,接口形式简洁、易用

(6)对所有资源严格要求硬件隔离层,软件中不允许直接访问硬件,不允许跨层调用。

(一)编程风格

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(二)可移植性

1)消除CPU差异

若希望自己写的程序在不同处理器上运行,首先需要了解这些处理器的不同之处。其中包括硬件的不同以及特殊语法的差异。例如MSP430单片机没有位操作指令,8051单片机有,若两者之间程序需相互移植,首先需要消灭这个差异。
在这里插入图片描述
2)消除硬件差异

在这里插入图片描述
在这里插入图片描述

更改数码管硬件布线,无需重写段码表

3)封装

封装是指将软/硬件对象的属性与行为绑定在一起,并放置在一个模块单元内。该单元负责将所描述的属性隐藏起来,外界对其内部属性的所有访问只能通过提供的应用程序接口实现。

在这里插入图片描述

初学者常见问题:

在这里插入图片描述
4)应用程序接口(API)

接口是对软/硬件对象的抽象,对外提供的服务和访问功能,

即:对象封装后对外呈现成什么样?

原则:(1)使用方便(2)功能丰富(3)但不要过多过滥

【例】为液晶显示模块规划应用程序接口:

在这里插入图片描述
5)软件层次

例:菜单程序
在这里插入图片描述
 
(1)杜绝跨层调用
(2)功能模块可以任意拼接、组合
(3)要有硬件隔离层(HAL)
(4)更换任意层代码,上下层建筑不变

(三)版本管理、可配置

在这里插入图片描述
 
(1)尽可能减少软件副本
(2)类似的产品/设计尽可能公用同一代码
(3)利用宏定义配置功能
(4)永远在最新的代码上开发,保留最新版

三 前后台多任务程序设计

(一)前后台程序的基本概念

在这里插入图片描述
任务(Task) :指完成某一单一功能的程序
后台程序:对时间要求不严格的任务,通常在主循环内执行
前台程序:要求快速响应或者时间严格的任务,通常中断内
队列/缓冲:用于暂存后台来不及处理的前台事件

(二)前后台程序的编写基本原则

(1)任何一个任务都不能阻塞CPU。

每个任务都应主动结束,让出CPU。不能有等待、死循环、长延时等环节(对初学者来说是难点!

在这里插入图片描述

(2)关注函数重入问题

可重入(Reentrancy):函数在自己调用自己的时候,不必担心数据被破坏。

从软件工程角度对函数可重入的作用可以解释为:具有可重入性的函数能够被多个任务同时调用。在后台程序中,任务都是顺序执行的,不存在多个任务同时调用一个函数的情况。但可能出现前台中断服务程序与后台任务同时调用某个函数。

因此对于前后台公用函数,必须是可重入的

【例】:

在这里插入图片描述

(3)临界代码保护(Critical Code Protection)

临界代码:运行时不可分割的代码,这部分代码不允许被中断打断

1) 依靠软件产生时间严格时序的程序段。

/***************************************************
*名称:          Pulse 10us()
*功能:         产生10us脉冲
*入门参数:     无
**************************************************/
void Pulse_10us()
{_DINT();            // -------以下是临界代码区,不允许被中断IO=1;               // 置高_delay_cycles(8); 	// 高电平持续10us (O赋值身耗2us)IO=0;               //置低_EINTO0;            // -------以上是临界代码区-----------
}

2)共享资源互斥性造成的临界代码

程序中任何可被占用的实体都称为“资源”。资源可以是硬件设备,如定时器、串口、打印机、键盘、LCD显示器等,也可以是变量、数组、队列、等数据。

被一个以上任务所占用的资源叫做“共享资源”。共享资源若不能同时被多任务占用,则具有“互斥性”(Mutual Exclusive)。

【例】:前后台同时调用液晶显示函数造成花屏

在这里插入图片描述

(4)临界代码的保护方法
  • 关中断、开中断
    隐患: 如果在A函数的临界代码区调用了另一个函数B,B函数内也有临界代码区,从B函数返回时,中断被打开了,这将造成A函数后续代码失去临界保护。所以,使用该方法时,不能在临界代码区调用任何具其他有临界代码的函数!
  • 利用硬件栈保存中断使能状态
    优点:不影响函数调用
    缺点:很多单片机的C语言不支持操作硬件栈
  • 利用变量保存中断使能状态
    缺点:每一段临界代码要消耗2-4字节内存
  • 利用模拟栈保存中断使能状态
    缺点:速度慢

典型错误1:在临界代码区调用其他临界代码

A()
{	int_Disable();	B();	// 这期间中断是开的,所执行的代码不被临界保护int_Enable();
}B()
{int_Disable();	// ...int_Enable();
}

典型错误2:在主函数和中断中都调用LCD操作函数

  • LCD操作耗时长,不应放在中断中。
  • LCD操作是临界代码,LCD是互斥性共享资源,LCD操作函数都是不可重入的,如果主函数里没有做临界代码保护,结果就是没多久屏幕就花了或呈死机效果。

讨论与总结

  1. 后台中任务顺序执行。每个后台任务中的内存(局部变量)在任务结束后可以全部释放,让给下一个任务使用。即使在RAM很少的处理器上也能同时执行众多任务。
  2. 后台中任务顺序执行。天然避免了后台任务资源互斥问题,但仍需考虑前后台之间的资源互斥问题。
  3. 前后台程序的结构灵活,实现形式与实现手段多样,是使用最广的程序结构,但缺乏架构标准,维护、升级、排错都很困难。
  4. 必须要程序员自己来判断和处理临界代码的隐患。
  5. 程序多任务的执行依靠每个任务的非阻塞性来保证,是编程最大的难点,下一节将介绍的FSM将是解决这一问题的利器!

四 FSM:状态机建模

在这里插入图片描述

1、什么是状态机?

有限状态自动机(Finite-State Machine, FSM),简称状态机,是表示有限个状态以及在这些状态之间的转移动作等行为的数学模型。

2、为什么要引入状态机?

流程图的缺陷:

1、不能用于描述“任何时候”发生的事件
2、无法描述“由外部事件决定流程”的程序
3、不适合描述带有阻塞的并发过程
4、难以描述大量的独立事件。

需要:能够描述并发结构的软件,能从行为的角度来描述软件,且能够根据模型生成代码,也能够对软件进行完整测试的新手段—状态机模型。

3、流程图无法描述的软件行为举例

(1)不能用于描述“任何时候”发生的事件
在这里插入图片描述
(2)不能用于描述由外部事件决定流程的事件

【例】:电子表有两个按键,但按键顺序完全由外部决定
在这里插入图片描述
(3)不适合描述带有阻塞的并发过程

【例】:一个单片机同时控制2台电动机完成运转时序

在这里插入图片描述
(4)不适合描述大量的独立事件

【例】:投币式自动咖啡机程序

流程图:投币->选咖啡->出咖啡->结束
然 而…

  • 如果没有放咖啡杯就选择咖啡,会发生什么情况?

  • 如果咖啡杯未满之前,用户取走了咖啡杯,会发生什么情况?

  • 如果咖啡灌了一半时,用户取走咖啡杯,再放回,能否把剩下一半继续加满?

  • 如果咖啡灌了一半时,用户取走咖啡杯,不再放回,剩下一半是否会加到下一用户杯中?

  • 如果咖啡杯未满之前,用户取走了咖啡杯,然后按退币扭,该如何处理?

  • 如果还没有完成一次点单之前,用户再次投币,会发生什么情况?

  • 如果一杯咖啡尚未加满时,用户又点了另一种咖啡,会发生什么情况?

  • 如果用户一次投入两杯咖啡的钱,该怎样处理?

  • 如果咖啡存储容器已空,用户点单时能否正确提示?

  • 如果咖啡杯未满之前,咖啡机空了,能否给用户退款?

4、引入“状态机” 的优势

上面这些例子中,软件下一步要执行的功能不仅与外界入信息有关,还与系统的“当前状态”有关。状态机就是一种基于“状态”与“事件”的软件描述手段!其优势在于:

(1) 能够处理并发。由于系统在每一时刻只能有唯一的状态,在每一个状态下,可能发生的事件也是有限的。因此系统中即使存在有大量的独立事件,软件描述也会简单得多。

(2) 能够消除阻寒。真正需要CPU处理的只有系统状态发生改变的那一刻,在系统等待事件到来的期间,是不需要CPU处理的。如果能够用状态与事件的形式来描述软件,能够将CPU从等待事件发生的过程中解放出来,从而生成无阻塞的代码。

(3) 能够降低系统的复杂度,提高可测性

5、状态机的表示方法:状态转移图

在这里插入图片描述

圆圈:状态 (有限个)
有向箭头:状态转移
Event事件:事件发生时将触发状态转移
Action动作:状态转移的同时执行动作

6、由状态转移图生成代码

方法1、在状态中判断事件(事件查询)

在这里插入图片描述

switch(State)		//根据当前状态决定程序分支
{case S0:			//在s0状态if(Event0){			//如果查询到Event0事件Action0();}else if(Event1){			//如果查询到Event1事件Action1();State=S1;}else if(Event2){			//如果查询到Event2事件Action3();State=S2;}break;case S1:			//在s1状态if(Event2){			//如果查询到Event2事件Action2();State=S2;}break;
......

方法2、在事件中判断状态(事件触发)

在这里插入图片描述

7、状态机建模举例

例1 电子表程序

在这里插入图片描述

====A键中断====
switch(Status)		/*根据当前状态处理A键所引发的状态跳跳转*/
{case DISP_TIMME: Status = DISP_DATE;break://时间显示时按A键,显示日期case DISP_DATE: Status = DISP_SEC; break;case DISP_SEC: Status= DISP_TIME; break;case SET_HOUR: if(++Hour>23) Hour=0; break; //小时设置时按A键调整小时case SET_MINUTE: if(++Min>59) Min=0; break;case SET_MONTH: if(++Month>12) Month=1; break;case SET_DATE: if(++Date>31) Date=0; break;
}====B键中断=====
switch (Status)			/*/根据当前状态处理B键所引发的状态跳转/*/
{
case DISP_TIME;		Status= SET_HOUR; break;	//时间显示时按B键,设置小时
case DISP_DATH;		Status= SET_HOUR: break;	//日期显示时按B键,设置小时
case DISP_SEC;		Second 0; break;			//秒钟显示时按B键,秒归零
case SET_HOUR;		Status= SET_MINUTE; break;	//小时设置时按B键,分钟设置
case SET_MINUTE;	Status= SET_MONTH; break;	//分钟设置时按B键月设置
case SET_MONTH;		Status= SET_DATE; break;	//月设置时按B键,日设置
case SET_DATE;		Status= DISP_TIME; break;	//日设置时按B键,显示时间
}

例2 长短按键识别

在这里插入图片描述
例3 事件序列匹配

在这里插入图片描述

五 模块化程序设计

1、模块化程序的原则

  1. 非阻寒性 不能长时间占用CPU,更不死等待某个事件的发生,尽快地让出CPU,供后续任务执行。
  2. 硬件隔离 屏蔽硬件特征,起到硬件隔离层的作用。上层软件将不涉及直接硬件操作。
  3. 模块独立性 各个程序库之间没有代码关联性(没有互相调用和隶属关系),在使用时,各个模块文件可以任意拼接、组合、拆分。
  4. 时间独立性 使用缓冲区、事件队列等手段,对时间关联性强的事件进行斩存和缓冲,使之可以被异步处理。
  5. 可移植性 代码都按照标准C的规范,很容易的移植到其他处理器上,或者其它硬件平台上。
  6. 100%注释 注释关键代码的功能或设计意图,以及每个函数的功能.入口出口参数、说明及注意事项,使用范例等。
  7. 开放性 方便日后修改、添加新的功能函数。

2、键盘模块化程序

在这里插入图片描述

3、带长短键识别的键盘模块化程序

在这里插入图片描述

4、串口收发模块化程序

在这里插入图片描述

5、数码管显示模块化程序

在这里插入图片描述

6、时钟和日历程序

在这里插入图片描述

六 事件触发多任务程序设计

1、什么是事件触发程序?

在这里插入图片描述
任务全部在中断内完成,主程序休眠。
可以看做前后台程序中,只有前台任务。

特点:1)实时性较好,事件响应较快;2)低功耗

2、事件触发程序的程序架构

在这里插入图片描述

中断:获取原始的事件信息。
事件引擎:判断何种事件发生,并调用相应处理程序。
(一个中断有多个中断源时)
事件处理程序:只负责某个事件的处理,要求非阻塞。

3、事件触发程序设计范例

有3个按键 (S1、S2、S3),按下为低电平。外部输入电压从ADC输入。设计一款超低功耗的电压表,要求用事件触发结构实现下列功能:

  1. 实现电压测量功能,每秒刷新显示2次电压测量值。
    每次测量值由ADC连续采样4次求平均得到。
  2. 按下S1键时,斩停采样与显示刷新(保持功能)
  3. 按下S2键时,恢复采样与刷新。
  4. 按下S3键时,将采样数据从串口发出。

在这里插入图片描述
在这里插入图片描述
第3步:编写5个事件处理程序,此时并不关心事件如何发生如何被检测到,以及按什么顺序发生

第4步:测试。按照预先设定的顺序,依次调用5个事件处理程序(并不需要硬件上真的发生事件),模拟事件发生,即可进行代码测试。

第5步:编写事件引擎,在中断内检测和判判断事件,并分别调用相应的事件处理程序。

七 时间触发系统

时间触发系统可以理解为一种特殊的事件触发系统,但它另有自己的特点。

例子:一个医生,必须在一些护理人员的帮助下,通宵照顾十个危重病人,方案可以是

● 安排护理人员在某个病人出现严重问题时唤醒他
——事件触发
● 每小时闹铃,闹铃响时起床去探访每个病人
——时间触发

以每小时的间隔探访病人,医生能在严重并发症出现之前探访每个病人并安排合理的治疗。另外,工作量在整个晚上平摊。于是,所有病人都能平安地度过这个夜晚。

而前一种方式可能会出现护理人员在唤醒医生时,有多个病人都出现了严重并发症,需要依次做手术,后面的病人有可能来不及得到手术治疗。

这个医院的例子在事件驱动的系统中,即可能同时发生几个事件。需要处理同时发生的多个事件不但增加了系统复杂性,而且降低了对事件触发系统在所有情况下的行为做出预计的能力。

相比而言,在时间触发的嵌入式系统中,设计人员能够通过仔细安排可控的顺序,保证一次只处理一个事件。

许多嵌入式系统并不需要睡眠,采用时间触发方法有很多好处,有助于改善可靠性和安全性(如广泛应用于航空航天工业和汽车工业),主要原因在于系统的行为可以预计。

时间触发方法还能降低CPU的负荷,并减少存储器的使用量。

嵌入式系统需要执行的任务分为两种:

  ● **周期性任务**,比如每100ms执行一次● **单次任务**,如在50ms的延迟后执行一次

考虑方案1:

void main(void)
{Init_System();while(1){X();                     // 执行任务(耗时10ms)Delay_90ms();   // 延迟90ms}
}

需要知道任务X的精确运行时间

这个运行时间永不变化—— 不可行

考虑方案2:

基于定时器中断,在一定的时刻调用函数

如果要支持多个任务(这些任务一般具有不同的运行时间并以不同的时间间隔运行),可以每个任务都使用一个定时器。

但:浪费硬件资源(或者不够用)、硬件的维护增加、会同时产生多个定时器中断。——不合理

解决方案:使用调度器

● 调度器可以看作是一个简单的操作系统,允许以周期性或单次方式来调用任务。

● 从底层的角度来看,调度器可以看作是一个由许多不同任务共享的定时器中断服务程序。

用调度器来调度三个任务的执行:

void main(void)
{SCH_Init();     // 设置调度器一次/*---- 增加各任务至任务队列(时间分辨率为1ms)----*/// Function_A将每隔2ms运行一次SCH_Add_Task(Function_A, 0, 2);// Function_B将每隔10ms运行一次SCH_Add_Task(Function_B, 1, 10); // Function_C将每隔15ms运行一次SCH_Add_Task(Function_C, 3, 15); SCH_Start();   // 启动调度while(1){// 按调度算法执行任务队列中各任务SCH_Dispatch_Tasks();   }
}

在这里插入图片描述
调度器的分类

  ● 合作式调度器● 抢占式调度器

合作式调度器:
● 任务在特定的时刻被调度运行(以周期性或单次方式)

● 当任务需要运行时,被添加到等待队列

● 当CPU空闲时,运行等待任务中的下一个(如果有的话)

● 前一任务运行直到完成,才轮到下一个等待任务

● 简单,用少量代码即可实现

● 一次只为一个任务分配存储器

● 通常完全由高级语言如C实现

● 小心设计可以实现快速响应外部事件

● 简单、可预测、可靠并且安全

抢占式调度器:

● 任务在特定的时刻被调度运行(以周期性或单次方式)

● 当任务需要运行时,被添加到等待队列

● 等待的任务运行一段固定的时间,如果没有完成,将被暂停并放回到等待队列。然后下一个等待任务(如果有的话)将运行一段固定的时间。

● 高优先级的任务可以抢占低优先级任务优先运行

● 复杂,“并行处理的”任务试图访问公用资源时需避免冲突等

● 必须为被抢占任务的所有中间状态分配存储器

● 通常(至少是部分)由汇编语言编写

● 对外部事件响应快

● 与合作式调度比,通常认为其更不可预测、并且可靠性较低

混合式调度器:

● 支持多个合作式调度的任务

● 支持一个抢占式任务(可以“中断”合作式任务)

这篇关于【小黑嵌入式系统第六课】嵌入式系统软件设计基础——C语言简述、程序涉及规范、多任务程序设计、状态机建模(FSM)、模块化设计、事件触发、时间触发的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/316605

相关文章

什么是cron? Linux系统下Cron定时任务使用指南

《什么是cron?Linux系统下Cron定时任务使用指南》在日常的Linux系统管理和维护中,定时执行任务是非常常见的需求,你可能需要每天执行备份任务、清理系统日志或运行特定的脚本,而不想每天... 在管理 linux 服务器的过程中,总有一些任务需要我们定期或重复执行。就比如备份任务,通常会选在服务器资

C语言线程池的常见实现方式详解

《C语言线程池的常见实现方式详解》本文介绍了如何使用C语言实现一个基本的线程池,线程池的实现包括工作线程、任务队列、任务调度、线程池的初始化、任务添加、销毁等步骤,感兴趣的朋友跟随小编一起看看吧... 目录1. 线程池的基本结构2. 线程池的实现步骤3. 线程池的核心数据结构4. 线程池的详细实现4.1 初

TP-LINK/水星和hasivo交换机怎么选? 三款网管交换机系统功能对比

《TP-LINK/水星和hasivo交换机怎么选?三款网管交换机系统功能对比》今天选了三款都是”8+1″的2.5G网管交换机,分别是TP-LINK水星和hasivo交换机,该怎么选呢?这些交换机功... TP-LINK、水星和hasivo这三台交换机都是”8+1″的2.5G网管交换机,我手里的China编程has

基于Qt实现系统主题感知功能

《基于Qt实现系统主题感知功能》在现代桌面应用程序开发中,系统主题感知是一项重要的功能,它使得应用程序能够根据用户的系统主题设置(如深色模式或浅色模式)自动调整其外观,Qt作为一个跨平台的C++图形用... 目录【正文开始】一、使用效果二、系统主题感知助手类(SystemThemeHelper)三、实现细节

Python中的异步:async 和 await以及操作中的事件循环、回调和异常

《Python中的异步:async和await以及操作中的事件循环、回调和异常》在现代编程中,异步操作在处理I/O密集型任务时,可以显著提高程序的性能和响应速度,Python提供了asyn... 目录引言什么是异步操作?python 中的异步编程基础async 和 await 关键字asyncio 模块理论

CentOS系统使用yum命令报错问题及解决

《CentOS系统使用yum命令报错问题及解决》文章主要讲述了在CentOS系统中使用yum命令时遇到的错误,并提供了个人解决方法,希望对大家有所帮助,并鼓励大家支持脚本之家... 目录Centos系统使用yum命令报错找到文件替换源文件为总结CentOS系统使用yum命令报错http://www.cppc

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

基于人工智能的图像分类系统

目录 引言项目背景环境准备 硬件要求软件安装与配置系统设计 系统架构关键技术代码示例 数据预处理模型训练模型预测应用场景结论 1. 引言 图像分类是计算机视觉中的一个重要任务,目标是自动识别图像中的对象类别。通过卷积神经网络(CNN)等深度学习技术,我们可以构建高效的图像分类系统,广泛应用于自动驾驶、医疗影像诊断、监控分析等领域。本文将介绍如何构建一个基于人工智能的图像分类系统,包括环境

水位雨量在线监测系统概述及应用介绍

在当今社会,随着科技的飞速发展,各种智能监测系统已成为保障公共安全、促进资源管理和环境保护的重要工具。其中,水位雨量在线监测系统作为自然灾害预警、水资源管理及水利工程运行的关键技术,其重要性不言而喻。 一、水位雨量在线监测系统的基本原理 水位雨量在线监测系统主要由数据采集单元、数据传输网络、数据处理中心及用户终端四大部分构成,形成了一个完整的闭环系统。 数据采集单元:这是系统的“眼睛”,

禁止平板,iPad长按弹出默认菜单事件

通过监控按下抬起时间差来禁止弹出事件,把以下代码写在要禁止的页面的页面加载事件里面即可     var date;document.addEventListener('touchstart', event => {date = new Date().getTime();});document.addEventListener('touchend', event => {if (new