丰田普锐斯(Restayl)媒体系统



这是该系列文章中的第一篇(介绍性)文章,介绍了我将如何完善汽车的媒体系统。 该项目本身正在进行中,没有时间像其他所有人一样,因此,亲爱的读者,请耐心等待,因为我经常不承诺铆钉文章。

一切始于我拥有普锐斯。

首先引起我注意的是更新导航的问题。 以下内容非常微不足道,但在某些地方,称为“多功能显示器”的设备(在普通人中为头部)的必要功能。 这是在众多配备Android且配备许多便利设施的中国收音机的背景下进行的。 但是,将它们安装在常规位置意味着缺少像能源分布和气候控制图这样的“障碍”。

这个想法的产生是因为它以某种方式比中国兄弟们建议的更紧密地将Android收音机与汽车连接起来。 关于这篇文章。

初始情况


这样啊 板上约有一个带电阻触摸屏的7英寸显示屏,并通过TX +和TX-线连接到其他电子设备。 从头开始已经有3对这样的电路,在电路中,这个奇迹叫做AVC-LAN,看起来像这样:



第1部分:环顾内部


如您所见,前端位于网络的间隙中,位于路由器与无线电,放大器的另一条链之间(我单独拥有),并且与导航单元的连接遵循单独的通道。 在其他地方,一个停车单元正在悬挂,在我的计划中没有任何提及。 好吧,好吧……我决定将与它的距离推迟到更好的时候。 而且,停车实际上不是真正的需求,而是游戏功能。

除去所有不必要的内容后,我们大致得到了以下设备框图:



感言


有一种想法是简单地用Android代替导航单元,但是当我更深入地了解它们与头部的通信方式时,这种想法消失了。 除了AVC-LAN外,这些模块还通过GVIF(千兆位视频接口)线连接,如果我还以100美元以上的价格在GVIF中购买视频信号转换器,则转换器制造商的相同面孔可能会不小心破裂。这可能很困难,但是..“-一首著名歌曲的动机在我脑海中响起,我不喜欢这个决定。

在网络上有解决方案,安装了中文收音机而不是收音机。 这不适合我,因为这两个显示器是不合理的冗余。 恕我直言

解决方案


诞生了以下解决方案:更换整个头部,完成android收音机,与Prius交朋友,为此:

  1. 设计USB <-> AVC-LAN硬件转换器
  2. 为此开发固件,使其像USB-HID一样连接。
  3. 使其复合,以便像正常的硬件键盘一样检测其中一个功能(以便通过面板上的按钮将其用作本机控件)
  4. 开发功能类似于(或优于)本地Priusovsky的Android应用程序
  5. 对准后置摄像头
  6. 解决机械零件中的问题(安装在常规位置)

在此过程中,有必要为android开发另一个应用程序-普通嗅探器,以便更方便地在AVC-LAN上反向传输数据包。 同时练习。

它看起来应该像这样:



作为硬件基础,决定在SM32F103上使用培训板:



与AliExpress一起订购,价格为$ 2.05。

或搜索-扰流板
也许很多东西已经被卖家删除了,所以我给出了神奇的字符串来搜索阿里:
STM32F103C8T6 ARM STM32最小系统开发板模块

我喜欢她的什么:

  • 处理器板上的USB硬件模块(设备)
  • 制造商有足够的USB堆栈(与Freescale-ovsky不同,晚上不记得了)。
  • 免费的GPIO端口,可用于连接显示器侧面的常规按钮。 也许这会将收音机的硬件按钮隐藏在面板下方。 我不知道她会是什么
  • 并且可以在其上将AVC-LAN转换器挂接到逻辑级别

我将按照实现的顺序进行进一步描述,这首先要归功于我的个人知识。 即 我试图认识到它们从一开始就没有的地方,而到​​了最后,肯定会发生什么。

无论如何,在不同的中心计划了几篇文章。 从硬件连接到android应用程序,该项目实际上是FullStack。

第2部分:USB,HID,描述符和所有组件,以获取试验原型


第一步,我想获得一堆设备和电话,以便设备可以将数据包传输到电话,然后在应用程序中显示该数据包。
正如加加林所说:走吧!

STM32上的USB HID复合设备


我决定要做的是根据我的任务改写ST示例,并获得主机可识别为键盘和“其他”组件的USB设备-RAW HID设备。 正如我已经说过的,第一个用于本机Android控制,第二个用于与设备上的程序直接交换AVC-LAN数据包。

基于STM的CubeMX,在阅读了很多有关如何实现自定义HID的文章之后,我在网络上发现了一件不愉快的事情:创建复合设备的问题实际上不存在或非常稀少。

源代码将在以后
由于该项目目前正在实验培训模式下实施,因此我尚未上传源代码。 如果项目成功完成,请确保将其拖动到Github并编辑带有链接的文章。
以它们的形式,上传没有意义-没有我,互联网上有很多混乱。

USB,复合,HID


关于这个问题只说几句话。 假定您或多或少熟悉USB标准。 如果不是这样,最好先熟悉一下并尝试使用CubeMX的示例。

因此,我们有:

STM USB堆栈和鼠标实现示例。 在那里,我们配置了一些描述符和一个功能端点。 这是用于控制整个设备的一对0x00和0x80的补充。

要实现我的项目,我需要键盘端点是双向的(我不知道为什么-它很有用),还有两个端点将用于与第二个RAW函数交换数据。 添加它们。

我们通过将OUT点添加到描述符中来使该点成为双向的:

配置描述符。
编辑描述符时,请注意索引和大小。
(2c5cf968121f0d8fa43a6755c09e15ef3a317791):

0x07, /*bLength: Endpoint Descriptor size*/ USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/ HID_EPOUT_ADDR, /*bEndpointAddress: Endpoint Address (IN)*/ 0x03, /*bmAttributes: Interrupt endpoint*/ HID_EPOUT_SIZE, /*wMaxPacketSize: 4 Byte max */ 0x00, HID_FS_BINTERVAL, 


并增加一些要点:

配置描述符
(bc2bd583c98715e106fcb3ab07b266bc9221be36):

  /* 59 */ 0x07, /*bLength: Endpoint Descriptor size*/ USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/ HID_EPIN_ADDR2, /*bEndpointAddress: Endpoint Address (IN)*/ 0x03, /*bmAttributes: Interrupt endpoint*/ HID_EPIN_SIZE, /*wMaxPacketSize: 4 Byte max */ 0x00, HID_FS_BINTERVAL, /*bInterval: Polling Interval (10 ms)*/ /* 66 */ 0x07, /*bLength: Endpoint Descriptor size*/ USB_DESC_TYPE_ENDPOINT, /*bDescriptorType:*/ HID_EPOUT_ADDR2, /*bEndpointAddress: Endpoint Address (IN)*/ 0x03, /*bmAttributes: Interrupt endpoint*/ HID_EPOUT_SIZE, /*wMaxPacketSize: 4 Byte max */ 0x00, HID_FS_BINTERVAL, /*bInterval: Polling Interval (10 ms)*/ 


这是一个配置描述符。 现在,主机将确保我们拥有某种复合HID设备,并且您可以将数据发送到所有这些点。 但是事实并非如此。
要做到这一点:

1.我们的控制器有一块专门分配的内存,与CAN和USB模块一起计时。 鉴于USB模块独立于接收/发送数据包的过程,您需要在此存储器中为每个端点设置缓冲区:

usbd_conf.c文件中的USBD_LL_Init
  HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x00 , PCD_SNG_BUF, 0x18); HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x80 , PCD_SNG_BUF, 0x58); HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , HID_EPOUT_ADDR , PCD_SNG_BUF, 0x100); HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , HID_EPIN_ADDR , PCD_SNG_BUF, 0x140); HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , HID_EPOUT_ADDR2 , PCD_SNG_BUF, 0x180); HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , HID_EPIN_ADDR2 , PCD_SNG_BUF, 0x1B0); 


缓冲区地址是任意的,只要它们不重叠即可。

由于某种原因,在编写ST堆栈时,设备的双向端点不会超过一个,因此我们将对堆栈进行一些修改:

调动


将USBD_HID_SendReport过程重命名为USBD_HID_SendReportEP,再添加一个参数-端点号。 为了向后兼容,我们将过程保留为旧名称,但是在主体中,我们使用终结点形式的常量调用USBD_HID_SendReportEP。 解决方案仍不是最美观的解决方案,但可以为实验解决,即使保留下来,也不会干扰特定项目。

usbd_hid.c
 uint8_t USBD_HID_SendReportEP (USBD_HandleTypeDef *pdev, uint8_t ep, uint8_t *report, uint16_t len) { ... ,   USBD_HID_SendReport } uint8_t USBD_HID_SendReport (USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len) { return USBD_HID_SendReportEP(pdev,HID_EPIN_ADDR,report,len); } 


现在一切就绪,可以发送数据了,仅在正确的时间调用此函数。

定案


为了方便起见,我们搜索项目并再次调用USBD_LL_CloseEP,但要查找新创建的端点。

接待处


为了使端点在道德上能够正常工作,您需要为其调用USBD_LL_PrepareReceive。 我建议读者遍历该行的项目搜索,并根据您的需求调整这些调用。

我的代码中有这只丑陋的乌贼:

usbd_core.c
 USBD_LL_PrepareReceive(pdev, HID_EPOUT_ADDR+(epnum&0x7F)-1 , hhid->Report_buf, USBD_HID_OUTREPORT_BUF_SIZE); 


即 我从端点数目连续的事实出发。 不好,恕我直言。 不要这样做。 但是,也不喜欢ST。

剩下的一切只是转到usbd_hid.c文件,尤其是转到USBD_HID_DataOut函数,并确保对接收到的数据处理程序的调用与您对美观的个人想法相符。 我也没有成功,因此代码和说明将很冗长且令人费解。 自己动手做。

检举


一切,在这个地方,我们得到了一个复合设备,该设备能够通过两个双向点交换数据。 在最后一步,我们“关闭”了HID驱动程序的好奇心,描述了这样的报告描述符:

 __ALIGN_BEGIN static uint8_t HID_ReportDesc2[33] __ALIGN_END = { 0x06, 0x00, 0xff, // USAGE_PAGE (Vendor Defined Page 1) 0x09, 0x01, // USAGE (Vendor Usage 1) 0xa1, 0x01, // COLLECTION (Application) 0x85, 0x01, // REPORT_ID (1) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255) 0x75, 0x08, // REPORT_SIZE (8) 0x95, 0x1f, // REPORT_COUNT (31) 0x09, 0x00, // USAGE (Undefined) 0x81, 0x00, // INPUT (Data,Ary,Abs) 0x85, 0x02, // REPORT_ID (2) 0x09, 0x01, // USAGE (Vendor Usage 1) 0x75, 0x08, // REPORT_SIZE (8) 0x95, 0x1f, // REPORT_COUNT (31) 0x91, 0x00, // OUTPUT (Data,Ary,Abs) 0xc0 // END_COLLECTION }; 

该报告告诉HID驱动程序:将有大约31个字节的数据。 无需弄清楚它们是什么-只需将它们提供给打开此设备的程序即可。 在物理报告中,零字节将等于报告索引(REPORT_ID(2))。 因此,总共将有32个字节。

然后在usbd-hid.c函数USBD_HID_Setup中输入有关它的数据:

usbd-hid.c
  switch (req->bRequest) { case USB_REQ_GET_DESCRIPTOR: if( req->wValue >> 8 == HID_REPORT_DESC) { // TODO: !!!   ,     req->wIndex !!! THIDDescPtrLen * rep = (req->wIndex==1)?&HID_ReportDesc:&HID_ReportDesc2; len = MIN(rep->len , req->wLength); pbuf = rep->ptr; } 

在程序中进一步:


  1. 组装AVC-LAN逻辑电平转换器,并连接到板。 分析AVC-LAN的物理层,真实波形。
  2. 在控制器级别处理接口并发送带有报告的数据包
  3. 端到端接口和反向工程Prius。 嗅探器包(或我的第一个Android应用)

聚苯乙烯


  • 我决定写一篇文章是因为(几乎)我被逼了,说服了应该分享。 即使我没有完成该项目,某些最新信息也可以以某种“原始”方式帮助某人。
  • 欢迎对该项目提出批评,因为 我本人还没有完全想象它会成功。
  • 对文章,设计,演示文稿的批评-特别是因为 这是该资源的第一篇文章。 随着工作的继续,我想以通常和易于理解的形式向读者表达我的想法

Source: https://habr.com/ru/post/zh-CN411617/


All Articles