[AUTOSAR][诊断管理][ECU][$19] 读取ECU的DTC故障信息

一、简介

  1. 在车载诊断中常用的诊断协议有ISO 14229等,在协议中主要定义了诊断请求、诊断响应的报文格式及ECU该如何处理诊断请求的应用。
  2. 其中ISO 14229系列标准协议定义了用于行业内诊断通信的需求规范,也就是UDS。UDS主要应用于OSI七层模型的第七层——应用层,它支持的汽车总线包括:CAN、LIN、FlexRay、Ethernet及K-LINE。
  3. UDS中的服务根据其功能分为6大类,共26种。其中包含的0x19服务(ReadDTCInformation)则是UDS中的重中之重。那么我们今天就一起进入到19服务中,感受其中的奥秘。

二、 服务介绍

19服务(ReadDTCInformation)用于读取ECU的DTC故障信息,此服务允许客户端从服务器读取诊断故障代码(DTC)的相关信息。此服务包含28个子服务(Subfunction),常用的5种子服务如下:

  • 0x01 reportNumberOfDTCByStatusMask(读取客户端定义状态掩码匹配的DTC数量)
  • 0x02 reportDTCByStatusMask(读取客户端定义状态掩码匹配的DTC)
  • 0x04 reportDTCSnapshotRecordByDTCNumber(检索客户端定义DTC掩码的快照数据)
  • 0x06 reportDTCExtDataRecordByDTCNumber(读取某个DTC及其相关的扩展数据,扩展数据包括DTC状态,优先级,发生次数,时间戳,里程等。)
  • 0x0A reportSupportedDTC(读取ECU支持的所有DTC的状态,包含支持的各个DTC编号以及相关状态)

今天主要解析19服务中的04子服务,也就是检索客户端定义DTC的快照号对应的快照记录数据,在AUTOSAR中也叫冻结帧。

(1)子服务介绍

  1. 快照数据概念介绍
    前面讲19服务常用子服务的时候,提到了Subfunction为04的子服务,使用04子服务对服务端进行请求,可以获取DTC发生时记录的快照数据。那04子服务是如何获取快照数据的呢?首先我们需要理解什么是快照数据。从ISO 14229-1协议可知,快照数据为发生某一故障时记录的DTC的电压、发动机转速、时间戳等,从而使工程师在ECU出现故障时能及时了解车辆的历史和实时故障信息。

  2. 报文格式介绍
    接下来通过介绍19 04子服务请求和响应的报文格式,分析报文中各个字节的相关定义。

请求格式

在这里插入图片描述
从图1中可知,19 04的请求报文包括四个部分,其中服务ID和Subfunction就不用过多解释了。DTCMaskRecord表示某个故障的DTC,当系统检测到一个故障发生时,则会存储其对应的故障数值,这个故障数值就是DTC。通过读取DTC可知一个故障发生时的具体位置以及原因和类型。通常UDS中DTC占3个字节,OBD Ⅱ占2个字节,在ISO 15031-6中定义的DTC由两个字节根基和一个字节的故障类型组成。我们通常用到的DTC格式都是由ISO 15031-6中定义的。图2是ISO 15031-6中定义的DTC的两个字节根基,图中很详细地解释了每一个Bit的含义。

在这里插入图片描述
SnapshotRecordNumber需要提前定义,可以有多个。如SnapshotRecordNumber设置为FF,则表示读取所有的快照数据组。

响应格式

图3
图3为响应报文格式,当使用19 04对ECU进行请求时,ECU给出的肯定响应的报文格式由七部分组成。此时的DTCAndStatusRecord由三个字节的DTC和一个字节的StatusOfDTC组成,StatusOfDTC表示DTC的状态。假设现在的DTC状态为0x09,则Bit0和Bit3置1。如某个DTC一直存在并且确认,则在ECU响应的报文中的StatusOfDTC为0x09。如图4
图4
SnapshotRecordNumber这个字节表示DTC快照记录的组号;DTCSnapshotRecordNumberOfldentifiers表示快照DID的个数,占一个字节;Dataldentifier这部分由两个字节组成,表示快照数据对应的DID,DTCSnapshotRecord表示快照DID对应的具体数据。

三、示例代码

(1)19_read_dtc_info.c

/********************************************************************************
* @file    19_read_dtc_info.c
* @author  jianqiang.xue
* @version V1.0.0
* @date    2023-05-30
* @brief   读取DTC信息
********************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#include "modules.h"
#include "os_api.h"
#include "edebug.h"
#include "kv_sys.h"
#include "ecu_ble_uart.h"
/* Private includes ----------------------------------------------------------*/
#include "std_math.h"
#include "app_can.h"
#include "can_nm.h"
#include "app_nm.h"
#include "diag_main.h"
#if AUTOSAR_DIAG_DTC_SWITCH
#include "dtc_main.h"
#endif
/* Private define ------------------------------------------------------------*/
#define UDS_ID         0x19
#define MAX_BUFF_SIZE  150
/* Private typedef -----------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/***************软定时器创建***************/
/* Private func --------------------------------------------------------------*//*** @brief  通过状态掩码报告DTC数目* @param  *data: 数据指针* @param  len: 数据长度* @retval 0--成功  >0--错误*/
static int8_t uds19_01(uint8_t *data, uint16_t len, uint8_t *out) {if (len != 3) {LOGE("len err != 3, sub%02x", data[1]);send_nrc_data(UDS_ID, NRC_INCORRECT_MESSAGE_LENTH);return 1;}if (data[1] & 0x80) { // 无需应答LOGI("No answer required, sub%02x", data[1]);} else {// 回复正响应码  单帧格式: len, 服务ID|0x40, 子功能ID,out[0] = 6;  // 数据总长度= 服务号 + sub_id + mask + data + num(2byte)out[1] = UDS_ID | 0x40;   // 服务号,回复上位机需要 |0x40out[2] = data[1];out[3] = AUTOSAR_DIAG_DTC_STATE_BIT; // 获取DTC掩码out[4] = 0; // SAE_J2012-DA_DTCFormat_00uint16_t dtc_count = get_dtc_num_by_mask(data[2]);out[5] = (uint8_t)(dtc_count >> 8);out[6] = (uint8_t)(dtc_count & 0xFF);out[7] = 0xAA;app_can_enqueue_msg(CAN_MSG_EVENT_SEND, NWL_RES_ADDR, out, 8);}return 0;
}/*** @brief  通过状态掩码报告DTC* @param  *data: 数据指针* @param  len: 数据长度* @retval 0--成功  >0--错误*/
static int8_t uds19_02(uint8_t *data, uint16_t len, uint8_t *out) {if (len != 3) {LOGE("len err != 3, sub%02x", data[1]);send_nrc_data(UDS_ID, NRC_INCORRECT_MESSAGE_LENTH);return 1;}if (data[1] & 0x80) { // 无需应答LOGI("No answer required, sub%02x", data[1]);} else {// 回复正响应码  单帧格式: len, 服务ID|0x40, 子功能ID,out[1] = UDS_ID | 0x40;   // 服务号,回复上位机需要 |0x40out[2] = data[1];out[3] = AUTOSAR_DIAG_DTC_STATE_BIT; // 获取DTC掩码uint8_t d_len = 0;d_len = get_dtc_status_by_mask(data[2], &out[4], MAX_BUFF_SIZE - 4 - 1); // 4--数据头 1--连续帧头预留out[0] = 3 + d_len; // 数据总长度 = 服务号 + sub_id + mask + ndata// 判断数据长度,单帧还是连续帧发送if (out[0] > 7) {memmove(out + 1, out, out[0] + 1); // 单帧改连续帧格式,数据总长度 + 长度位,数据总长度 + 长度位out[0] = NWL_FIRST_FRAME << 4; // 数据帧格式(nwl_frame_st_t)if (g_tx_msg.data != 0) {free(g_tx_msg.data);g_tx_msg.data = NULL;}// 发送首帧(只含6byte data)后,剩余长度:去除 (服务号|sub_id|mask + D0D1D2)d_len = out[1] - 3 - 3;g_tx_msg.data = malloc(d_len);if (g_tx_msg.data == NULL) {send_nrc_data(UDS_ID, NRC_ACCESS_DENIED);return 2;}app_can_enqueue_msg(CAN_MSG_EVENT_SEND, NWL_RES_ADDR, out, 8);memcpy(g_tx_msg.data, out + 8, d_len);g_tx_msg.len = d_len;} else {memset(&out[out[0] + 1], 0xAA, 8 - out[0] - 1);  // 空白区填充指定值app_can_enqueue_msg(CAN_MSG_EVENT_SEND, NWL_RES_ADDR, out, 8);}}return 0;
}/*** @brief  通过DTC码报告DTC 快照记录* @param  *data: 数据指针* @param  len: 数据长度* @retval 0--成功  >0--错误*/
static int8_t uds19_04(uint8_t *data, uint16_t len, uint8_t *out) {uint32_t dtc_id;if (len != 6) {LOGE("len err != 6, sub%02x", data[1]);send_nrc_data(UDS_ID, NRC_INCORRECT_MESSAGE_LENTH);return 1;} else { // == 6uint8_t record_numb = data[5]; // 记录号if ((record_numb > SS_NB_MAX) && record_numb != 0xFF && record_numb != 0x00) {LOGE("record numb nonsupport:%02x, sub%02x", record_numb, data[1]);send_nrc_data(UDS_ID, NRC_REQUEST_OUT_OF_RANGE);return 2;}dtc_id = data[2];dtc_id <<= 8;dtc_id += data[3];dtc_id <<= 8;dtc_id += data[4];uint8_t SN = is_dtc_id(dtc_id); // 得到dtc id,对应的数组索引if (SN == 0xFF) {LOGE("dtc id id err:%02x, sub%02x", dtc_id, data[1]);send_nrc_data(UDS_ID, NRC_SUBFUNCTION_NOT_SUPPORTED);return 2;}if (data[1] & 0x80) { // 无需应答LOGI("No answer required, sub%02x", data[1]);} else {// 回复正响应码  单帧格式: len, 服务ID|0x40, 子功能ID,out[1] = UDS_ID | 0x40;   // 服务号,回复上位机需要 |0x40out[2] = data[1]; // SUB_ID 子功能IDout[3] = data[2]; // DTC_ID 低16bitout[4] = data[3]; // DTC_ID 高8bitout[5] = data[4]; // DTC_ID 低8bitout[6] = get_dtc_snap_shot_status(SN, record_numb); // DTC Status 最近一次错误状态out[7] = record_numb;out[8] = SS_TYPE_MAX_NUMBER;uint16_t d_len = 0;d_len = get_dtc_snap_shot_by_id(SN, record_numb, &out[9], MAX_BUFF_SIZE - 8 - 1); // 7--数据头 1--连续帧头预留// 数据总长度 = 服务号 + 子功能ID + DTC_ID(3byte) + DTC Status + record_numb + MAX_NUMBER + DATA_LENout[0] = 8 + d_len;memmove(out + 1, out, out[0] + 1); // 单帧改连续帧格式,数据总长度 + 长度位out[0] = NWL_FIRST_FRAME << 4; // 数据帧格式(nwl_frame_st_t)if (g_tx_msg.data != 0) {free(g_tx_msg.data);g_tx_msg.data = NULL;}// 发送首帧(只含6byte data)后,剩余长度:去除 (服务号 + 子功能ID + DTC_ID(3byte) + DTC Status)d_len = out[1] - 2 - 3 - 1;g_tx_msg.data = malloc(d_len);if (g_tx_msg.data == NULL) {send_nrc_data(UDS_ID, NRC_ACCESS_DENIED);return 3;}app_can_enqueue_msg(CAN_MSG_EVENT_SEND, NWL_RES_ADDR, out, 8);memcpy(g_tx_msg.data, out + 8, d_len);g_tx_msg.len = d_len;}}return 0;
}/*** @brief  通过DTC码报告DTC扩展数据记录* @param  *data: 数据指针* @param  len: 数据长度* @retval 0--成功  >0--错误*/
static int8_t uds19_06(uint8_t *data, uint16_t len, uint8_t *out) {uint32_t dtc_id;if (len != 6) {LOGE("len err != 6, sub%02x", data[1]);send_nrc_data(UDS_ID, NRC_INCORRECT_MESSAGE_LENTH);return 1;}uint8_t record_numb = data[5];  // 记录号if ((record_numb > SS_NB_MAX) && record_numb != 0xFF && record_numb != 0x00) {LOGE("record numb nonsupport:%02x, sub%02x", record_numb, data[1]);send_nrc_data(UDS_ID, NRC_REQUEST_OUT_OF_RANGE);return 2;}dtc_id = data[2];dtc_id <<= 8;dtc_id += data[3];dtc_id <<= 8;dtc_id += data[4];uint8_t SN = is_dtc_id(dtc_id); // 得到dtc id,对应的数组索引if (SN == 0xFF) {LOGE("dtc id id err:%02x, sub%02x", dtc_id, data[1]);send_nrc_data(UDS_ID, NRC_SUBFUNCTION_NOT_SUPPORTED);return 2;}if (data[1] & 0x80) { // 无需应答LOGI("No answer required, sub%02x", data[1]);} else {// 回复正响应码  单帧格式: len, 服务ID|0x40, 子功能ID,out[1] = UDS_ID | 0x40;   // 服务号,回复上位机需要 |0x40out[2] = data[1]; // SUB_ID 子功能IDout[3] = data[2]; // DTC_ID 低16bitout[4] = data[3]; // DTC_ID 高8bitout[5] = data[4]; // DTC_ID 低8bitout[6] = get_dtc_snap_shot_status(SN, record_numb); // DTC Status 最近一次错误状态out[7] = record_numb;//os_delay(1);uint16_t d_len = 0;d_len = get_dtc_snap_shot_ex_data(SN, record_numb, &out[8], MAX_BUFF_SIZE - 8 - 1); // 7--数据头 1--连续帧头预留// 数据总长度 = 服务号 + 子功能ID + DTC_ID(3byte) + DTC Status + record_numb  + DATA_LENout[0] = 7 + d_len;if (out[0] > 7) {memmove(out + 1, out, out[0] + 1); // 单帧改连续帧格式,数据总长度 + 长度位out[0] = NWL_FIRST_FRAME << 4; // 数据帧格式(nwl_frame_st_t)if (g_tx_msg.data != 0) {free(g_tx_msg.data);g_tx_msg.data = NULL;}// 发送首帧(只含6byte data)后, 去除 (服务号 + 子功能ID + DTC_ID(3byte) + DTC Status)d_len = out[1] - 2 - 3 - 1;g_tx_msg.data = malloc(d_len);if (g_tx_msg.data == NULL) {send_nrc_data(UDS_ID, NRC_ACCESS_DENIED);return 3;}memcpy(g_tx_msg.data, out + 8, d_len);g_tx_msg.len = d_len;app_can_enqueue_msg(CAN_MSG_EVENT_SEND, NWL_RES_ADDR, out, 8);} else {memset(&out[out[0] + 1], 0xAA, 8 - out[0] - 1);  // 空白区填充指定值app_can_enqueue_msg(CAN_MSG_EVENT_SEND, NWL_RES_ADDR, out, 8);}}return 0;
}/*** @brief  报告支持的全部DTC* @param  *data: 数据指针* @param  len: 数据长度* @retval 0--成功  >0--错误*/
static uint8_t uds19_0A(uint8_t *data, uint16_t len, uint8_t *out) {if (len != 2) {LOGE("len err != 2, sub%02x", data[1]);send_nrc_data(UDS_ID, NRC_INCORRECT_MESSAGE_LENTH);return 1;}if (data[1] & 0x80) { // 无需应答LOGI("No answer required, sub%02x", data[1]);} else {// 回复正响应码  单帧格式: len, 服务ID|0x40, 子功能ID, maskout[1] = UDS_ID | 0x40;   // 服务号,回复上位机需要 |0x40out[2] = data[1]; // SUB_ID 子功能IDout[3] = AUTOSAR_DIAG_DTC_STATE_BIT; // 掩码uint16_t d_len = 0;d_len = get_all_dtc_status(&out[4], MAX_BUFF_SIZE - 4 - 1); // 4--数据头 1--连续帧头预留// 数据总长度 = 服务号 + 子功能ID + 掩码  + DATA_LENout[0] = 3 + d_len;// LOGD("%u,%u\r\n", out[0], d_len);if (out[0] > 7) {memmove(out + 1, out, out[0] + 1); // 单帧改连续帧格式,数据总长度 + 长度位out[0] = NWL_FIRST_FRAME << 4; // 数据帧格式(nwl_frame_st_t)if (g_tx_msg.data != 0) {free(g_tx_msg.data);g_tx_msg.data = NULL;}// 发送首帧(只含6byte data)后, 去除 (服务号 + 子功能ID + DTC_ID(3byte) + DTC Status)d_len = out[1] - 2 - 3 - 1;g_tx_msg.data = malloc(d_len);if (g_tx_msg.data == NULL) {send_nrc_data(UDS_ID, NRC_ACCESS_DENIED);return 3;}memcpy(g_tx_msg.data, out + 8, d_len);LOGD("%x,%u,%x,%u\r\n", g_tx_msg.data[d_len-1], d_len, out[out[1]+1], out[1]+1);g_tx_msg.len = d_len;app_can_enqueue_msg(CAN_MSG_EVENT_SEND, NWL_RES_ADDR, out, 8);} else {memset(&out[out[0] + 1], 0xAA, 8 - out[0] - 1);  // 空白区填充指定值app_can_enqueue_msg(CAN_MSG_EVENT_SEND, NWL_RES_ADDR, out, 8);}}return 0;
}void uds19_main(nwl_msg_t* p) {uint8_t data[MAX_BUFF_SIZE];uint8_t d_len = 0;if (p->len < 2) {LOGE("len err < 2");send_nrc_data(UDS_ID, NRC_INCORRECT_MESSAGE_LENTH);goto end;}switch (p->data[1] & 0x7F) { // 子功能,bit7为应答位。  =1则不允许应答// 通过状态掩码报告DTC数目case 0x01: {if (uds19_01(p->data, p->len, data) != 0) {}break;}// 通过状态掩码报告DTCcase 0x02:if (uds19_02(p->data, p->len, data) != 0) {}break;// 通过DTC码报告DTC 快照记录case 0x04: {if (uds19_04(p->data, p->len, data) != 0) {}break;}// 通过DTC码报告DTC扩展数据记录case 0x06: {if (uds19_06(p->data, p->len, data) != 0) {}break;}// 报告支持的全部DTCcase 0x0A: {if (uds19_0A(p->data, p->len, data) != 0) {}break;}default:send_nrc_data(UDS_ID, NRC_SUBFUNCTION_NOT_SUPPORTED);break;}
end:return;
}#if AUTOSAR_DIAG_SWITCH && USE_UDS_19 && AUTOSAR_DIAG_DTC_SWITCH
DIAG_SERVICE_REG(UDS_ID, DIAG_NO_SECURITY_LEVEL, (DEFAULT_SESSION|EXTENDED_SESSION),(DIAG_PHYS_REQ|DIAG_FUNC_REQ), NULL, NULL, uds19_main);
#endif

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

论文解读:Large Language Models as Analogical Reasoners

一、动机 大模型在各种类型的NLP任务上均展现出惊艳的表现。基于CoT propmt能够更好地激发大模型解决复杂推理问题的能力&#xff0c;例如解决数学解题&#xff0c;可以让模型生成reasoning path。现有的经典的CoT方法有few-shot cot、zero-shot cot等。然后现有的cot面临两个…

vue后台第二部步(布局和封装图标组件)

目录结构&#xff1b;根据需求修改、创建对应目录&#xff1b; src 应用部署目录├─api 接口├─assets 公共文件│ ├─theme.scss 主题样式…

数据库监控:关键指标和注意事项

【squids.cn】 全网zui低价RDS&#xff0c;免费的迁移工具DBMotion、数据库备份工具DBTwin、SQL开发工具等 听到模糊的说法“我们的数据库有问题”对于任何数据库管理员或管理员来说都是一场噩梦。有时是真的&#xff0c;有时不是&#xff0c;到底问题出在哪里呢&#xff1f;真…

《语音优先》智能语音技术驱动的交互界面设计与语音机器人设计(译者序)...

“言为心声,语为心境”&#xff0c;语言与对话是我们沟通与协作的重要方式。而智能语音技术是一种基于人工智能和自然语言处理技术的语音交互技术。它可以通过语音识别技术将用户的语音指令转换为文本&#xff0c;然后通过自然语言处理技术对文本进行分析和理解&#xff0c;最终…

2023Etsy入驻攻略——防封安全

2023了&#xff0c;跨境电商现在上车还来得及吗&#xff1f;当然&#xff01;Etsy是一个低成本低竞争高回报的平台&#xff0c;相较于其他电商平台&#xff0c;他的佣金非常低&#xff0c;利润率更高&#xff0c;非常合适跨境小白入局。 但由于目前Etsy关闭了中国大陆卖家的注…

FTP服务器操作手册

FTP服务器(File Transfer Protocol Server)是在互联网上提供文件存储和访问服务的计算机&#xff0c;它们依照FTP协议提供服务。FTP协议是File Transfer Protocol(文件传输协议)&#xff0c;专门用来传输文件的协议。FTP服务器是企业里经常用到的服务器&#xff0c;今天就介绍一…

Qt 项目实战 | 多界面编辑器

Qt 项目实战 | 多界面编辑器 Qt 项目实战 | 多界面编辑器界面设计创建子窗口类 官方博客&#xff1a;https://www.yafeilinux.com/ Qt开源社区&#xff1a;https://www.qter.org/ 参考书&#xff1a;《Qt 及 Qt Quick 开发实战精解》 Qt 项目实战 | 多界面编辑器 开发环境&…

最新Jn建站系统2.0 已集成各类源码 【附视频安装教程】

附视频安装教程|已集成各类源码 目前已集成的网站&#xff1a; 1.发卡网(最新) 2.代刷网(无需授权) 3. 博客网(自带模板) 4.易支付(稳定版) 5.个人导航网(简洁) 6.代理查询网 7.留言网 8.匿名网 9.表白墙(最新) 10.抽奖网 11.源码站 12.z-blog博客程序 13.织梦CM…

在Word中,图片显示不全

在今天交作业的时候&#xff0c;发现了一个非常SB的事情&#xff0c;把图片复制过去显示不完全&#xff1a; 使用文心一言查看搜索了一下&#xff0c;发现可能是以下几种原因&#xff1a; 图片所在行的行高设置不正确。可以重新设置行高&#xff0c;具体步骤包括打开图片显示…

自然语言处理---RNN经典案例之构建人名分类器

1 案例介绍 关于人名分类问题&#xff1a;以一个人名为输入, 使用模型帮助判断它最有可能是来自哪一个国家的人名&#xff0c;这在某些国际化公司的业务中具有重要意义&#xff0c;在用户注册过程中&#xff0c;会根据用户填写的名字直接给他分配可能的国家或地区选项&#xff…

【C语言进阶】指针进阶(三)

指针进阶&#xff08;三&#xff09; 9.指针和数组笔试题解析10.指针笔试题 9.指针和数组笔试题解析 数组名的理解 数组名是数组首元素的地址 但是有2个例外&#xff1a; sizeof(数组名)&#xff0c;这里的数组名表示整个数组&#xff0c;sizeof(数组名)计算的是整个数组的大…

SpringMVC(三)获取请求参数

1.1通过ServletAPI获取 SpringMVC封装的就是原生的servlet 我们进行测试如下所示&#xff1a; package com.rgf.controller.service;import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping;import javax.servlet.…

纺织工厂数字孪生3D可视化管理平台,推动纺织产业数字化转型

近年来&#xff0c;我国加快数字化发展战略部署&#xff0c;全面推进制造业数字化转型&#xff0c;促进数字经济与实体经济深度融合。以数字孪生、物联网、云计算、人工智能为代表的数字技术发挥重要作用。聚焦数字孪生智能工厂可视化平台&#xff0c;推动纺织制造业数字化转型…

OpenCV17-图像形态学操作

OpenCV17-图像形态学操作 1.形态学操作1.1腐蚀1.2膨胀 2.形态学应用2.1开运算2.2闭运算2.3形态学梯度2.4顶帽运算2.5黑帽运算2.6击中击不中变换2.7形态学应用示例 1.形态学操作 1.1腐蚀 图像腐蚀&#xff08;Image erosion&#xff09;可用于减小图像中物体的大小、填充孔洞或…

css之Flex弹性布局(子项常见属性)

文章目录 &#x1f380;前言&#xff1a;本篇博客介绍弹性布局flex容器中子项的常见用法&#x1fa80;flex:子项目占得份数 &#xff08;划分不同子项的比例&#xff09;&#x1f387;align-self 控制单独一个子项在侧轴的排列方式&#x1f9f8;order属性定义子项的排列顺序 &a…

酷开科技 | 酷开系统,为居家生活打开更精彩的窗口

电视在我们的日常生活中扮演着重要的角色。虽然&#xff0c;作为客厅C位的扛把子——电视的娱乐作用深入人心&#xff0c;但是&#xff0c;它的涵义和影响力却因我们每个人的具体生活环境而存在着种种差异&#xff0c;而我们的生活环境又受到我们所处的社会及文化环境的影响。 …

一文了解AIGC与ChatGPT

一、AIGC简介 1.AIGC基础 (1)AIGC是什么 AIGC是人工智能图形计算的缩写&#xff0c;是一种基于图形处理器&#xff08;GPU&#xff09;的计算技术&#xff0c;可以加速各种计算任务&#xff0c;包括机器学习、深度学习、计算机视觉等。 AIGC是一种基于GPU的计算技术&#x…

Git(一)Windows下安装及使用Git Bash

目录 一、简介1.1 什么是Git&#xff1f;1.2 Git 的主要特点1.3 什么是 Git Bash&#xff1f; 二、下载三、安装3.1 同意协议3.2 选择安装位置3.3 其他配置&#xff08;【Next】 即可&#xff09;3.4 安装完毕3.5 打开 Git Bash 官网地址&#xff1a; https://www.git-scm.com/…

包管理工具

代码共享方案 放到npm仓库&#xff0c;下载到本地放到node_modules npm配置文件 必须填写的属性&#xff1a;name、version name是项目的名称&#xff1b; version是当前项目的版本号&#xff1b; description是描述信息&#xff0c;很多时候是作为项目的基本描述&#xff1b…

力扣每日一题61:旋转链表

题目描述&#xff1a; 给你一个链表的头节点 head &#xff0c;旋转链表&#xff0c;将链表每个节点向右移动 k 个位置。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], k 2 输出&#xff1a;[4,5,1,2,3]示例 2&#xff1a; 输入&#xff1a;head [0,1,2], k 4 输…