【图解UDS】UDS汽车诊断标准协议(ISO 14229)带你入门到精通_uds诊断协议-程序员宅基地

技术标签: can  c语言  UDS/OBD诊断/刷写  # UDS诊断(ISO 14229)  

                                  【图解UDS】UDS汽车诊断标准协议(ISO 14229)带你入门到精通

目录

为了便于学习ISO 14229 UDS诊断协议,提供三个资源链接:

0 前言

1 诊断的基本概念

2 UDS诊断诊断协议

2.1 诊断服务的概念

2.2 诊断会话控制0x10服务

2.3 会话访问0x27服务

2.4 用于读/写的DID的0x22/0x2E服务

2.5 故障存储相关的0x19和0x14服务

3 结尾


总目录链接:

《UDS/OBD诊断&诊断描述文件CDD》总目录icon-default.png?t=L892https://blog.csdn.net/qfmzhu/article/details/120425660

为了便于学习ISO 14229 UDS诊断协议,提供三个资源链接:

a)【图解UDS】UDS汽车诊断开发流程及Vector解决方案工具链介绍

b)ISO 14229 -Part1,2,3,4,5,6,7 UDS最新标准文件获取路径

c)ISO 14229 Road vehicles — Unified diagnostic services (UDS)标准各Part部分修订和发布状态汇总

0 前言

诊断的概念来源于医学,医生通过询问、观察病人,或者通过仪器检测,利用数据对病症做出判断。

而车辆诊断的目的也有类似的地方,为了能够快速准确的判断车辆或者某个控制器的故障以及故障原因,从而为维修提供可靠的依据。

内容大致分为三个部分,首先介绍诊断的基本概念,再为大家讲解UDS诊断协议,以及协议中常用到的诊断服务,最后对今天的内容做一个小结。

1 诊断的基本概念

车辆的诊断需要有Tester端和ECU端,Tester端和ECU端通过一问一答的形式进行通信,因而Tester端和ECU端都需要遵循同样的诊断通信协议,常用的诊断协议有ISO 14230,ISO 15031,ISO 15765,还有我们熟悉的ISO 14229就是UDS协议,在协议里面定义了诊断的请求,诊断响应的报文格式,以及ECU怎样处理诊断请求报文,以及诊断服务的应用。

UDS是Unified Diagnostic Services的缩写,在国际标准ISO 14229-1中定义,UDS标准中除了定义服务的用法,以及服务的格式以外,还定义了一些标准化的数据,而到OEM要使用UDS协议时,除了要使用标准定义的服务以及标准数据以外,还要依据自身的情况,定义属于OEM的特定数据,比如说,定义所要遵循的服务,需要支持的DID,需要支持的DTC等这些内容,这样形成的符合某OEM的诊断规范才能用于ECU诊断功能的开发以及验证。

随着车辆ECU的增多,车辆网络拓扑结构也越来越负责,比如说一辆车需要有多种总线(CAN总线,LIN,以太网,FlexRay),

所以在2013年释放的UDS协议中,除了对通用诊断服务的定义以外,还增加了关于UDS在各个总线中应用的定义

这张图就描述了UDS在OSI七层模型中的应用,OSI七层模型,第一层第二层分别定义了物理层和数据链路层,第三层第四层定义了网络层和传输层,第七层是应用层。

比如说我们熟悉CAN总线,物理层和数据链路层遵循的是ISO 11898,而它的传输层遵循的是ISO 15765-2,在ISO 14229-3中定义了UDS基于CAN总线的应用,而现在比较火的以太网,它的物理层和数据链路层遵循的是ISO 13400-3,它的传输层也就是DoIP遵循的是ISO 13400-2, 它的UDS基于以太网的应用是ISO 14229-5

下面我们来看下,关于诊断服务的一些知识,

2 UDS诊断诊断协议

2.1 诊断服务的概念

首先来看服务请求和响应格式,“请求”由Tester端发送给ECU,请求报文里带有SID,根据具体的服务内容后面加具体的数据。肯定响应格式由“SID+40+具体的数据”。否定响应格式是一个固定的格式“7F+请求报文里的SID+一个字节的NRC”

看两个名词,一个叫做Subfunction,一个叫做ID,UDS服务支持Subfunction的请求和响应格式,“请求”为“SID+一个字节Subfunction+具体的数据”,肯定响应为“SID+40+Subfunction+具体的数据”,而有的UDS服务里面是不支持Subfunction,是支持DID的,DID是“数据ID”的意思,那么它的请求格式为“SID+具体的DID+数据内容”,肯定响应“SID+40+DID+具体的数据”,这里举出两个例子,一个是 “31例程控制服务”,还有一个是“2F IO控制服务”,31就是它的请求报文里面,带一个字节的Subfunction和两个字节的Routine ID,后面的这个数据是跟具体的数据内容,也可以没有具体的数据。2F是它的SID+两个字节的DID+一个字节的输入输出控制参数(这里注意这一个字节的数据类似于Subfunction,但是他不是Subfunction)+后面加具体的数据内容。

下面为大家介绍一个概念,为肯定响应抑制位。肯定响应抑制位是在Subfunction里的这个字节的最高位,我们把它叫做肯定响应抑制位。只有这个服务支持Subfunction的时候,才有可能支持肯定响应抑制位,当肯定响应抑制位置1的时候,要求所有的肯定响应的抑制将不再发送。当肯定响应抑制位为0的时候,肯定响应是不被抑制的。这里要注意的是它只是抑制肯定响应,而否定响应是不被抑制的。

Tester发送的请求报文格式错误,或者请求发送的条件处于错误,ECU将发送否定响应,否定响应的格式是“7F+SID+NRC”,常用到的NRC在这里罗列了。

11表示服务不支持;

12 subfunction不支持;

13 请求的长度不正确,或者格式不正确

31 是请求超出范围;

7E 是在当前会话下subfunction不支持

7F 是在当前会话下服务不支持

来看两个时间参数,一个是叫做P2Sever,一个是叫做P2Sever*。当Tester给ECU发送请求过后,ECU需要在P2Sever时间内给出相应的响应,如果ECU当前正在处理别的任务,处理别的事情,而不能在P2Sever的时间内给出相应的响应,那么它先在P2Sever时间内给出一个NRC为78的Pending报文,告诉Tester“ECU正在忙”,之后会在P2Sever*的时间内给出其它的响应报文,如果P2Sever*的时间内还是不能给出相应的肯定响应和否定响应,将继续给出Pending报文,直到能够正确处理请求报文之后,会给出正确的响应报文。

今天会着重介绍26个UDS服务里的6个,分别是10诊断会话控制,14清除诊断信息,19读取诊断信息,22由DID读取数据,27安全解锁服务,2E由DID写入数据。

下面我们来看诊断会话控制就是10服务

2.2 诊断会话控制0x10服务

ECU会有不同的会话控制,所以ECU在不同的阶段,比如说开发,生产,售后阶段也会用到不同的会话模式,因为每个服务功能的不同,也会在诊断规范里定义这些服务所支持的诊断会话模式

这张表是14229里面,对各个诊断服务,对会话控制的支持情况,比如说通信控制28服务,要求在默认会话下不支持;27安全解锁服务,在默认会话模式下不支持;和刷写相关的34,36,37服务,在默认会话下也是不支持的。

我们来看更会话控制有关的3个NRC,首先来看NRC 7F:NRC 7F是指在当前会话下服务不支持。28通信控制服务,要求在默认会话下是不支持的,在扩展会话下能支持。而当ECU处于默认会话的时候,我们上位机发送了28这个服务,ECU收到之后,会回复7F NRC的否定响应。

NRC 7E和NRC 7F 不同的是:NRC 7E是在当前会话下Subfunction不支持。一个用的比较多的用法是,编程会话是不能够由默认会话跳转到编程会话的,只能由扩展会话跳转到编程会话。但ECU处于默认会话的时候,执行了10 02 编程会话的请求,ECU会回复7E NRC的否定响应。

再来看NRC 31,NRC 31常用的用法是请求超出范围,比如说22服务,发送的DID,是ECU不支持的,比如说发送的请求22 01 01 ,因为ECU不支持01 01这个DID,会发送NRC 31的否定响应,还有一个用法是:22在3个会话(默认,编程,扩展下都是支持的),22后面所跟的DID来读取数据的DID对各个会话等级是有要求的,比如说读取硬件版本号在编程会话模式下是支持的,读取车速在编程会话下是不支持的,当ECU处于编程会话的时候,来通过 C0 01来读取车速,那么ECU会回复NRC 31的否定响应。

这个是会话状态的一个状态机,状态机之间可以互相跳转,状态机自身也能跳转,我们把除了默认会话之外的会话状态,都叫做非默认会话状态。当ECU一上电的时候是处于默认会话的,我们通过10,比如说10 03,10 02来将会话状态由默认会话跳转到非默认会话。由非默认会话执行10 01跳转至默认会话。当ECU处于非默认会话的时候,S3 time这个时间超时,ECU也会从非默认会话跳转到默认会话。为了防止ECU从非默认会话跳转至默认会话,我们要求Tester端周期发送3E服务Tester present,让ECU一直维持在非默认会话。那么S3 time这个时间怎么用呢?我们来看下面这张图

Tester端会利用S3Client周期发送Tester present给ECU,ECU收到Tester present比如说3E 00,3E 80的服务请求,会让ECU维持在非默认会话,如果Tester端S3server这个时间内,比如说5000毫秒时间内,都没有给ECU发送任何诊断请求报文,那么ECU就会从非默认会话跳转到默认会话;如果ECU处于解锁状态,也会从解锁状态跳转到锁定状态。通常S3cleint时间小于S3server的时间,比如说网关延时的一些情况。

这个是10服务的请求和响应格式。SID+一个字节的Subfunction(常用的有01默认会话,02编程会话,03扩展会话),它的肯定响应格式是50(就是10+40)+一个字节的Subfunction(就是诊断会话类型)+4个字节的会话参数。

支持的NRC有3个,12 subfunction不支持;13请求格式或者长度错误;22条件不支持。

下面我们来看下,安全解锁27服务。

2.3 会话访问0x27服务

常用到的服务:2E服务通过DID来写入数据;2F通过DID来控制输入输出端口的数值;还有ECU刷写有关的编程服务。这些服务都会改变和影响一些内存里的数据,或者输入输出端口的一些值,所以这些服务是一个被保护的服务。这些服务只有ECU处于解锁状态下才能够执行,而ECU一上电处于锁定状态,那么ECU如何从锁定状态跳转到解锁状态呢?

是要求Tester端和ECU端进行27解锁服务之后,ECU才能够处于解锁状态,那么这个解锁的过程是一个固定的:首先由Tester端给ECU发送请求报文来请求种子,ECU收到这个报文后,回复肯定响应,肯定响应里带有种子数;Tester端收到这个种子数,根据自己安全算法算出来一个K1发送给ECU,ECU也有自己对应的安全算法,他由这个Seed算出来一个密钥K2,当ECU收到这个K1后和自身计算的K2进行比较,如果两者是一致的,那么ECU发送肯定响应给Tester端,告诉Tester端ECU已经解锁。

我们刚才也提到了ECU一上电处于锁定状态,只有执行了安全解锁的流程后才能跳转到解锁状态,一个ECU可以同时拥有多个安全等级,多个安全等级之间可以是相互独立的,也可以是有依赖关系的,比如说要求先解锁安全等级1才能解锁安全等级2,那么当ECU处于解锁状态的时候,会有几种情况会使ECU由解锁状态跳转至锁定状态,比如说执行了11复位服务,比如说有了重新上下电,还比如说有了执行10会话切换,也会让ECU由解锁状态跳转到锁定状态。

当ECU处于解锁状态的时候Tester端再去请求种子的时候,回复的种子全为0。

这个是请求种子的请求报文和肯定响应报文。请求报文为“27+01”;肯定响应“67+01+四个字节的种子”。

当Tester端计算得到了一个密钥,它会发送“27+02+4个字节的密钥”给ECU。当ECU将两者密钥比较后,它认为比较的结果是一致的,ECU会给Tester端发送“67+02”,认为ECU已经处于解锁状态。

那么当ECU已经处于解锁状态的时候,Tester端又一次请求了种子,发送了请求种子的请求报文给ECU,那么ECU就会回复“种子数全为0的肯定响应”报文给Tester端。表明ECU现在处于解锁状态。

这个是27服务支持的所有NRC是在14229-1里定义,比如说我们常用的12;13;这里注意24是一个请求顺序错误,比如说我们要求的安全解锁状态过程必须是先请求Seed再发送key,如果你没有执行请求seed的请求报文,直接发送了key,就会回复24 NRC;比如说35是非法Key,如果Tester发送了非法的密钥给ECU,ECU就会回复35 NRC;36是尝试次数超限,比如说这是要看具体的诊断规范定义,有的定义请求尝试次数不能超过3次,那么Tester端发送给ECU的Key连续3次错误的时候,ECU就会回复36 NRC;37指延时还没有到,因为在有的诊断规范里定义请求的尝试次数达到最大值的时候,ECU会锁定一段的时间,在这个时间之内,你的Tester端是不能够再次请求种子的,所以在这个时间之内,比如说有的整车厂用到10秒延时,Tester端再一次发送了请求种子的请求报文给ECU,那么ECU就会回复37 NRC的否定响应报文。

下面我们来看通过DID来读取和写入数据,就是22和2E服务

2.4 用于读/写的DID的0x22/0x2E服务

首先来看22服务的请求和响应格式,请求格式“22+两个字节的DID”;它的肯定响应“62+DID+所读取的数据”。这里举出了一个例子,比如说现在的DID是F1 86来读取当前的诊断会话状态,它的肯定响应格式“62+ F1 86+02”读取当前处于编程会话状态。

在14229-1 2013版附录C里面列出一些推荐使用的DID和这些DID的功能,大家也可以去看一下这个附录C

22服务支持的NRC。13是请求格式不正确;14读取的数据已经超过了传输的最大值,就是超限了;31我们刚才也已经提到过了,比如说请求的DID不支持,请求的DID在当前会话下不支持;33要求在解锁状态下,而现在没有处于解锁状态执行了响应的请求。

看一下由DID写入数据:2E服务。他的请求格式“2E+2个字节的DID+需要写入的数值”;肯定响应的格式“6E + DID”。这里举出来一个例子,由F1 90来写入VIN码,写入一个17字节的VIN码,这里简化,就打了省略号。当写入成功后,ECU回复肯定响应“6E +F1 90”

2E服务支持的NRC。31;3E;33;72和编程有关的,比如说在Bootloader刷写的过程中,需要对Flash进行操作,而写入数据没有写成功的时候,会回复72 NRC

下面我们来看和故障存储有关的服务。

2.5 故障存储相关的0x19和0x14服务

什么是故障呢?当系统检测到了一个错误或者是一个故障发生的时候,会将相对应的数值故障码进行存储,那么这个对应的数值故障码,我们称之为故障码,就是DTC。

一个DTC可以反应出一个故障发生的具体位置,和这个故障发生原因和类型,我们通过读取的DTC信息,可以为维修提供一些依据。除此以外还有与法律有关的故障,比如说排放有关的,在未来还会有安全相关的故障

通过这个故障可以反应出在ECU具体的哪一个位置,和产生的故障类型,在很多国际标准里面都定义了DTC的格式。比如说UDS里定义DTC由3个字节组成,而ISO 15031-6里定义了DTC格式由“两个字节根基+一个字节的故障类型”组成。那么我们常用的UDS服务里面DTC格式用的是哪一种呢?有95%用到的DTC格式都是ISO 15031-6里定义的DTC的故障类型和格式

ISO 15031-6定义的DTC格式什么样的呢?

两个字节的根字节来定义DTC,

左边前两位能反应DTC到底是哪一个系统:

00表示Powertrain;

01表示底盘;

10表示车身;

11是网络相关的。

左边第3~4位反应的是,DTC到底是由ISO,SAE,这些标准组织所定义的故障,还是由整车厂来定义命名的故障;

左边第5~8反应的是车辆系统的区域;

右边8位,这个字节具体的编码,就是DTC的编码。

在14229-1中定义的19服务读取DTC信息里,定义28个Subfunction,根据不同的Subfunction来获取不同的诊断信息,在这里我们介绍4个不同的Subfunction,这4个Subfunction也是在规范中常用的,他们分别是02;04;06;0A。

  • 19 02由DTC的状态码获取DTC;
  • 19 04读取DTC的快照数据。在14229里定义的数据叫做快照数据;在Autosar里定义的数据叫做冻结帧,其实他们指的是一类数据。快照数据是指当这个错误发生,或者当这个DTC存储的时候,记录的一些环境数据,比如说车速,水温,发动机转数等这些数据,从而我们读取这些数据之后,能够更好的判断DTC产生的原因以及发生故障原因。
  • 19 06是来获取DTC存储的时候一些扩展数据,这个数据常用的比如说有一些计数器,比如说老化计数器,这样的数据。
  • 19 0A是来读取这个ECU所支持的全部的DTC,ECU支持的哪些DTC是在ECU诊断规范的时候已经定义好的,所以我们通过19 0A读取的DTC是这个ECU应该支持的所有的DTC,即使这个DTC没有产生,也能够被读取的

刚才我们提到了DTC状态字节,这个DTC状态由8个位组成的一个字节。这8个位分别代表不同的含义,具体这8个位代表的含义,包括这8个位初始值是什么,它什么时候被置1,什么时候又被清0,它在什么情况下用,怎样用,在14229-1 2013版附录D有详细的定义。大家如果想具体了解这8个位的定义,可以参看附录D。

这里要提醒大家的是除了Bit4和Bit6以外,其它所有位的初始值都应该为0,而Bit4和Bit6的初始值位1。

常用的有比如说Bit0和Bit3.

Bit0当检测到这个故障,发生错误的时候被置1;

Bit3 ConfirmedDTC根据具体DTC的应用逻辑,这个DTC被检测到了多次,这个次数由具体的ECU规范定义,那么这一位也应该被置1。

我们通过19 02读取DTC的时候,会用到3个不同类型的DTC Status,那么这3个不同的DTC有什么区别呢:

  • 在请求报文里有一个字节的DTC Status Mask,这个是被Test用来读取DTC数据的,这个值可以是00到FF之间的任意值,根据所要读取的DTC内容决定。如果你想读取这个ECU产生的所有DTC,你可以用 0xFF.
  • 在肯定响应中,也有一个字节DTC Status Availability Mask,这个字节的DTC Status,是ECU诊断规范里定义的
  • 在肯定响应中,读取的DTC后面还有一个字节,是反应的这个DTC,所产生时,对应的状态信息。

我们来看具体的请求和响应格式,首先看19 02。19 02后面跟一个字节的Status Mask,第0位和第3位被置1,而这一个字节Mask,是在ECU诊断规范定义的,所以 59 02 +一个字节的Mask+具体的DTC+DTC后面的跟的DTC Status。

如果有多个DTC,后面会重复DTC的格式:3个字节的DTC+DTC Status。

通过19 0A读取ECU支持的所有DTC,请求格式是两个字节“19 + 0A”;肯定响应格式“59 + 0A+一个字节的Mask+后面跟ECU支持的所有DTC”

当诊断故障信息被存储了以后,我还需要,问题我们已经通过维修的方式解决了,我们用什么样的方法将这个DTC清除呢?

用到14服务清除诊断信息,14服务格式很简单,请求格式是“14 + 3个字节数值”,这3个字节的数值可以是针对单个DTC清除,也可以是按组来清除DTC,也可以是清除全部DTC。当3个字节都为FF时,表示将ECU里产生的所有DTC清除。

那我能不能按照组来清除DTC,比如说清除和车身有关的DTC,就按照车身这个组的数值,将它添加到请求报文格式里;

那我能不能单独清除,只针对某一个DTC,清除这个DTC,也是可以的。只需将这个DTC的具体数值放在请求报文,那么的肯定响应格式是一个字节54。

这个表格在14229中也有描述,大家可以具体参看。

3 结尾

欢迎大家给我留言,如果觉得好,动动你的手指,“点赞”+“收藏

获取更多汽车行业资讯,以及工具链的使用,可以关注微信公众号“汽车电子助手

或者扫描下方二维码进行关注

在这里插入图片描述

END

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qfmzhu/article/details/105716337

智能推荐

js-选项卡原理_选项卡js原理-程序员宅基地

文章浏览阅读90次。【代码】js-选项卡原理。_选项卡js原理

设计模式-原型模式(Prototype)-程序员宅基地

文章浏览阅读67次。原型模式是一种对象创建型模式,它采用复制原型对象的方法来创建对象的实例。它创建的实例,具有与原型一样的数据结构和值分为深度克隆和浅度克隆。浅度克隆:克隆对象的值类型(基本数据类型),克隆引用类型的地址;深度克隆:克隆对象的值类型,引用类型的对象也复制一份副本。UML图:具体代码:浅度复制:import java.util.List;/*..._prototype 设计模式

个性化政府云的探索-程序员宅基地

文章浏览阅读59次。入选国内首批云计算服务创新发展试点城市的北京、上海、深圳、杭州和无锡起到了很好的示范作用,不仅促进了当地产业的升级换代,而且为国内其他城市发展云计算产业提供了很好的借鉴。据了解,目前国内至少有20个城市确定将云计算作为重点发展的产业。这势必会形成新一轮的云计算基础设施建设的**。由于云计算基础设施建设具有投资规模大,运维成本高,投资回收周期长,地域辐射性强等诸多特点,各地在建...

STM32问题集之BOOT0和BOOT1的作用_stm32boot0和boot1作用-程序员宅基地

文章浏览阅读9.4k次,点赞2次,收藏20次。一、功能及目的 在每个STM32的芯片上都有两个管脚BOOT0和BOOT1,这两个管脚在芯片复位时的电平状态决定了芯片复位后从哪个区域开始执行程序。BOOT1=x BOOT0=0 // 从用户闪存启动,这是正常的工作模式。BOOT1=0 BOOT0=1 // 从系统存储器启动,这种模式启动的程序_stm32boot0和boot1作用

C语言函数递归调用-程序员宅基地

文章浏览阅读3.4k次,点赞2次,收藏22次。C语言函数递归调用_c语言函数递归调用

明日方舟抽卡模拟器wiki_明日方舟bilibili服-明日方舟bilibili服下载-程序员宅基地

文章浏览阅读410次。明日方舟bilibili服是一款天灾驾到战斗热血的创新二次元废土风塔防手游,精妙的二次元纸片人设计,为宅友们源源不断更新超多的纸片人老婆老公们,玩家将扮演废土正义一方“罗德岛”中的指挥官,与你身边的感染者们并肩作战。与同类塔防手游与众不同的几点,首先你可以在这抽卡轻松获得稀有,同时也可以在战斗体系和敌军走位机制看到不同。明日方舟bilibili服设定:1、起因不明并四处肆虐的天灾,席卷过的土地上出..._明日方舟抽卡模拟器

随便推点

Maven上传Jar到私服报错:ReasonPhrase: Repository version policy: SNAPSHOT does not allow version: xxx_repository version policy snapshot does not all-程序员宅基地

文章浏览阅读437次。Maven上传Jar到私服报错:ReasonPhrase: Repository version policy: SNAPSHOT does not allow version: xxx_repository version policy snapshot does not all

斐波那契数列、素数、质数和猴子吃桃问题_斐波那契日-程序员宅基地

文章浏览阅读1.2k次。斐波那契数列(Fibonacci Sequence)是由如下形式的一系列数字组成的:0, 1, 1, 2, 3, 5, 8, 13, 21, 34, …上述数字序列中反映出来的规律,就是下一个数字是该数字前面两个紧邻数字的和,具体如下所示:示例:比如上述斐波那契数列中的最后两个数,可以推导出34后面的数为21+34=55下面是一个更长一些的斐波那契数列:0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584,_斐波那契日

PHP必会面试题_//该层循环用来控制每轮 冒出一个数 需要比较的次数-程序员宅基地

文章浏览阅读363次。PHP必会面试题1. 基础篇1. 用 PHP 打印出前一天的时间格式是 2017-12-28 22:21:21? //>>1.当前时间减去一天的时间,然后再格式化echo date('Y-m-d H:i:s',time()-3600*24);//>>2.使用strtotime,可以将任何字符串时间转换成时间戳,仅针对英文echo date('Y-m-d H:i:s',str..._//该层循环用来控制每轮 冒出一个数 需要比较的次数

windows用mingw(g++)编译opencv,opencv_contrib,并install安装_opencv mingw contrib-程序员宅基地

文章浏览阅读1.3k次,点赞26次,收藏26次。windows下用mingw编译opencv貌似不支持cuda,选cuda会报错,我无法解决,所以没选cuda,下面两种编译方式支持。打开cmake gui程序,在下面两个框中分别输入opencv的源文件和编译目录,build-mingw为你创建的目录,可自定义命名。1、如果已经安装Qt,则Qt自带mingw编译器,从Qt安装目录找到编译器所在目录即可。1、如果已经安装Qt,则Qt自带cmake,从Qt安装目录找到cmake所在目录即可。2、若未安装Qt,则安装Mingw即可,参考我的另外一篇文章。_opencv mingw contrib

5个高质量简历模板网站,免费、免费、免费_hoso模板官网-程序员宅基地

文章浏览阅读10w+次,点赞42次,收藏309次。今天给大家推荐5个好用且免费的简历模板网站,简洁美观,非常值得收藏!1、菜鸟图库https://www.sucai999.com/search/word/0_242_0.html?v=NTYxMjky网站主要以设计类素材为主,办公类素材也很多,简历模板大部个偏简约风,各种版式都有,而且经常会更新。最重要的是全部都能免费下载。2、个人简历网https://www.gerenjianli.com/moban/这是一个专门提供简历模板的网站,里面有超多模板个类,找起来非常方便,风格也很多样,无须注册就能免费下载,_hoso模板官网

通过 TikTok 联盟提高销售额的 6 个步骤_tiktok联盟-程序员宅基地

文章浏览阅读142次。你听说过吗?该计划可让您以推广您的产品并在成功销售时支付佣金。它提供了新的营销渠道,使您的产品呈现在更广泛的受众面前并提高品牌知名度。此外,TikTok Shop联盟可以是一种经济高效的产品或服务营销方式。您只需在有人购买时付费,因此不存在在无效广告上浪费金钱的风险。这些诱人的好处是否足以让您想要开始您的TikTok Shop联盟活动?如果是这样,本指南适合您。_tiktok联盟