基于UDS的BootLoader上位机源代码(C#)
基于UDS的BootLoader上位机源代码,支持ISO15765通信,支持PeakCAN , ZJG CAN等CAN卡, 支持S-record格式的二进制文件解析; 可二次开发或扩展应用。

基于UDS烧录的上位机源代码使用说明
1. 总体说明
1.1. 设备(CAN卡)操作
(1) 软件集成了PCAN USB的设备操作,硬件设备的操作参考了设备的官方例程,本软件中仅使用了设备启动和关闭,消息接收和发送相关的接口,及例程中的先关参数定义。
(2) 软件集成了周立功CAN设备操作
1.2. 开发工具
本软件使用Visual Studio 2013集成IDE开发。
2. 软件模块
2.1 软件工程说明
打开软件工程,软件工程下的文件目录如下图所示。
点击文件后缀名为*.csproj的文件启动工程,软件工程的结构如下图所示。
2.2 窗体界面
软件共有三个窗体界面:Form2为登录窗体界面,Form1为软件主窗体界面,Form3为解锁设置界面。
(1)Form2界面描述
Form2界面如下图所示。软件启动时会首先展示该界面。再输入正确的账号和密码后,会离开该界面进入主界面。
(2)Form1界面描述
Form1界面如下图所示,该界面包含了整个软件的所有功能。
界面上的“设置CAN设备”部分为CAN卡设置,用户可以切换页选择不同的设备,配置不同的设备参数,最后点击“启动设备”即可启动正确连接的CAN卡,如果启动失败会弹出错误提示弹窗。由PCAN的驱动可以共享,启动PCAN后,打开PCAN View或PCAN Explorer等软件仍然可以对本上位机已经启动的设备进行连接,连接的设备名称为PCAN Ligth USB 16…。
“升级设置”部分为软件升级的参数设置,用户可以通过“浏览”选择需要烧录的文件,可以通过文本框设置软件升级的参数:起始地址(烧录的起始地址),数据长度(烧录的数据量大小),填充码(MCU的Flash默认值),UDS的物理寻址ID,UDS的功能寻址ID,UDS的响应ID,以及ID的格式(标准帧/扩展帧ID格式)等信息。其中的保存设置按钮的作用是在设置好上述参数后,点击“保存设置”会将设置的参数保存到软件运行目录下的配置文件中,在下次启动软件时,软件会将上次设置你的参数导入,避免每次软件升级时都需要设置一遍参数。点击“开始升级”按钮,软件将开启进行软件升级。
空白部分为调试信息显示文本框,软件升级过程中将实时显示软件升级进行的步骤及信息提示。
(3)Form3界面描述
Form3界面用于使用明文烧录时进行密码解锁,界面如下
在文本框中输入密码即可解锁。
2.3 软件框架说明
(1) 多线程处理。软件升级的过程耗时较长,为不造成UI卡顿和假死,软件采用多线程处理。软件主要线程有软件升级线程和消息接收线程。软件升级线程使用backgroundworker创建,消息接收线程由system.Thread创建。
(2) 线程同步。软件升级线程和消息接收线程由用户编写的方法(见源代码说明部分)进行同步和事件通知。
(3) 模块化。不同功能模块的方法和参数封装在不同的类中。
(4) 软件升级线程由“开始升级”的按钮点击事件启动,消息接收线程也由“开始升级”的按钮点击事件启动,软件升级结束时,将结束消息接收线程。
2.4 软件工程文件列表
序号 |
文件名称 |
描述 |
1 |
OpenDevice.cs |
该文件包含了CAN卡设备操作的方法和参数。 |
2 |
PCANBasic.cs |
该文件来自PCAN的官方例程,包含了PCAN设备的参数和API接口声明 |
3 |
LicenseModule.txt |
该文件为软件license的模板,用于读取license时进行关键字匹配 在license验证策略没有变更的情况下,请勿随意更改 |
4 |
UDS.cs |
该文件包含了CAN消息的发送接收,多帧处理,线程同步方法,UDS参数等。 该文件是真个软件中涉及UDS的核心文件。 该文件中的多包传输机制代码请勿随意更改。 |
5 |
Form1.cs |
软件主窗体设计器 |
6 |
Form2.cs |
软件登录窗体设计器 |
7 |
Form3.cs |
明文烧录时解锁设置的窗体设计器 |
8 |
INIOperation.cs |
I包含NI文件操作的接口 |
9 |
LicenseAnalysis.cs |
包含license文件的处理方法,该文件在license认证策略没有变更的情况下请勿随意更改。 |
10 |
Program.cs |
包含Main函数的工程默认文件 |
11 |
SecurityAccess.cs |
包含软件升级时的安全算法代码 |
12 |
SRecordProcess.cs |
包含s-record格式文件的处理方法源代码,和软件升级相关的一些全局参数。 |
3. 软件详细说明
3.1 OpenDevice.cs文件说明
该文件包含了设备(can卡)操作的接口,以及和设备相关的一些参数定义。部分定义参考了CAN卡的官方例程。
1、枚举定义:DeviceOperationType,定义了设备操作的类型。
CAN_DEVICE_OPERATION_NONE 无操作
CAN_DEVICE_OPERATION_OPEN 打开设备
CAN_DEVICE_OPERATION_CLOSE 关闭设备
2、枚举定义:DeviceType,定义了设备类型
CAN_DEVICE_NONE 无类型
CAN_DEVICE_PCAN PCAN系列设备
CAN_DEVICE_ZLGCAN 周立功系列设备
3、静态类; PCAN_Local_Para ,定义了PCAN设备相关的参数
public static TPCANHandle m_PcanHandle; 设备句柄
public static TPCANBaudrate m_Baudrte; 波特率
public static TPCANType m_HwType; PCAN的类型
4、静态类:ZLGCAN_Local_Para,定义了周立功设备相关的参数
public static UInt32 zlg_devType; 设备类型
public static UInt32 zlg_devIndex; 设备索引
public static UInt32 zlg_devCanIndex; CAN通道索引
public static ZLGCAN.VCI_INIT_CONFIG zlg_devConfig; 设备参数配置
5、公共类:OpenDevice, 定义了CAN设备操作的接口,包括设备启动,设备反初始化等
PcanDeviceOperation方法说明 |
||
方法名 |
PcanDeviceOperation 该方法用于启动PCAN或关闭PCAN设备。 |
|
参数 |
HwTypeStr |
表示设备类型的字符串 |
|
baudTypeIndex |
选择的波特率索引 |
OptTyte |
枚举类型:CAN卡操作的类型,打开还是关闭 |
|
其他 |
PCAN的设备参数需要参考官方文档的描述,计算过程可参考PCAN的官方例程。 根据设备操作的类型,调用了PCAN在动态链接库中提供的Initialize和Uninitialize接口。 |
PCAN_ReInitial方法说明 |
||
方法名 |
PCAN_ReInitial 该方法用于重新初始化已经打开的PCAN设备。 |
|
参数 |
|
|
|
|
|
|
|
|
其他 |
PCAN消息没有发送成功时可以进行重新启动,已清除未发送成功的消息和缓冲区。 调用了PCAN在动态链接库中提供的Initialize和Uninitialize接口。 |
ZLGCANDeviceOperation方法说明 |
||
方法名 |
ZLGCANDeviceOperation 该方法用于启动ZLGCAN或关闭ZLGCAN设备。 |
|
参数 |
seltDevType |
设备类型的选择索引 |
|
seltDevIndex |
设备索引的选择索引号 |
seltDevdevCanIndex |
CAN通道的选择索引号 |
|
seltDevCanBaudrate |
波特率的选择索引号 |
|
DevOperationType |
枚举类型:CAN卡操作的类型,打开还是关闭 |
|
其他 |
ZLGCAN的设备参数需要参考官方文档的描述,计算过程可参考ZLGCAN的官方例程。 设备的启动流程也需参考官方文档或例程的设计,调用了ZLGCAN在动态链接库中提供的VCI_OpenDevice、VCI_InitCAN、VCI_StartCAN、VCI_CloseDevice接口。 |
ZLGCAN_ReInitial方法说明 |
||
方法名 |
ZLGCAN_ReInitial 该方法用于复位已经启动的ZLGCAN设备 |
|
参数 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
其他 |
ZLGCAN的设备参数需要参考官方文档的描述,计算过程可参考ZLGCAN的官方例程。 调用了ZLGCAN在动态链接库中提供的VCI_ResetCAN和VCI_StartCAN接口。 |
3.2 PCANBasic.cs文件说明
该文件由PCAN的内容官方例程提供,包含了PCAN设备的参数和接口声明。本程序完全引用该文件,未做也无需做任何变更。
3.3 ZLGCAN.cs文件说明
该文件由ZLGCAN的内容官方例程提供,包含了ZLGCAN设备的参数和接口声明。本程序完全引用该文件,未做也无需做任何变更。
3.4 UDS.cs文件说明
该文件包含了UDs网络层的核心代码,包括网络层消息的接收和多包传输功能。
1、类SeedKey
包含了seed和key的定义,用于27服务时请求种子和保存key。
2、类SerialNumberFrame
包含了数据多包传输时消息帧的定义。
3、类Session
用于新建消息接收和发送类。
4、类DataToSend
用于保存发送诊断数据的属性。
5、类UDSReceiveFrame
用于保存接收的诊断数据的属性。
6、类UDSDataFrame
用于保存即将发送的UDS数据的属性,用在消息发送时。
7、静态类UDS_ID
包含UDS ID的定义和ID类型的定义。消息类型的定义都转换为了PCAN提供的ID类型枚举定义,在使用时需要注意。
8、静态类UserThreadProcess
该类用于线程同步处理,用于UDS消息的发送线程和接收线程。
相关变量 |
|
ThreadBreak |
Bool型变量,用于设置被阻塞(用延时模拟)的线程是否终止阻塞,true-终止阻塞 false-继续阻塞 |
DelayTime |
用于设置线程阻塞的时间,单位为毫秒 |
UserThreadWaitDelay方法说明 |
||
方法名 |
UserThreadWaitDelay 用于将阻塞的线程延长指定的阻塞时间。 |
|
参数 |
addTime |
时间,毫秒 |
|
|
|
|
|
|
其他 |
|
UserThreadWaitCancel方法说明 |
||
方法名 |
UserThreadWaitCancel 用于取消线程的阻塞状态 |
|
参数 |
|
|
|
|
|
|
|
|
其他 |
如果线程未被阻塞,而先调用了该方法,则设置线程进入阻塞时,线程将立即终止阻塞。 |
UserThreadWait方法说明 |
||
方法名 |
UserThreadWait 用于设置线程的阻塞状态和阻塞时间 |
|
参数 |
ms |
线程的阻塞时间,单位为毫秒 |
|
|
|
|
|
|
其他 |
如果线程未被阻塞,而先调用了该方法,则设置线程进入阻塞时,线程将立即终止阻塞。 |
9、类UDS
该类为UDS的核心代码,包含了UDS消息的接收和发送处理
相关变量 |
|
N_PDU_TYPE_SF |
单帧消息的标识 |
N_PDU_TYPE_FF |
首帧消息的标识 |
N_PDU_TYPE_CF |
连续帧消息的标识 |
N_PDU_TYPE_FC |
流控帧消息的标识 |
INTERVAL |
发送间隔 |
session |
当前消息发送和接收的状态类 |
OK |
相关标识 |
ERROR |
|
TIME_OUT |
|
seedKey |
Seed和key类的实例化,随UDS类实例化 |
maxNumberOfBlockLength |
多帧发送时的多包长度 |
|
|
sendOneFrame方法说明 |
||
方法名 |
sendOneFrame 消息发送接口,发送一帧消息 |
|
参数 |
frame |
UDSDataFrame类型的消息帧 |
|
|
|
|
|
|
其他 |
该方法为消息发送的接口,每调用一次发送一帧消息。 方法调用了PCAN和ZLGCAN设备的发送接口。消息发送时的处理按照PCAN和ZLGCAN提供的官方例程设计。 |
sendData方法说明 |
||
方法名 |
sendData UDS数据的发送接口,实现单帧和多帧消息的发送 |
|
参数 |
data |
数组,UDS消息的数据 |
|
canID |
发送的ID |
idType |
ID类型,需要转换成PCAN提供的枚举类型 |
|
其他 |
该方法为UDS消息的发送接口,包含了单帧消息和多帧消息的发送机制。 数据多包传输时网络层的打包工作在在该接口中完成。 在发送多包的连续帧时由于PCAN和ZLGCAN的发送机制不同,代码上的处理也不同: PCAN通过重复调用发送接口即可快速发送连续帧; ZLGCAN需使用其多帧发送机制,将多帧消息同时发送。 |
sendAndReceive方法说明 |
||
方法名 |
sendAndReceive UDS数据的发送接口,实现单帧和多帧消息的发送,以及UDS命令反馈判断 |
|
参数 |
data |
数组,UDS消息的数据 |
|
canID |
发送的ID |
idType |
ID类型,需要转换成PCAN提供的枚举类型 |
|
其他 |
该方法为UDS消息的发送接口,包含了单帧消息和多帧消息的发送机制。 数据多包传输时网络层的打包工作在在该接口中完成。 在发送多包的连续帧时由于PCAN和ZLGCAN的发送机制不同,代码上的处理也不同: PCAN通过重复调用发送接口即可快速发送连续帧; ZLGCAN需使用其多帧发送机制,将多帧消息同时发送。
|
hexToASCII方法说明 |
||
方法名 |
hexToASCII 将UDS反馈命令中的有效数据转换为ASCII码,返回ASCII的字符串 |
|
参数 |
index |
数组索引 |
|
data |
数组 |
|
|
|
其他 |
|
frmAmount方法说明 |
||
方法名 |
frmAmount 多包传输时计算消息的帧数 |
|
参数 |
|
|
|
data |
数组 |
|
|
|
其他 |
|
senndFirstFrame方法说明 |
||
方法名 |
senndFirstFrame 多包传输时发送首帧 |
|
参数 |
data |
UDS待发送的 |
|
frame |
首帧消息帧 |
|
|
|
其他 |
|
ReceiveDataProc方法说明 |
||
方法名 |
ReceiveDataProc CAN消息的接收 |
|
参数 |
|
|
|
|
|
|
|
|
其他 |
CAN消息的接收接口,包含了对UDS反馈消息处理。 该方法由Thread线程调用 |
startReceivedThread方法说明 |
||
方法名 |
startReceivedThread 启动CAN消息接收线程 |
|
参数 |
|
|
|
|
|
|
|
|
其他 |
该方法创建一个消息接收线程。在软件升级时创建,在升级结束时线程终止 |
uds_entry_reporgMode方法说明 |
||
方法名 |
uds_entry_reporgMode 发送1002命令 |
|
参数 |
id |
CAN命令的ID |
|
idType |
CAN ID的类型 |
|
|
|
其他 |
该方法创建一个消息接收线程。在软件升级时创建,在升级结束时线程终止 |
3.5 Form1.cs文件说明
该文件包含了Form1窗体中的控件事件和软件升级流程方法。
相关变量及方法 |
|
DeviceOperation |
OpenDevice类的实例 |
udsPro |
UDS类的实例 |
INI |
INIOperation类的实例 |
bw_SwUpdate |
BackgroundWorker类的实例 |
cl_red |
Color类型 |
cl_blue |
Color类型 |
MainWindow |
静态窗体,用于在静态方法中操作主船体 |
InvokeDelegate |
委托 |
radio_burnType_checked() |
烧录方式按钮的按下checked事件 |
InvokeMethod() |
主窗体中richtextbox文字设置方法,用于在委托中调用 |
dubugInfoDisplay() |
调试信息显示方法 |
UdsResponseData |
数组,用于保存接收到了UDS反馈命令,3个字节 |
UdsProgModeEntrySuccess |
标志位,用于1002命令的接收:Bit7-Bit4:接收到1002的响应;Bit3-Bit0:1-接收到积极响应 0-接收到消息响应 |
cmd_dect_1002 |
Bool型的标志,判断是否检测1002命令的反馈 |
UdsReceivedDataProcess() |
UDS消息接收处理,用于在接收线程中判断特定的响应命令。 |
CanDeviceCnntSuccess |
CAN设备的连接状态 |
MainForm() |
窗体加载方法,由工程自动创建,在该方法中绑定了bw_SwUpdate的相关事件 |
MainForm_Load() |
窗体的Load方法,由工程自动创建,包含了初始化窗体信息,和读取INI文件配置信息的方法 |
but_CnntDevice_Click() |
设备启动按钮的click方法,由工程自动创建,在该方法中调用了设备启动接口 |
but_LoadFile_Click() |
烧录文件导入按钮的click方法,由工程自动创建 |
but_SaveInfo_Click() |
保存按钮的click方法,由工程自动创建 |
INIReadAllPara() |
INI 配置文件读取的方法。 |
SwParaInit() |
软件参数初始化方法,主要用于软件升级时判断参数配置的情况 |
but_StartSwUpdate_Click() |
开始升级按钮的click方法,主要包含了初始化刷写参数,启动消息接收线程和启动UDS刷写线程 |
uds_sw_update_work() |
bw_SwUpdate的dowork方法,包含了软件升级的流程 |
uds_sw_update_changed() |
bw_SwUpdate的changed方法,主要用于刷写过程中进度条的显示 |
uds_sw_update_completed() |
bw_SwUpdate的completed方法,升级线程结束时调用,主要关闭消息接收线程 |
rhtxt_DebugInfo_KeyDown() |
Richtextbox的keydown事件, |
rhtxt_DebugInfo_TextChanged() |
Richtextbox的TextChanged事件,用于调试信息变化时始终显示最新的信息 |
MainForm_FormClosed() |
Form1的FormClosed |
chbx_idType_CheckedChanged() |
Id类型按钮的checkedchanged事件,用于显示不同格式的CAN消息ID |
radbut_burnType_MouseDown() |
密文烧录的MouseDown事件 |
SelectedDeviceType |
设备类型枚举 |
3.6 Form2.cs文件说明
该文件主要包含了登录窗体的功能
相关变量及方法 |
|
frm_Login() |
窗体初始化方法,由工程自动创建 |
but_login_Click() |
登录按钮事件 包含账户和密码识别及主窗体显示,由工程自动创建 |
linkLabel1_MouseClick() |
忘记密码链接的事件,由工程自动创建 |
frm_Login_Load |
窗体的Load事件,由工程自动创建 |
3.7 Form3.cs文件说明
该文件主要包含了切换明文/密文烧录时的解锁窗体的功能
相关变量及方法 |
|
Form3 () |
窗体初始化方法,由工程自动创建 |
but_unlock_Click |
解锁按钮事件,由工程自动创建,包含密码识别 |
Form3_Load |
窗体的Load事件,由工程自动创建 |
3.8 INIOperation.cs文件说明
该文件主要包含INI文件操作的接口。Ini文件操作的接口需要调用系统API。
Writue方法说明 |
||
方法名 |
Writue Ini文件写入方法 |
|
参数 |
section |
Ini文件的section |
|
key |
Ini文件的键 |
value |
Ini文件的值 |
|
其他 |
|
ReadValue方法说明 |
||
方法名 |
ReadValue Ini文件读取方法,返回读取的字符串 |
|
参数 |
section |
Ini文件的section |
|
key |
Ini文件的键 |
|
|
|
其他 |
|
3.9 LicenseAnalysis.cs文件说明
该文件主要包含license文件的处理方法
各变量及接口的解释清查看详细代码注释。
License文件由注册机生成,需要保证license文件的解析方法和生成方法匹配。
3.10 Program.cs文件说明
该文件包含了程序入口。
Main方法中包含了license处理接口的调用,若无需处理license可以将相关语句屏蔽。
见代码注释。
3.11 SecurityAccess.cs文件说明
该文件包含了27服务中安全算法的接口
AccessAlgorithm—安全算法接口
需要保证上位机的安全算法和BootLoader软甲的安全算法一致。
3.12 SRecordProcess.cs
该文件包含Mot16格式的文件的处理方法及相关参数定义。
相关变量 |
|
SourceFilePath |
烧录文件的路径 |
S19StartAddr_App |
应用程序的起始地址 |
S19DataLen_App |
应用程序的长度 |
S19DataRecord_App |
数组,有效的应用程序数据(以起始地址和长度开始的数据) |
SRecordDefaultCode |
芯片Flash的缺省码 |
SRecordAnalysis_app方法说明 |
||
方法名 |
SRecordAnalysis_app Mot16文件解析,提取有效的应用程序数据。同时根据烧录格式进行解密 |
|
参数 |
scrPath |
烧录文件路径 |
|
|
|
|
|
|
其他 |
|
StrToHexByte方法说明 |
||
方法名 |
StrToHexByte 将字符串转换为16进制数 返回16进制的数组 |
|
参数 |
hexString |
字符串 |
|
|
|
|
|
|
其他 |
|
SRecordBlockSizeCal方法说明 |
||
方法名 |
SRecordBlockSizeCal UDS数据下载时的块个数计算 |
|
参数 |
s19record |
应用程序的有效数据,也是UDS下载的有效数据 |
|
s19maxDwsize |
块大小,该参数由34服务的反馈决定 |
BlockSize |
数据下载时的块个数。 |
|
其他 |
|
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通