旧乡故客
发表于: 2018-6-28 18:04:14 | 显示全部楼层

了解如何使用标准USB接口将数据从PC发送到EFM8微控制器。


所需的硬件/软件

●    SLSTK2000A EFM8评估板

●    Simplicity Studio集成开发环境

●    SCILAB


项目概况

微控制器和个人电脑之间的直接可靠的通信连接可以为各种嵌入式应用程序增加强大的功能 - 您可以将传感器数据上传到PC进行分析,从图形用户界面发送命令,甚至可以集成启动加载功能这使得无需典型调试接口即可更新固件。不久之前,此功能的标准选择是计算机的“串行端口”,这是一个极为模糊的术语,指的是为RS-232信号特性设计的通用异步接收器/发送器(UART)。然而,现在,使用串口与微控制器进行通信可能相当于用一群牛耕田 - 牛是简单的野兽,他们完成了工作,但很少有人会选择他们在最新的GPS导向兆丰-拖拉机。


抛开偏好,仅仅因为串行端口不再是许多计算机上的标准功能(更不用说平板电脑和智能手机),RS-232变得越来越不实用。那么,选择就属于USB,在现代消费电子领域,这当然要优于RS-232。然而嵌入式开发人员并不总是需要USB的复杂功能,更重要的是,当您从串行端口移植到USB时,实现复杂性经历了巨大的飞跃。


幸运的是,对于普通的EFM8开发人员来说,嵌入式USB连接的路径已经被Silicon Laboratories的专家清除和平整。在这个项目中,我们将使用VCPXpress库,它极大地简化了在Windows和EFM8微控制器之间建立虚拟COM端口(VCP)连接的过程。 VCP功能非常适合需要直接通信链接的嵌入式项目,因为USB设备枚举为COM端口,因此可以使用标准串行端口软件例程传输和接收字节。


该项目的基本目标是成功建立个人电脑和EFM8微控制器之间的VCP通信。我们将使用Scilab脚本将ASCII数据发送到EFM8,然后EFM8将使用前一篇文章中讨论的技术在LCD上显示相应的字符。


端口I / O

端口I / O配置与我们在上一篇文章中使用的相同。

hw_cnfg1.jpg


SPI信号映射到适当的端口引脚,除了芯片选择信号,我们通过P0.1手动驱动。我们不需要直接配置USB数据线的端口引脚;所有的USB外设初始化都是通过VCPXpress库完成的。


外设和中断

外设和中断设置与我们以前使用的类似:SPI配置为与LCD模块通信,Timer4用于短延时。我们不在这个项目中使用Timer2,因为我们不需要帧速率。相反,只要微控制器收到USB数据包,LCD就会更新。


固件

为此项目开发的低级LCD接口也用于此项目。当EFM8从PC接收到数据包时,它将清除LCD并打印接收到的字符。在之前的项目中,由于内存限制,液晶显示器仅限于前60行;这次只使用了40行,因为VCPXpress库需要额外的RAM。


要在Simplicity Studio中创建VCPXpress应用程序,请首先像往常一样创建一个新项目,然后合并现有的任何源文件或代码块。这里有一个重要的提示:尽管你的直觉可能会说服你,但不要选中“USB Library”旁边的方框:

libno.jpg


选中此框将导致Simplicity Studio合并您不需要的库文件和配置代码,更糟糕的是,实际上可能与VCPXpress库冲突。


您需要将VCPXpress库添加到您的项目中。在Project Explorer窗格中右键单击项目名称,然后选择Properties。转到C / C ++常规>路径和符号。选择“库”选项卡并添加VCPXpress.lib:

library.jpg

然后转到“包含”选项卡并添加VCPXpress包含目录:

USB_step_2_cropped_2.jpg


还有一些需要包含在项目中的文件:VCPXpress.h和VCPXpress.lib是库文件,并且在初始化USB接口时涉及到descriptor.h和descriptor.c。你可以在压缩的项目文件中找到所有四个:


另外一个项目配置提示:当您构建VCPXpress项目时,您可能会(可能确定)会看到如下所示的链接器警告:

warning.jpg


这些警告并不一定意味着代码存在问题,您可以按如下方式将它们禁用:右键单击项目名称,然后选择“属性”。转到C / C ++ Build> Settings并选择“Tool Settings”选项卡。点击“Keil 8051 Linker”下的“Miscellaneous”并粘贴“OVERLAY(?PR?_USB_WRITEFIFO?EFM8_USBDEP!*,?PR?_USBD_READ?EFM8_USBD !,?PR?_USBD_WRITE?EFM8_USBD !,?PR?_VCPXCORE_WRITE?VCPXPRESS! *)“添加到”其他标志“文本框中:

flags.jpg


如果你点击“Keil 8051 Linker”,你应该看到这个:

linker.jpg


令人惊讶的是,实现基本的VCPXpress功能需要很少的代码。需要一个函数调用来初始化USB接口,一个调用USB中断处理程序:USB_Init(&InitStruct)和API_Callback_Enable(myAPICallback);这两个都可以在USBVCPCommunication_main.c中找到。处理收到的USB数据包的代码位于USBInterface.c中:

  1. VCPXpress_API_CALLBACK(myAPICallback)
  2. {
  3.    uint32_t API_InterruptCode;

  4.    //get the code that indicates the reason for the interrupt
  5.    API_InterruptCode = Get_Callback_Source();

  6.    //if the USB connection was just opened
  7.    if (API_InterruptCode & DEVICE_OPEN)
  8.    {
  9.            //start the first USB read procedure
  10.            Block_Read(USBRxPacket, USB_PACKET_SIZE, &USBBytesReceived);
  11.            /*we will process the received bytes when we get
  12.            a callback with an RX_COMPLETE interrupt code*/
  13.    }

  14.    if (API_InterruptCode & RX_COMPLETE)   // USB read complete
  15.    {
  16.            /*this flag tells the while loop in USBVCPCommunication_main.c
  17.              to process a received USB packet*/
  18.            USB_PACKET_RECEIVED = TRUE;

  19.            //continue with the next USB read procedure
  20.            Block_Read(USBRxPacket, USB_PACKET_SIZE, &USBBytesReceived);
  21.    }

  22. }
复制代码

如上面的代码所示,USB事件通过这个“回调”功能来处理。回调函数类似于中断服务例程(ISR)。发生中断事件时,硬件会使处理器在ISR中执行代码。回调本质上是一个更高级别的软件驱动的ISR:中断事件由库处理,如果事件需要应用程序固件注意,则库将处理器指向回调函数。


Block_Read()函数用于启动从PC接收数据的过程。当收到USB数据包时,固件将执行VCPXpress_API_CALLBACK(),并且中断代码将指示USB数据已准备好进行处理。


“EFM8UB1外设驱动程序库”提供了代码与VCPXpress库进行交互的功能和宏的文档。您可以通过单击Simplicity Studio中的“软件文档”访问此信息:

swdoc.jpg


USB设备需要USB主机

我们可以使用一个简单的终端程序来发送和接收VCP数据,但我们将使用Scilab--基准Scilab-to-EFM8接口将在未来的项目中派上用场。您需要下载Scilab串行端口库;下载的zip文件中包含安装和使用库的说明。以下代码用于将ASCII字符串发送到EFM8:

当您运行脚本时,Scilab控制台会被清除,并提示您输入“将此字符串发送到EFM8:”(请注意,此处提供的固件只支持26个大写字母和空格字符)。输入一些文字,然后按回车键发送。该脚本会重复提示输入新字符串,直到您按下返回键而不输入任何其他字符。

  1. COMPort_Number = 4;

  2. cd "C:\Program Files\scilab-5.5.2";

  3. exec("C:\Program Files\scilab-5.5.2\slLoadLib.sci");

  4. clc();

  5. EFM8Port = slMount();

  6. slConfig(EFM8Port, 115200, 8, 0, 1);

  7. return_val = slOpen(EFM8Port, COMPort_Number);

  8. if return_val == 0
  9.     printf("Unable to open COM port %d\n", COMPort_Number);
  10.     slUMount(EFM8Port);
  11.     slUnload();

  12. else
  13.     while 1
  14.         CharsToSend = input("Send this string to the EFM8:", "string");
  15.    
  16.         if(CharsToSend == " ")
  17.             break;
  18.         end

  19.         slSendArray(EFM8Port, ascii(CharsToSend), length(CharsToSend));
  20.     end

  21.     slClose(EFM8Port);
  22.     slUMount(EFM8Port);
  23.     slUnload();
  24. end
复制代码

测试系统

以下是测试通信链接的过程:

●    构建“USBVCPCommunication”项目并将代码加载到EFM8中。

●    断开插入标有“DBG”的连接器的迷你USB电缆,然后将电源开关移至“USB”。

●    将电脑的USB电缆连接到微型USB连接器(靠近操纵杆)。

●    查看Windows设备管理器以确定您的VCP连接的COM端口号,并相应地修改Scilab脚本。

devman.jpg

●    运行Scilab脚本并输入一些要发送的字符。按下Enter后,字符应显示在LCD上。


跳转到指定楼层
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题 29 | 回复: 32



手机版|

GMT+8, 2024-4-19 13:15 , Processed in 0.160625 second(s), 8 queries , Gzip On, MemCache On. Powered by Discuz! X3.5

YiBoard一板网 © 2015-2022 地址:河北省石家庄市长安区高营大街 ( 冀ICP备18020117号 )

快速回复 返回顶部 返回列表