【EASY EAI Nano-TB(RV1126B)开发板试用】介绍、系统安装 本文介绍了灵眸科技 EASY EAI Nano-TB(RV1126B) 开发板的相关信息,包括包装、外观、产品特性等,并介绍了系统镜像安装部署的相关流程。 介绍 EASY-EAI-Nano-TB是灵眸科技研发的一款应用于AIoT领域的AIOT主板。 核心板基于瑞芯微的RV1126B处理器设计,集成了4个Cortex-A53及独立的NEON协处理器,支持4K@30fps的 H.264/H.265解码器,还支持4K@30fps的H.264/H.265编码器。 引入了新一代完全基于硬件的最大 12M 像素 ISP(图像信号处理器),实现了多种算法加速器,如HDR、3A、LSC、3DNR、2DNR、锐化、去雾、鱼眼校正、伽马校正、特征点检测等。 同时还引入了最大800万像素的AI-ISP作为传统ISP的补充,提供卓越的空间降噪性能和强大的图像增强效果。 内嵌的NPU算力高达3Tops,支持INT4/INT8/INT16/FP16混合运算。 提供完整的Linux开发包供客户二次开发。 包装 套件 外观 Top view Bottom view 动态演示见顶部视频。 产品特性 名称 EASY EAI Nano-TB 处理器 RV1126B 内核 4×ARM Cortex-A53@1.6GHz NPU 支持INT4/INT8/INT16/FP16混合运算,算力高达3TOP VPU 4K@30fps H.264/H.265 Decoder 4K@30fps H.264/H.265 Encoder ISP 12M ISP+8M AI-ISP 操作系统 Debian12/Ubuntu22.04 内存 1/2GB DDR4 电子硬盘 64GB EMMC MIPI DSI 1路4-Lane MIPI DSI,1.5Gbps/lane MIPI CSI 2路,每一路支持4 lanes,2.5Gbps/Lane TF卡 1路TF卡接口 USB 3.0 Host 2路USB3.0 TYPE-A接口 USB 2.0 Host 1路USB2.0 TYPE-A接口 Type-C 1路固件下载接口 以太网 2路千兆以太网 WiFi 1路WiFi6 蓝牙 1路蓝牙5.2 星闪 1路星闪通信SLE1.0 麦克风 1路麦克风输入 喇叭 1路3W/4Ω喇叭 UART 2路,3.3V CAN 1路,3.3V I2C 1路 PWM 2路 SPI 2路 SAI 1路 GPIO 3路 调试串口 1路 指示灯 1个电源指示灯 按键 1个复位键,1个LOAD按键,1个PWRON开关机按键 看门狗 支持外部硬件看门狗 供电电压 直流12V电压输入 机械尺寸 120mm(长) *90mm(宽) 环境测试 -20℃ ~ +85℃ 主控 处理器为瑞芯微 RV1126B 该处理器集成了4个Cortex-A53及独立的NEON协处理器, 支持4K@30fps的 H.264/H.265解码器, 支持4K@30fps的H.264/H.265编码器。 内置3D GPU,完全兼容OpenGL ES1.1/2.0/3.2、OpenCL 2.2和Vulkan 1.2 内嵌 NPU 支持 INT4/INT8/INT16/FP16 混合运算,算力高达3Tops,可转换基于TensorFlow/MXNet/PyTorch/Caffe 等一系列框架的网络模型。 详见:EASY EAI灵眸科技 . 系统安装 下载镜像 链接:https://pan.baidu.com/s/1Ch36_5gO2_QUgAcgVAZSlQ?pwd=1234 解压文件 双击运行烧录软件 ...\\\\tools\\\\windows\\\\RKDevTool\\\\RKDevTool_Release\\\\RKDevTool.exe ; Loader模式 确认设备在通电状态下:先按住【LOAD按键】不松手,保持这个状态; 再单击【RESET按键】,等待3~4秒,松开【LOAD按键】。板卡即可进入LOADER模式。 烧录软件显示目标设备 镜像烧录 点击【执行】按钮,烧录成功效果如下 动态演示详见底部视频。 总结 本文介绍了灵眸科技 EASY EAI Nano-TB(RV1126B) 开发板的相关信息,包括包装、外观、产品特性等,并介绍了系统镜像安装部署的相关流程,为相关产品的快速开发和应用设计提供了参考。
2025-12-23 18:05
鹰速光电的Cameralink采集卡,转USB采集设备,便携式应用。其对应的电脑采集软件功能较为齐全。如下。 采集软件功能强大 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
2025-12-23 17:26
分享一个最新的便携微孔雾化装置的原理图,主要功能为驱动微孔雾化,兼具外围的升压和检水。 特点:整体硬件成本低,具备自动扫频追频以及自动检水功能,按键和指示灯设计方便简洁 主要逻辑功能需求 雾化片:108KHz,16mm直径,微孔超声波雾化片 雾化驱动:自动扫频追频,雾化量另行标定,名义雾化速率:4mg/s 按键1: 长按开机,再次长按关机;关机状态下进入低功耗以节省电池电量;按键1在开机状态下循环,高-中-低档位控制雾化速率 档位关机记忆 按键2: 在开机状态按下出雾,释放后立即停止出雾 在开机状态下3分钟内,按键1和按键2无动作的话,自动关机 LED1, LED2, LED3 灯:指示档位状态,开机状态下,低档:亮一个,中档:亮2个,高档:亮三个;关机时所有LED灯灭 LED4:雾化状态,出雾亮,无雾灭,开机状态下无水时闪烁,关机状态灭 LED5:低电量状态显示,闪烁:电量低,关机或者电压正常时熄灭。电池电压低时长按按键1,LED5闪烁, 并且无法开机 使用单节锂电池供电 上述原理图中的主要器件清单 升压芯片:LN2220PAR (南麟) 充电管理:TP4057(友台) 主控及雾化驱动芯片:LX8201 (乐而信) 电容/水位监测:TC301D (诺泰)
2025-12-23 17:09
使用adv7180已经解码出视频了,但整体图像没有色彩显示,更改色彩相关寄存器依旧没有反应,前端分压电路采用官方手册配置,使用36欧加39欧加电容,是否还有别的因素导致图像没有色彩
2025-12-23 16:51
2025-12-23 15:58
1.什么是芯片电阻器 芯片电阻器是电子电路中用于控制电流的基础电子零部件。它被设计为表面贴装型(SMD),可直接焊接在印刷电路板(PCB)上,从而实现紧凑的电路设计。它被广泛应用于智能手机、家电、工业设备等空间有限的电子设备中。 芯片电阻器的主要作用包括限流、分压、信号整形等,与电路的稳定性与安全性密切相关。要正确理解其性能,准确读取“阻值”至关重要。若使用错误的阻值,则会导致电路误动作或故障。 本文将用通俗易懂且适合初学者的方式,为大家解说如何从印标在芯片电阻器上的数字和符号中正确读取阻值的方法。 2.数字与符号的含义 芯片电阻器的表面通常印有3位或4位数字,这些数字表示其阻值。与引线电阻器的色码不同,芯片电阻器采用数字标记,以实现小型化。 例如,3位数字“104”表示“10 × 10⁴”,阻值为10,0000Ω(100kΩ)。其规则是:前两位表示有效数字,最后一位表示乘数(10的几次方)。 阻值的单位是Ω(欧姆),kΩ(千欧)和MΩ(兆欧)也经常使用。3. 特殊印标:零欧姆与小数点表示法 部分芯片电阻器使用与常规不同的特殊印标。 零欧姆电阻器 印标:“000”“0”等 含义:阻值 ≒ 0Ω(用作跳线) 小数点表示法(R符号) “R”被用作小数点的替代符号。 这些标记在低阻值或精密用途中尤为常见。为防止误读,需要通过各厂家的数据表等进行确认。 4.常用印标模式与读法 芯片电阻器上有一些实际常见的印标及其对应的阻值。 例如,“472”表示“47 × 10²”,阻值为4.7kΩ。“6800”表示“680 × 10⁰”,阻值为680Ω。这些模式是基于E系列(后述)的标准阻值,在电路设计中频繁使用。 若记住读法规则,如印标“000”表示零欧姆电阻器,“104”表示100kΩ,“222”表示2.2kΩ,则会使贴装零部件的确认和故障排查更加顺畅。 由于小型零部件视觉辨认性较差,误读阻值还可能导致设计失误。掌握准确的读法对于实现高可靠性的电路设计至关重要。5. E系列与阻值的关系 电阻器的阻值是基于将名为E系列的电阻器标准阻值系统化分类的标准(IEC 60063)而设计的。 E系列包括“E6”“E12”“E24”“E48”“E96”“E192”等,各自的精度和使用目的不同。例如,E6的精度为±20%,被分成不同的数量级,共有6种阻值。E12的精度为±10%,E24的精度提高至±5%,可选阻值也更丰富。E96和E192用于精度在±1%以下的高精度电阻器,适用于测量仪器和高可靠性电路。 E系列在抑制电阻值偏差和实现设计标准化方面发挥着重要作用。 理解E系列后,可以根据所需精度选择合适的阻值。结合印标的读法,掌握E系列的知识,是迈向高手境界的第一步。 6.总结 正确读取芯片电阻器的阻值,是电子电路设计最基础的要求。加深对印标规则和E系列的理解,不仅可以提高零部件选择的精度,还有助于防止故障。
2025-12-23 14:36
现在有一组通讯协议,但是我对校验方法不熟悉导致通讯异常,想问问大神指点一下校验方法-如图所示我想给ID1的发送连接指令正确数据应该是怎样的
2025-12-23 14:29
本人目前工作于一家汽车零部件公司,武汉博格华纳科技有限公司,在里面担任高级嵌入式软件工程师。主要研究车规级MCU芯片模组和智能汽车ADAS系统开发,主导过多款不同MCU厂家的CAN/CANFD/LIN通信项目,比如恩智浦NXP的S32K144,英飞凌的Aurix TC275这些外资车规级MCU芯片,特别想试试意法半导体的STM32F7系列的高端芯片,准备在阿波罗STM32F767开发板上实现基于CAN/CANFD的UDS完整诊断协议栈。刚好近期在某宝上购买了正点原子的阿波罗STM32F767开发板,板载的CAN收发器是TJA1050,刚好可以用来做UDS on CAN开发,因此本期帖子就是把我工作中自己实现量产测试过的成熟UDS协议栈实现到阿波罗STM32F767上,看看使用效果!!!!! 做过整车或者汽车零部件开发的研发人员,应该都知道UDS诊断协议,这个协议非常的重要,特别是在现在的新能源电车和传统的油车上,都会百分百涉及到UDS诊断协议,为什么呢? 因为汽车上的部件,比如BMS锂电池系统,发动机,底盘控制器,皮带传动系统,车灯,ABS,雨刮器等等,这些部件量产装车后,就不可能随意的拆解了,只有出现重大故障进行维修时,去4S店和自己车的品牌维修店,修车工人才会使用仪器进行拆解维修!!! 这里就不能像我们平时给STM32开发板用串口来连接调试了,汽车上的部件装车后,是没有串口给你调试的,因为汽车上第一是为了防止黑客篡改代码或者协议,不可能给你留串口接口的,这是不符合功能安全和信息安全的。 汽车上有一套经过亿万次测试认证的诊断调试协议,叫做UDS诊断协议,也就是ISO14229协议,当汽车部件需要调试时,诊断工程师会使用CAN分析仪或者诊断设备来抓取CAN报文进行分析,通过安全访问服务解锁成功后,读取DTC故障代码,才能知道汽车哪个零件出故障了,进行定点修复。 我看了网上,目前还没有一个人做过UDS诊断相关的帖子,第一,很多人从事相关的开发,涉及到利益链,就不会去公开分享讲解UDS的实现。第二,很多人没有接触过汽车行业,不懂这个UDS协议。第三,很多开发汽车零部件的工程师根本不会自己去实现UDS诊断协议,因为他们用的是Vector的达芬奇工具配置好的UDS协议栈,这个协议非常的复杂,很多冗余代码,不可能自己进行私下移植,因为它做了加密处理。而且它们是与芯片进行绑定的,比如NXP,英飞凌,瑞萨等等,不可能移植到STM32上。基于以上种种问题,我个人就来做全网第一个原创从0到1手搓14229 UDS诊断协议栈的人,希望给广大网友进行技术共享,破解整车厂的那层诊断面纱。—————— UDS协议是一套基于主从服务的诊断协议,主要分为以下25中服务: 上图就涵盖了UDS的所有服务,实现UDS就是把上面的单个服务进行完整实现就可以了。 实际使用时,我们可以用UDS进行OTA 升级,刷写汽车零部件固件。也可以进行故障代码DTC存储,为维修定位故障调试做好准备!!!!! 因为UDS服务众多,一篇帖子是不可能讲解完毕的,所以本节帖子,就开始进行10 和 11 服务进行讲解。后面继续完成其它服务讲解!!! 好了,开始讲解10服务 1。10 Diagnostic Session Control 又叫 诊断会话控制 它分为3个会话 <a.默认会话 默认会话模式使能 ECU 的默认诊断会话,该会话模式不需要任何诊断应用程序的超时处理(例如:无需诊断设备在线服务保持此会话模式激活)。 如果任何其它非默认模式的会话模式被激活,而默认模式再一次被启动,则须遵守以下执行规则: 1.1 当 ECU 发送诊断会话控制肯定响应报文后,ECU 终止当前诊断会话模式并启动新请求的诊断会话模式; 1.2 如果 ECU 发送诊断会话控制肯定响应报文,且诊断工具在诊断会话中解锁了ECU,则 ECU 须重新锁定; 1.3 如果 ECU 发送诊断会话控制肯定响应报文并跳转到默认会话模式,它将复位所有在此前会话模式下激活的状态和控制服务。例如:通信控制(28h)、控制 DTC设置(85h)、输入输出控制(2Fh); 1.4 如果 ECU 发送该服务否定响应报文,此激活的会话模式保持不变。注意,如果要求初始化,完成初始化的 ECU 启动默认会话模式。初始化步骤后,无需诊断会话模式控制服务将诊断会话设为默认会话。 <b. 编程会话 编程会话允许支持 ECU 内存编程的所有需要的诊断服务。 如果 ECU 在引导程序中运行编程会话,ECU 只能通过诊断工具发起的“ECU 复位”(11h)服务,会话类型为默认会话的“诊断会话控制”(10h)服务或 ECU 会话层超时退出此会话。 ECU 在引导程序中运行时,ECU 接收到“会话类型”为默认会话的“诊断会话控制”(10h)服务或 ECU 会话层超时发生,并且两种情况下存在有效的应用程序时,ECU 须重启应用程序。 <c. 扩展诊断会话 扩展诊断会话模式可用来支持对 ECU 控制变量进行调整(如怠速,CO 值等)所需的所有诊断服务,也可用来使能一些服务,并不限于特定用于功能调整的诊断服务。 诊断工具使用此服务切换一个或多个 ECU 的诊断会话模式。一种诊断会话使能 ECU中一系列特定的诊断服务。 1.5 诊断会话控制 DiagnosticSessionControl(10h)报文格式如下: 这3中会话在UDS服务中有一套运行状态机: 当诊断工具通过10服务使 ECU 进入不同的诊断会话模式。要执行一个诊断服务,必须在适合的会话模式下。 同一时刻只能有一个诊断会话模式被激活。 上电后如果没有诊断会话请求,ECU 需自动进入常规/默认会话模式(01h)。 如果 ECU 需要满足一定的条件才能启动一个新的诊断会话,供应商需提供相应说明。 下图描述了模式切换的过程,默认会话模式可以直接切换到扩展会话模式,但是不能直接切换到编程会话模式,如果想进入编程会话模式,则必须先进入扩展会话模式。同样,编程会话模式不能直接进入扩展会话模式,只能进入默认会话模式。ECU 复位以及 S3 定时器超时将导致 ECU 进入默认会话模式。 核心代码如下: #include \"uds_user.h\" #include \"SID10_DiagnosticSessionControlCfg.h\" /****************************************************************************** Variables* ******************************************************************************/ Struct_Uds_SID_DSC_Info Uds_SID_DSC_Info; /****************************************************************************** Function definitions* ***** *************************************************************************/ /************************************************************************* / /* Function:void ChangeSession_Init(void) Description: Parameters: void Return: void */ void ChangeSession_Init(void) { Uds_SID_ER_Info.HardResetFlag = false; Uds_SID_SA_Info.Security_Locked = true; Uds_SID_SA_Info.RequestSeedFlag = false; } /*************************************************************************/ /* Function:void SID_DSC_Analysis(uint8 *pInd, uint16 indLen) Description: Parameters: pInd indLen Return: void */ void SID_DSC_Analysis(uint8_t *pInd, uint16_t indLen) { uint8_t loop; uint8_t subID; subID = pInd[0U] & 0x7FU; for (loop = 0U; loop < UDS_SID_DSC_SUBFUNC_NUMBER; loop++) { if ((subID & 0x7FU) == Uds_SID_DSC[loop].SubID) { break; } } if (loop < UDS_SID_DSC_SUBFUNC_NUMBER) { Uds_Dcm_Info.Cur_Task = UDS_TASK_SID_DSC; } else { Uds_Response.ResCode = UDS_RES_CODE_SFNS; } } /*************************************************************************/ /* Function:boolean SID_DSC_Appl_Deal (uint8 *pInd, uint8 *pRes, uint32 *pResLen) Description: Parameters: pInd SubID pRes pResLen Return: boolean Return Values:E_OK E_NOT_OK */ boolean SID_DSC_Appl_Deal(uint8_t *pInd, uint8_t *pRes, uint32_t *pResLen) { uint8_t loop; uint8_t subID; boolean ret; if ((pInd[0U] & 0x80U) != 0U) { Uds_Response.SuppressPosRspBit = true; } subID = pInd[0U] & 0x7FU; for (loop = 0U; loop < UDS_SID_DSC_SUBFUNC_NUMBER; loop++) { if (subID == Uds_SID_DSC[loop].SubID) { break; } } if (loop < UDS_SID_DSC_SUBFUNC_NUMBER) { ret = Uds_SID_DSC[loop].pFunc(&pRes[1U], &pResLen[0U]); if (Uds_Response.ResCode == UDS_RES_CODE_PR) { pRes[0U] = subID; pResLen[0U] += 1U; } } else { Uds_Response.ResCode = UDS_RES_CODE_SFNS; ret = E_OK; } return ret; } #include \"SID10_DiagnosticSessionControlCfg.h\" #include \"SID11_ECUReset.h\" #include \"Dcm_DrvCfg.h\" /****************************************************************************** Constants* ******************************************************************************/ boolean SID_DSC_SUBID_DS_Callback(uint8_t *pRes, uint32_t *pResLen); boolean SID_DSC_SUBID_PRGS_Callback(uint8_t *pRes, uint32_t *pResLen); boolean SID_DSC_SUBID_EXTDS_Callback(uint8_t*pRes, uint32_t *pResLen); /** **************************************************************************** Type definitions* ******************************************************************************/ /****************************************************************************** Variables* ******************************************************************************/ const Struct_Uds_SID_DSC Uds_SID_DSC[UDS_SID_DSC_SUBFUNC_NUMBER] = { {0x01U, SID_DSC_SUBID_DS_Callback}, {0x81U, SID_DSC_SUBID_DS_Callback}, {0x02U, SID_DSC_SUBID_PRGS_Callback}, {0x03U, SID_DSC_SUBID_EXTDS_Callback}, {0x83U, SID_DSC_SUBID_EXTDS_Callback}, }; /****************************************************************************** Function definitions* ***** *************************************************************************/ /************************************************************************* / /* Function:void SID_DSC_SUBID_DS_Callback (uint8 *pRes, uint32_t *pResLen) Description: Parameters: pRes pResLen Return: boolean Return Values:E_OK E_NOT_OK */ boolean SID_DSC_SUBID_DS_Callback(uint8_t *pRes, uint32_t *pResLen) { boolean ret; if (Uds_SID_DSC_Info.Active_Session == UDS_PROGRAMMING_SESSION_ACTIVE) { Uds_SID_DSC_Info.Active_Session = UDS_DEFAULT_SESSION_ACTIVE; pResLen[0U] = 4U; pRes[0U] = (uint8_t)(UDS_P2_SERVER_MAX / 0x100U); pRes[1U] = (uint8_t)(UDS_P2_SERVER_MAX); pRes[2U] = (uint8_t)(UDS_P2EX_SERVER_MAX / 0x100U); pRes[3U] = (uint8_t)(UDS_P2EX_SERVER_MAX); Uds_Response.ResCode = UDS_RES_CODE_PR; } else { ChangeSession_Init(); Uds_SID_DSC_Info.Active_Session = UDS_DEFAULT_SESSION_ACTIVE; pResLen[0U] = 4U; pRes[0U] = (uint8_t)(UDS_P2_SERVER_MAX / 0x100U); pRes[1U] = (uint8_t)(UDS_P2_SERVER_MAX); pRes[2U] = (uint8_t)(UDS_P2EX_SERVER_MAX / 0x100U); pRes[3U] = (uint8_t)(UDS_P2EX_SERVER_MAX); Uds_Response.ResCode = UDS_RES_CODE_PR; } ret = E_OK; return ret; } /*************************************************************************/ /* Function:void SID_DSC_SUBID_PRGS_Callback (uint8_t *pRes, uint32_t *pResLen) Description: Parameters: pRes pResLen Return: boolean Return Values:E_OK E_NOT_OK */ boolean SID_DSC_SUBID_PRGS_Callback(uint8_t *pRes, uint32_t *pResLen) { boolean ret; / 编程会话02,功能地址下不响应,不执行 / if ((Uds_Indication.TA_Type[0U] & 0x55) != 0U)//0x55 { if (Uds_SID_DSC_Info.Active_Session == UDS_DEFAULT_SESSION_ACTIVE) { Uds_Response.ResCode = UDS_RES_CODE_SFNSIAS; } else { ChangeSession_Init(); Uds_SID_DSC_Info.Active_Session = UDS_PROGRAMMING_SESSION_ACTIVE; pResLen[0U] = 4U; pRes[0U] = (uint8_t)(UDS_P2_SERVER_MAX / 0x100U); pRes[1U] = (uint8_t)(UDS_P2_SERVER_MAX); pRes[2U] = (uint8_t)(UDS_P2EX_SERVER_MAX / 0x100U); pRes[3U] = (uint8_t)(UDS_P2EX_SERVER_MAX); Uds_Response.ResCode = UDS_RES_CODE_PR; } } else { NOP(); } ret = E_OK; return ret; } /*************************************************************************/ /* Function:void SID_DSC_SUBID_EXTDS_Callback (uint8_t *pRes, uint32_t *pResLen) Description: Parameters: pRes pResLen Return: boolean Return Values:E_OK E_NOT_OK */ boolean SID_DSC_SUBID_EXTDS_Callback(uint8_t *pRes, uint32_t *pResLen) { boolean ret; if (Uds_SID_DSC_Info.Active_Session == UDS_PROGRAMMING_SESSION_ACTIVE) { Uds_Response.ResCode = UDS_RES_CODE_SFNSIAS; } else { ChangeSession_Init(); Uds_SID_DSC_Info.Active_Session = UDS_EXTENDED_SESSION_ACTIVE; pResLen[0U] = 4U; pRes[0U] = (uint8_t)(UDS_P2_SERVER_MAX / 0x100U); pRes[1U] = (uint8_t)(UDS_P2_SERVER_MAX); pRes[2U] = (uint8_t)(UDS_P2EX_SERVER_MAX / 0x100U); pRes[3U] = (uint8_t)(UDS_P2EX_SERVER_MAX); Uds_Response.ResCode = UDS_RES_CODE_PR; } ret = E_OK; return ret; } 这个函数指针数组就实现了3个子服务的功能。我们依次进行讲解 01 默认会话 boolean SID_DSC_SUBID_DS_Callback(uint8_t *pRes, uint32_t *pResLen) { boolean ret; if (Uds_SID_DSC_Info.Active_Session == UDS_PROGRAMMING_SESSION_ACTIVE) { Uds_SID_DSC_Info.Active_Session = UDS_DEFAULT_SESSION_ACTIVE; pResLen[0U] = 4U; pRes[0U] = (uint8_t)(UDS_P2_SERVER_MAX / 0x100U); pRes[1U] = (uint8_t)(UDS_P2_SERVER_MAX); pRes[2U] = (uint8_t)(UDS_P2EX_SERVER_MAX / 0x100U); pRes[3U] = (uint8_t)(UDS_P2EX_SERVER_MAX); Uds_Response.ResCode = UDS_RES_CODE_PR; } else { ChangeSession_Init(); Uds_SID_DSC_Info.Active_Session = UDS_DEFAULT_SESSION_ACTIVE; pResLen[0U] = 4U; pRes[0U] = (uint8_t)(UDS_P2_SERVER_MAX / 0x100U); pRes[1U] = (uint8_t)(UDS_P2_SERVER_MAX); pRes[2U] = (uint8_t)(UDS_P2EX_SERVER_MAX / 0x100U); pRes[3U] = (uint8_t)(UDS_P2EX_SERVER_MAX); Uds_Response.ResCode = UDS_RES_CODE_PR; } ret = E_OK; return ret; } 02 编程会话 boolean SID_DSC_SUBID_PRGS_Callback(uint8_t *pRes, uint32_t *pResLen) { boolean ret; / 编程会话02,功能地址下不响应,不执行 / if ((Uds_Indication.TA_Type[0U] & 0x55) != 0U)//0x55 { if (Uds_SID_DSC_Info.Active_Session == UDS_DEFAULT_SESSION_ACTIVE) { Uds_Response.ResCode = UDS_RES_CODE_SFNSIAS; } else { ChangeSession_Init(); Uds_SID_DSC_Info.Active_Session = UDS_PROGRAMMING_SESSION_ACTIVE; pResLen[0U] = 4U; pRes[0U] = (uint8_t)(UDS_P2_SERVER_MAX / 0x100U); pRes[1U] = (uint8_t)(UDS_P2_SERVER_MAX); pRes[2U] = (uint8_t)(UDS_P2EX_SERVER_MAX / 0x100U); pRes[3U] = (uint8_t)(UDS_P2EX_SERVER_MAX); Uds_Response.ResCode = UDS_RES_CODE_PR; } } else { NOP(); } ret = E_OK; return ret; } 03 扩展会话 boolean SID_DSC_SUBID_EXTDS_Callback(uint8_t *pRes, uint32_t *pResLen) { boolean ret; if (Uds_SID_DSC_Info.Active_Session == UDS_PROGRAMMING_SESSION_ACTIVE) { Uds_Response.ResCode = UDS_RES_CODE_SFNSIAS; } else { ChangeSession_Init(); Uds_SID_DSC_Info.Active_Session = UDS_EXTENDED_SESSION_ACTIVE; pResLen[0U] = 4U; pRes[0U] = (uint8_t)(UDS_P2_SERVER_MAX / 0x100U); pRes[1U] = (uint8_t)(UDS_P2_SERVER_MAX); pRes[2U] = (uint8_t)(UDS_P2EX_SERVER_MAX / 0x100U); pRes[3U] = (uint8_t)(UDS_P2EX_SERVER_MAX); Uds_Response.ResCode = UDS_RES_CODE_PR; } ret = E_OK; return ret; } 编译烧录代码后,打开串口,连接PCAN进行调试,读取报文 这里我使用串口,是应为STM32上有串口,不是汽车实物。 其实只需要CAN调试器PCAN即可!!! 打开ECUbus上位机,这个和PCAN绑定的上位机。 也可以使用周立功的USBCAN 连接好,下面设置发送接收CAN ID 对应我代码里的 #define UDS_CAN_PHY_ADDR 0x111U #define UDS_CAN_FUNC_ADDR 0x7DFU #define UDS_CAN_TX_ADDR 0x222U 中间那个是功能码ID,这里用不到,我们只需物理地址CAN ID 注意,上位机的TX 111对应我们STM32的接收RX,同理,上位机的接收RX 222对应STM32的TX。构成主从网络,上位机为主,STM32为从 添加服务 发送01 默认会话服务 可以看到串口收发的CAN报文数据和PCAN 解析的一致,完美验证了10 01服务 发送02 编程会话服务 选中这个02 发送 可以看到串口收发的CAN报文数据和PCAN 解析的一致,完美验证了10 02服务 发送03 扩展会话服务 发送数据 可以看到串口收发的CAN报文数据和PCAN 解析的一致,完美验证了10 03服务 至此,UDS会话控制服务测试完毕。。 2。电控单元复位EcuReset(11h)也叫复位服务 ECU 复位服务用于要求 ECU 根据复位类型参数值来有效执行复位操作。 11服务的数据格式如下: 主要分为3个子服务 11 01硬件复位 11 02钥匙开关复位 11 03钥匙开关复位 它们的核心代码如下: boolean SID_ER_SUBID_HR_Callback(uint8_t *pRes, uint32_t *pResLen) { boolean ret; /*Reset type 看门狗复位方式*/ //NVIC_SystemReset(); Uds_SID_ER_Info.HardResetFlag = true; Uds_Response.ResCode = UDS_RES_CODE_PR; ret = E_OK; return ret; } boolean SID_ER_SUBID_KeyR_Callback(uint8_t *pRes, uint32_t *pResLen) { boolean ret; /*Reset type 芯片复位管脚*/ //NVIC_SystemReset(); Uds_SID_ER_Info.HardResetFlag = true; Uds_Response.ResCode = UDS_RES_CODE_PR; ret = E_OK; return ret; } boolean SID_ER_SUBID_SR_Callback(uint8_t *pRes, uint32_t *pResLen) { boolean ret; / Reset type / Uds_SID_ER_Info.HardResetFlag = true; //NVIC_SystemReset(); Uds_Response.ResCode = UDS_RES_CODE_PR; ret = E_OK; return ret; } 下面来进行测试: 1。测试01硬件复位 选中 发送报文 可以看到复位后,会打印阿波罗STM32F767 UDS 开机重启复位 这是因为 明白了吧。测试正确 02。钥匙开关复位测试 选中 测试正常 03。软件复位 选中 发送数据 可以看到正确服务 至此,完成了11 重启服务的所有功能测试 详情看视频
2025-12-23 14:20
如题,很老的板子了,但是还是想求一套资料
2025-12-23 13:38
高速先生成员-- 黄刚 高速先生成员-- 黄刚随着产品速率越来越高,人们对传输线阻抗偏差的接受度也肯定越来越小了,大家都怀揣着加工出来的板子传输线阻抗能做到10%、8%甚至5%误差的梦想。有梦想绝对是好事,高速先生支持每一个有梦想的人。但是光有梦想肯定控不好阻抗,高速先生一定会把你们摇醒,让你们好好思考下到底有什么因素会影响加工的阻抗误差哈! 影响阻抗的因素有很多,高速先生之前文章也写过不少,今儿再给大家分享一些影响指数也贼高的因素,那就是流胶。。。 什么是流胶?的确又要花点篇幅从PCB加工工艺说起了。首先PCB叠层的组成大家应该知道哈。无论是多少层PCB板(当然2层除外哈),它的组成部分都会由以下三个元素组成,那就是PP,CORE和铜箔。 铜箔大家好理解,那就是铜嘛。PP和CORE大家都也不用觉得他们差异很大,先说下PP哈。我们叫习惯了PP,其实它的学名叫半固化片Prepreg,它的组成元素就2个,玻璃纤维布和树脂,就像下面的切片图所示。 真实长啥样?就是下面那样了。其中玻璃纤维布,简称玻纤布,树脂,俗称胶水,它就是我们今天的要说的流胶的那个胶了哈! 那什么叫CORE呢?也没什么复杂,那就是把PP上下各加上一张铜箔,预先压合一次,本质上就是一个双面板,所以CORE的学名也叫芯板,就是下面那样了。 CORE和PP的差异点主要是2个,一是CORE多了上下两面的铜箔,二是CORE是预先压合好的PP,把CORE和PP在多层板中叠好再次高温压合的时候,CORE是不会再变化的了。那怎么能把多张CORE和PP压合成一个稳定的多层板呢?就主要靠CORE上下的PP里面的胶了。压合时的高温会把PP里的胶变成近似液体状,然后填充多层板里面的空隙,最后像胶水一样把多个CORE粘起来。 那流胶就是把多个CORE粘起来嘛,为什么会影响传输线的加工偏差呢?最近刚好有一个客户的阻抗测试结果,我们一起拿出来看看大家就知道了。 高速先生的一贯风格,先说结论,那就是测试发现50欧姆传输线的阻抗加工后偏低了,只做到了47欧姆左右。因为这个是客户的一块要求非常高的测试板,因此47欧姆就不很好了。 那要分析原因,首先就看看叠层?这个信号线走L2层,参考L1和L3层,L2和L3就是一个CORE了,L1层就是单独的铜箔,L1和L2之间是PP。 根据工厂确认的叠层厚度和线宽,我们算了下阻抗,算出来是很好的,妥妥的50欧姆! 那肯定是加工时哪个因素变掉了导致阻抗偏低呗。客户很纠结,一定要找到原因,那没办法了,板子数据测试后,我们只能拿去切片看看了。不看不知道,一看吓0.5跳。 能看到线宽和设计的4mil基本上出入不大,下面L2和L3层的CORE也很稳定,在4mil左右。最大的问题是L1和L2层的PP厚度咋就和确认的叠层差那么远呢?叠层上明明写的厚度是3.81mil,切片看到的只有2.9mil,少了1mil那么多?!和板厂确认了PP的型号是对的,用的PP本身的厚度就是3.8mil左右没毛病。3.8mil的PP压合完只有2.9mil了? 的确,最大的问题就是在这里,如果L1和L2层的PP厚度从3.8mil变成2.9mil后,加工出来的阻抗就真的变成了47欧姆左右了,也。。。没毛病!!! 对啥啊对,47欧姆阻抗我会算啊,关键是为什么PP压合后直接少了将近1mil啊,我想知道的是这个问题啊!!由于这个项目是客户自己画的测试板,那我们就提出要不看看客户的设计图。打开设计图看到之后,客户率先发表意见:你们看,在L2层为了排除其他走线的干扰,我就只走了7、8根待测的信号线,其他都是空的啊,应该不存在走线之间的干扰导致阻抗变化啊!的确啊,这一层也就那么几根信号线,都离得远远的,肯定不会有什么干扰啊! 终于到高速先生发话了:这就对了嘛! 简单的几个字就定位了阻抗偏低的最大问题。。。
2025-12-23 10:14