热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

基于CAN总线的汽车诊断协议UDS(ECU底层模块移植开发)

一、意义为了指导开发工程师,正确的使用诊断模块,快速开发出满足车厂要求的诊断功能。二、诊断模块介绍此诊断模块根据ISO-14229-1文档,并结合部分车厂的文档进行开发,使用面向对

一、意义
为了指导开发工程师,正确的使用诊断模块,快速开发出满足车厂要求的诊断功能。

二、诊断模块介绍

此诊断模块根据ISO-14229-1文档,并结合部分车厂的文档进行开发,使用面向对象的思路进行设计,将模块需要处理的所有事情封装在模块内部,留出模块处理过程接口和配置接口供调用接口的工程师使用。通过调用配置接口,可以配置我们想要的功能。通过调用处理过程接口,诊断模块便能提供诊断服务,无需其他操作,便能实现诊断功能,开发起来方便快捷。

使用过程中的复杂之处在于配置,需要根据具体项目的诊断需求进行具体配置。以下详细介绍。

三、接口与配置说明

1、类型定义

1)、安全等级定义

typedef enum{

       LEVEL_ZERO = 7,//安全等级0,当一个服务不需要安全解锁时,使用此安全等级。

       LEVEL_OnE= 1,//安全等级1,当一个服务可以在安全等级1时,使用此安全等级。

       LEVEL_TWO = 2,//安全等级2,当一个服务可以在安全等级2时,使用此安全等级。

       LEVEL_THREE = 4,//安全等级3,当一个服务可以在安全等级3时,使用此安全等级。

LEVEL_FOUR = 8,//安全等级4,工厂模式会话使用此安全等级,用户零部件商下线配置。

       LEVEL_UNSUPPORT = 0,//不支持,当一个服务在某个会话模式不支持时,使用此等级。

}SecurityLevel;

2)、复位类型,参考ISO-14229-1中11服务复位类型的定义。

typedef enum{

       HARD_RESET = 1,//硬件复位

       KEY_OFF_ON_RESET = 2,//关开钥匙复位

       SOFT_RESET = 3,//软件复位

       ENABLE_RAPID_POWER_SHUTDOWN = 4,//预留,一般不使用

       DISABLE_RAPID_POWER_SHUTDOWN = 5,//预留,一般不使用

}EcuResetType;

3)、DTC类型定义。

typedef enum{

       ISO15031_6DTCFORMAT= 1,

       ISO14229_1DTCFORMAT = 2,

       SAEJ1939_73DTCFORMAT = 3,

}DTCFormatIdentifier;

 

 

 

4)、诊断故障状态定义

typedef enum{

       PASSED,//测试通过

       IN_TESTING,//测试未完成

       FAILED,//测试失败

}DTCTestResult;

5)DID类型定义

typedef enum{

       EEPROM_DID,//静态存储器DID,存储在EEPROM中的DID使用此类型

       REALTIME_DID,//实时DID,存储在RAM中,会实时改变的数据使用此类型

       IO_DID,//输入输出控制DID,需要通过2F服务控制的DID使用此类型

}DIDType;

6)、DID的读写属性

typedef enum{

       READOnLY= 1,//只读

       WRITEOnLY= 2,//只写

       READWRITE = 3,//可读写

}ReadWriteAttr;

7)、通信控制参数

typedef enum{

       ERXTX,//enableRxAndTx

       ERXDTX,//enableRxAndDisableTx

       DRXETX,//disableRxAndEnableTx

       DRXTX,//disableRxAndTx

       //ERXDTXWEAI,//enableRxAndDisableTxWithEnhancedAddressInformation

       //ERXTXWEAI,//enableRxAndTxWithEnhancedAddressInformation

}CommulicationType;

8)、通信控制的控制对象参数

typedef enum{

       NCM = 1,//application message

       NWMCM,//network manage message

       NWMCM_NCM,//application and netwrok manage message

}communicationParam;

9)、子功能在会话的支持情况

typedef enum{

       SUB_DEFAULT = 1,//sub function supported in default session

       SUB_PROGRAM = 2,//sub function supported in program session

       SUB_EXTENDED = 4,////sub function supported in extedned session

SUB_FACTORY = 8,//sub funcion supported in factory session,

       SUB_ALL = 7,//sub function supported in both of three session

}SubFunSuppInSession;

10)、诊断故障码的等级,仅在HD10中有使用

typedef enum{

       LEVEL_A,

       LEVEL_B,

       LEVEL_C,

}DTCLevel;

11)、输入输出控制接口函数原型

typedef uint8_t (*IoControl)(uint8_t ctrl, uint8_t param);

Ctrl表示控制类型:

0:归还控制权到ECU

1:恢复默认状态

2:冻结当前

3:短时调整

只有当ctrl为3时存在param,param参数根据具体的DID而不同,如当控制开关时,可以表示为:

0:关

1:开,

如控制档位时

1:1档

2:2档

....

12)、安全解锁算法接口函数原型

typedef uint32_t (*SecurityFun)(uint32_t);

此原型表示一个函数指针,有一个uint32_t型的参数,表示种子。返回uint32_t型值,表示根据算法算出的秘钥

13)、DTC的检测接口函数原型

typedef DTCTestResult (*DetectFun)(void);

无参数,需要返回DTCTestResult 类型的值,2表示测试失败,0表示测试通过,1表示正在测试(测试未完成)。

14)、复位接口函数原型。

typedef void (*ResetCallBack)(EcuResetType);

参数

EcuResetType:复位类型,取值范围,1-5,分别表示硬件复位,key-off-on复位,软件复位。通常用1和3。

15)、通信控制接口函数原型

typedef void (*CommCallBack)(CommulicationType , communicationParam);

参数:

CommulicationType :参考1.7定义

communicationParam:参考1.8定义

16)、CAN发送接口函数原型

typedef uint8_t (*SendCANFun)(uint32_t ID, uint8_t *array, uint8_t length, uint8_t priority);

注:以上所有接口函数原型供诊断开发时使用,开发时必须提供以上接口,否则诊断模块将无法正常工作。

 

#define       USE_MALLOC              0//1:使用动态内存分配,0:不使用动态内存分配。

#define          USE_J1939_DTC            0//仅HD10使用,建议不修改

当时不使用动态内存分配时候,存在以下参数,可调节。

/*======================== buf size cOnfig================================*/ 

#define MAX_DTC_NUMBER                           35//最大DTC个数

#define MAX_DID_NUMBER                           70//最大DID个数

#define MAX_SNAPSHOT_NUMBER                10//最大快照信息个数

#define MAX_GROUP_NUMBER                      5//最大DTC组个数

/*======================== buf size cOnfig================================*/ 

 

2、接口函数

1)、诊断基本配置函数

void Diagnostic_Init(uint32_t requestId, uint32_t responseId, uint32_t funRequestId, uint16_t EEPromStartAddr, uint16_t EEpromSize,SendCANFun sendFun,uint16_t p2CanServerMax, uint16_t p2ECanServerMax);

requestId:诊断仪请求ID(物理寻址)

responseId:ECU响应ID(物理寻址)

funRequestId:功能寻址请求ID

EEPromStartAddr:诊断模块可使用的EEPROM起始

EEpromSize:诊断模块可使用的EEPROM的大小

sendFun:诊断模块发送CAN报文使用的函数指针

p2CanServerMax:诊断的响应时间参数限制(未发送78响应时,具体可参数项目诊断规范)

p2ECanServerMax:诊断的响应时间参数限制(发送了78响应后,具体可参数项目诊断规范)

2)、诊断额外支持的请求和响应ID(仅HD10使用)

void Diagnostic_Set2ndReqAndResID(uint32_t requestId1, uint32_t responseId1,uint32_t funRequestId1);

requestId1:诊断仪第二请求ID(物理寻址)

responseId1:ECU第二响应ID(物理寻址)

funRequestId1:第二功能寻址请求ID

3)、诊断模块释放接口

void Diagnostic_DelInit(void);

此接口会处理释放内存,保存故障码的操作,一定要在休眠之前调用。

4)、诊断模块报文接收函数

void Diagnostic_RxFrame(uint32_t ID,uint8_t* data,uint8_t IDE,uint8_t DLC,uint8_t RTR);

此函数需要在接收中断中调用,如果不调用,诊断模块将无法收到任何报文,无法提供任何服务。参数:

ID:报文ID,可以是11位和29位ID

Data:报文数据指针

IDE:参考S12G手册

DLC:报文长度

RTR:参考S12G手册

5)、诊断模块时间基数函数

void Diagnostic_1msTimer(void);

此函数需要在1毫秒的RTI中断中调用,如不调用,诊断模块所有与超时相关的功能将不能工作(包括多帧响应,S3超时等)。

6)、添加安全算法的函数

bool InitAddSecurityAlgorithm(SecurityLevel level, SecurityFun AlgoritthmFun,byte SeedSubFunctionNum,byte KeySubFunctionNum , uint8_t* FaultCounter,uint8_t FaultLimitCounter , uint32_t UnlockFailedDelayTimeMS,SubFunSuppInSession SubFuntioncSupportedInSession,uint8_t KeySize);

此函数的功能是为诊断模块的添加安全算法,最多支持三个等级的安全算法,如果不添加安全算法,27服务将没有正响应。参数:

Level:能使用LEVEL_ONE,LEVEL_TWO,LEVEL_THREE,不能使用LEVEL_ZERO和LEVEL_UNSUPPORT

AlgoritthmFun:安全解锁算法函数,参考三.1.12。

SeedSubFunctionNum:此算法支持的请求种子的子功能,如“27 01”中的“01”

KeySubFunctionNum :此算法支持的发送秘钥的子功能,如“27 02”中的“02”

FaultCounter:预留参数,设置为NULL

FaultLimitCounter:解锁失败次数限制,超时此次数时,启用延时

UnlockFailedDelayTimeMS:解锁失败后延时时间,单位为毫秒,如3000表示3秒

SubFuntioncSupportedInSession:子功能在会话模式的支持情况,可以是SUB_PROGRAM ,SUB_EXTENDED,也可以都支持,使用按位或的方式SUB_PROGRAM | SUB_EXTENDED。

KeySize:seed和可以的长度,可以设置为2或者4。设置为2时只使用高生成种子的高两个字节,解锁算法生成的秘钥也需要放到高两个字节。设置为4时将使用所有字节。

7)、初始化工厂模式安全算法函数

void InitFactorySecuriyAlgorithm(void);

无参数,此函数内部会调用InitAddSecurityAlgorithm函数,添加安全算法,算法包含于内部,如不进行此初始化,工厂模式将无法解锁。

8)、配置服务的函数

bool InitSetSessionSupportAndSecurityAccess(bool support ,uint8_t service,uint8_t PHYDefaultSession_Security,       uint8_t PHYProgramSeesion_Security,       uint8_t PHYExtendedSession_Security,      uint8_t FUNDefaultSession_Security,       uint8_t FUNProgramSeesion_Security,       uint8_t FUNExtendedSession_Security);

Support:只能为TRUE,如果为FALSE和未配置一样会有11否定响应。

Service:服务名称,如0x10,0x11,0x27等(一次只能使用一个)

PHYDefaultSession_Security:服务在物理寻址默认会话支持的安全访问等级。

PHYProgramSeesion_Security:服务在物理寻址编程会话支持的安全访问等级。

PHYExtendedSession_Security:服务在物理寻址扩展会话支持的安全访问等级。

FUNDefaultSession_Security,:服务在功能寻址默认会话支持的安全访问等级。

FUNProgramSeesion_Security:服务在功能寻址编程会话支持的安全访问等级。

FUNExtendedSession_Security:服务在功能寻址扩展会话支持的安全访问等级。

注意:以上6个参数,

如果支持,不需要安全解锁,则使用LEVEL_ZERO,

如果不支持,则使用LEVEL_UNSUPPORT,

如果需要安全解锁等级1才能支持,则使用 LEVEL_ONE,

如果需要安全解锁等级2才能支持,则使用LEVEL_TWO,

如果需要安全解锁等级3才能支持,则使用LEVEL_THREE,

如果同时支持多个安全等级,则只用按位或的方式,如LEVEL_TWO|LEVEL_THREE

9)、添加DID的接口函数

void InitAddDID(uint16_t DID , uint8_t DataLength , uint8_t* DataPointer , DIDType DidType , IoControl ControlFun , ReadWriteAttr RWAttr,uint16_t EEaddr, bool SupportWriteInFactoryMode);

DID:DID数字,如:0xF190

DataLength:DID的数据长度,如F190为17。

DataPointer:DID数据指针,此指针由应用程序提供,当类型为EEPROM_DID时,此参数设为NULL,类型为IO_DID并且不需要读时,也可设置为NULL。

DidType:DID的类型可以是EEPROM_DID,REALTIME_DID,IO_DID。

ControlFun:输入输出控制的函数指针,当类型不为IO_DID时,此参数设置为NULL。

RWAttr:读写属性

EEaddr:DID的eeprom地址只有DidType为EEPROM_DID时有效,当此参数为0时,诊断模块将自动分配eeprom地址,因此如果不需要手动指定地址,将此值设置为0即可。

SupportWriteInFactoryMode:是否支持在工厂模式可写。

注意:工厂模式的会话模式为0x71,需要先切换到10 03扩展会话,才能切换到工厂模式会话,工厂模式写DID数据需要先27解锁,分别是27  71请求种子,27  72发送秘钥。工厂模式解锁算法包含在诊断模块内部,对客户不可见。

10)、添加故障码的接口函数

#if USE_J1939_DTC

void Diagnostic_DM1MsgEnable(bool dm1en);

bool InitAddDTC(uint32_t DTCCode,DetectFun MonitorFun,byte DectecPeroid, byte ValidTimes,DTCLevel dtcLevel,uint32_t spn, uint8_t fmi);

#else

bool InitAddDTC(uint32_t DTCCode,DetectFun MonitorFun,byte DectecPeroid, byte ValidTimes,DTCLevel dtcLevel);

#endif

灰色部分仅在HD10中使用,可以不作关注

DTCCode:诊断故障代码,如0x910223,诊断模块只使用低24位,高8位设置为零。

MonitorFun:故障检测函数指针。

DectecPeroid:故障检测周期,此参数暂未使用,可以设置为0.

ValidTimes:故障有效次数,记录历史故障码的故障出现次数,当在历史故障和当前故障码同时置位时,设置为1,当历史故障码需要多个点火循环才能置位时,可设置为大于等于2的数。2表示需要两个点火周期,3表示3个,类推。

dtcLevel:故障等级,仅HD10使用,可以设置为LEVEL_C

11)、添加快照信息接口函数

void InitAddDTCSnapShot(uint8_t recordNumber , uint16_t ID , uint8_t* datap , uint8_t size);

recordNumber:快照信息记录号,如1,表示全局快照,2,表示局部快照。

ID:此快照的ID,如0x9102表示快照车速信息。

Datap:此快照记录的内存指针,需要是能表示实时状态(如实时车速)的内存指针。

Size:此快照的大小,字节数。

12)、设置故障扩展信息-老化计数器的扩展信息号的接口函数

void InitSetAgingCounterRecordNumber(uint8_t RecordNumer);

RecordNumer:老化计数器信息的序号(需要参考诊断规范中19 06的响应信息,一般范围1-4)

13)、设置故障扩展信息-已老去计数器的扩展信息号的接口函数

void InitSetAgedCounterRecordNumber(uint8_t RecordNumer);

RecordNumer:已老去计数器信息的序号(需要参考诊断规范中19 06的响应信息,一般范围1-4)

14)、设置故障扩展信息-故障发生次数计数器的扩展信息号的接口函数

void InitSetOccurrenceCounterRecordNumber(uint8_t RecordNumer);

RecordNumer:故障发生次数计数器信息的序号(需要参考诊断规范中19 06的响应信息,一般范围1-4)

15)、设置故障扩展信息-故障待定计数器的扩展信息号的接口函数

void InitSetPendingCounterRecordNumber(uint8_t RecordNumer);

RecordNumer:故障待定计数器信息的序号(需要参考诊断规范中19 06的响应信息,一般范围1-4)

16)、设置支持的故障位的接口函数

void InitSetDTCAvailiableMask(uint8_t AvailiableMask);

AvailiableMask:故障位,如0x09表示支持当前位和历史位

17)、设置DTCgroup的接口函数

void InitAddDTCGroup(uint32_t Group);

Group:14服务的group,目前支持支0xFFFFFF(仅低24位有效),清除所有故障码。

18)、配置11服务的接口函数

void InitSetSysResetParam(bool support01 , bool support02 , bool support03 , bool support04 ,

bool support05 , ResetCallBack callback, bool supressPosResponse);

support01:11服务是否支持01子功能,TRUE:支持,FALSE:不支持

support02:11服务是否支持02子功能,TRUE:支持,FALSE:不支持

support03:11服务是否支持03子功能,TRUE:支持,FALSE:不支持

support04:11服务是否支持04子功能,TRUE:支持,FALSE:不支持

support05:11服务是否支持05子功能,TRUE:支持,FALSE:不支持

Callback:复位接口函数指针,由应用提供,诊断模块只调用,具体的复位动作需要应用根据参数执行。

supressPosResponse:是否支持抑制响应,TRUE:支持,FALSE:不支持

19)、配置28服务的接口函数

void InitSetCommControlParam(bool supportSubFun00, bool supportSubFun01 , bool supportSubFun02 , bool supportSubFun03 , bool supportType01, bool supportType02, bool supportType03, CommCallBack callback, bool supressPosResponse);

supportSubFun00:是否支持00子功能-使能接收和发送,TRUE:支持,FALSE:不支持

supportSubFun01:是否支持01子功能-使能接收关闭发送,TRUE:支持,FALSE:不支持

supportSubFun02:是否支持02子功能-关闭接收使能发送,TRUE:支持,FALSE:不支持

supportSubFun03:是否支持03子功能-关闭接收和发送,TRUE:支持,FALSE:不支持

supportType01:是否支持控制参数01-一般通信报文,TRUE:支持,FALSE:不支持

supportType02:是否支持控制参数02-网络管理报文,TRUE:支持,FALSE:不支持

supportType03:是否支持控制参数03-通信报文和网络管理报文,TRUE:支持,FALSE:不支持

Callback:通信控制接口函数指针,由应用提供,诊断模式只负责调用,控制逻辑由应用实现。

supressPosResponse:是否支持抑制响应,TRUE:支持,FALSE:不支持

20)、配置10服务的接口函数

void InitSetSessionControlParam(bool supportSub01, bool supportSub02,bool supportSub03, bool sub02SupportedInDefaultSession, bool sub03SupportedInProgramSession, bool supressPosResponse);

supportSub01:是否支持01子功能-默认会话,TRUE:支持,FALSE:不支持

supportSub02:是否支持02子功能-编程会话,TRUE:支持,FALSE:不支持

supportSub03:是否支持03子功能-拓展会话,TRUE:支持,FALSE:不支持

sub02SupportedInDefaultSession:在默认会话是否支持02子功能,TRUE:支持,FALSE:不支持

sub03SupportedInProgramSession:在编程会话是否支持03子功能,TRUE:支持,FALSE:不支持

supressPosResponse:是否支持抑制响应,TRUE:支持,FALSE:不支持

21)、配置3E服务的接口函数

void InitSetTesterPresentSupress(bool supressPosResponse);

supressPosResponse:是否支持抑制响应,TRUE:支持,FALSE:不支持

22)、配置85服务的接口函数

void InitSetDTCControlSupress(bool supressPosResponse);

supressPosResponse:是否支持抑制响应,TRUE:支持,FALSE:不支持

23)、配置当前会话模式DID的接口函数

void InitSetCurrentSessionDID(uint16_t m_DID);

由于此数据在诊断模块,应用无法得到,所以使用此接口即可。此函数内部会添加DID。

24)、配置CAN数据库DID的接口函数

void InitSetCanDataBaseVersionDID(uint16_t m_DID);

由于此数据在诊断模块,应用无法得到,所以使用此接口即可。此函数内部会添加DID。

25)、配置CAN诊断版本DID的接口函数

void InitSetCanDiagnosticVersionDID(uint16_t m_DID);

由于此数据在诊断模块,应用无法得到,所以使用此接口即可。此函数内部会添加DID。

26)、配置网络管理版本DID的接口函数

void InitSetCanNMVersionDID(uint16_t m_DID);

由于此数据在诊断模块,应用无法得到,所以使用此接口即可。此函数内部会添加DID。

27)、配置CAN驱动版本DID的接口函数

void InitSetCanDriverVersionDID(uint16_t m_DID);

由于此数据在诊断模块,应用无法得到,所以使用此接口即可。此函数内部会添加DID。

28)、加载所有诊断模块数据的接口函数

void Diagnostic_LoadAllData(void);

需要先 配置好DID,安全算法,DTC后才能调用此接口函数,此接口函数回从EEPROM中读取所有需要的数据。

29)、配置车架号的接口函数

void Diagnostic_ConfigVIN(uint8_t length, uint8_t* data);

HD10使用此函数。

/************set netwrok layer parameters********/

30)、设置网络层参数的接口函数

void Diagnostic_SetNLParam(uint8_t TimeAs, uint8_t TimeBs, uint8_t TimeCr, uint8_t TimeAr, uint8_t TimeBr, uint8_t TimeCs, uint8_t BlockSize, uint8_t m_STmin, uint8_t FillData);

TimeAs:网络层定时参数AS

TimeBs:网络层定时参数BS

TimeCr:网络层定时参数CR

TimeAr:网络层定时参数AR

TimeBr:网络层定时参数BR

TimeCs:网络层定时参数CS

BlockSize:网络层参数BloskSieze(BS)

STmin:网络层定时参数STmin

FillData:未使用字节的填充数据

31)、诊断处理过程的接口函数

void Diagnostic_Proc(void);

此函数时最终实现诊断功能的函数,需要放到主循环不停的调用,如有需要,可以设置定时调用,最大定时为1MS。

3、诊断模块开发步骤

诊断模块的开发分为以下四个步骤

1)、在CAN接收中断中调用Diagnostic_RxFrame函数,保证将接收到的报文传到诊断模块。

2)、将RTI中断配置为1MS,并在RTI中断函数中调用Diagnostic_1msTimer。

3)、新建诊断模块初始化函数,在函数中配置所有的服务和参数

4)、在主循环中调用Diagnostic_Proc函数。

 

基于CAN总线的汽车诊断协议UDS(ECU底层模块移植开发)


推荐阅读
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • Metasploit攻击渗透实践
    本文介绍了Metasploit攻击渗透实践的内容和要求,包括主动攻击、针对浏览器和客户端的攻击,以及成功应用辅助模块的实践过程。其中涉及使用Hydra在不知道密码的情况下攻击metsploit2靶机获取密码,以及攻击浏览器中的tomcat服务的具体步骤。同时还讲解了爆破密码的方法和设置攻击目标主机的相关参数。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • Google Play推出全新的应用内评价API,帮助开发者获取更多优质用户反馈。用户每天在Google Play上发表数百万条评论,这有助于开发者了解用户喜好和改进需求。开发者可以选择在适当的时间请求用户撰写评论,以获得全面而有用的反馈。全新应用内评价功能让用户无需返回应用详情页面即可发表评论,提升用户体验。 ... [详细]
  • 本文介绍了通过ABAP开发往外网发邮件的需求,并提供了配置和代码整理的资料。其中包括了配置SAP邮件服务器的步骤和ABAP写发送邮件代码的过程。通过RZ10配置参数和icm/server_port_1的设定,可以实现向Sap User和外部邮件发送邮件的功能。希望对需要的开发人员有帮助。摘要长度:184字。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • 如何在服务器主机上实现文件共享的方法和工具
    本文介绍了在服务器主机上实现文件共享的方法和工具,包括Linux主机和Windows主机的文件传输方式,Web运维和FTP/SFTP客户端运维两种方式,以及使用WinSCP工具将文件上传至Linux云服务器的操作方法。此外,还介绍了在迁移过程中需要安装迁移Agent并输入目的端服务器所在华为云的AK/SK,以及主机迁移服务会收集的源端服务器信息。 ... [详细]
  • C++字符字符串处理及字符集编码方案
    本文介绍了C++中字符字符串处理的问题,并详细解释了字符集编码方案,包括UNICODE、Windows apps采用的UTF-16编码、ASCII、SBCS和DBCS编码方案。同时说明了ANSI C标准和Windows中的字符/字符串数据类型实现。文章还提到了在编译时需要定义UNICODE宏以支持unicode编码,否则将使用windows code page编译。最后,给出了相关的头文件和数据类型定义。 ... [详细]
  • Android开发实现的计时器功能示例
    本文分享了Android开发实现的计时器功能示例,包括效果图、布局和按钮的使用。通过使用Chronometer控件,可以实现计时器功能。该示例适用于Android平台,供开发者参考。 ... [详细]
  • 修复安装win10失败并提示“磁盘布局不受UEFI固件支持”的方法
    本文介绍了修复安装win10失败并提示“磁盘布局不受UEFI固件支持”的方法。首先解释了UEFI的概念和作用,然后提供了两种解决方法。第一种方法是在bios界面中将Boot Mode设置为Legacy Support,Boot Priority设置为Legacy First,并关闭UEFI。第二种方法是使用U盘启动盘进入PE系统,运行磁盘分区工具DiskGenius,将硬盘的分区表设置为gpt格式,并留出288MB的内存。最后,通过运行界面输入命令cmd来完成设置。 ... [详细]
  • Thisworkcameoutofthediscussioninhttps://github.com/typesafehub/config/issues/272 ... [详细]
  • 本文介绍了Java高并发程序设计中线程安全的概念与synchronized关键字的使用。通过一个计数器的例子,演示了多线程同时对变量进行累加操作时可能出现的问题。最终值会小于预期的原因是因为两个线程同时对变量进行写入时,其中一个线程的结果会覆盖另一个线程的结果。为了解决这个问题,可以使用synchronized关键字来保证线程安全。 ... [详细]
  • 有没有一种方法可以在不继承UIAlertController的子类或不涉及UIAlertActions的情况下 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
author-avatar
alive
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有