Micro Framework USB Driver开发

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

               

Micro Framework开发USB驱动也有一段时间了,随着开发的深入,对USB理解也渐渐清晰起来。

从系统架构上来说为Micro Framework开发USB驱动有三个层面的工作。一是针对USB芯片的驱动移植(很多ARM CPU都集成了USB功能),实现MFHAL层要求的USB接口;二是开发PC平台上针对MF设备的USB驱动;三是编写应用程序(非Micro Framework应用程序),通过USB接口直接和MF设备通信(这个工作是我加的,其实完成前两步工作,就已经使MFDeployVS2008和设备正常通信了)。

下面我针对这三个层面,详细说一下我的开发工作。

一、USB驱动移植

这一步是最难的,特别是对USB没有任何了解的人来说。Micro FarmeworkUSB开发接口如下(含HAL层和PAL层的接口,其中PAL层的代码已经提供,不需要任何编程)。

1CPU_USB_GetInterruptState Function

Determines whether there are currently interrupts pending for the USB port.

2CPU_USB_Initialize Function

Initializes the client module at the driver layer.

3CPU_USB_ProtectPins Function

Puts USB pins into a known state to prevent spurious inputs.

4CPU_USB_RxEnable Function

Enables a specified USB port to receive data.

5CPU_USB_StartOutput Function

Begins sending output to a specified USB port.

6CPU_USB_Uninitialize Function

Uninitializes (shuts down) USB communications at the driver layer.

7USB_ClearEvent Function

Clears one or more USB events.

8USB_Flush Function

Flushes the buffers associated with USB ports.

9USB_GetEvent Function

Gets the state of a USB event.

10USB_Initialize Function

Initializes the USB subsystem.

11USB_Read Function

Reads a block of data from a USB port.

12USB_SetEvent Function

Sets the state of a USB event.

13USB_Uninitialize Function

Initializes the USB subsystem.

14USB_Write Function

Writes a block of data to a USB port.

其实接口什么样都无所谓,关键是首先你要让USB设备能work,让PC机能识别你的设备,USB开发的里程碑有三个,一是让PC机发现未知设备,二是让PC机识别USB设备,三是正确安装USB驱动(当然要能正常工作)。

1、第一步让USB识别你的设备,这一步可以说是最难,也可以说是最容易的一步,说它最难是因为这一步和硬件的正常工作非常相关,如果硬件工作不正常或USB接口有物理故障,这一步都很难通过,所以在开发USB驱动之前,一定确保硬件设备的USB能正常工作(比如在linuxWince环境下能正常工作)。说它容易是因为仅需要正确配置一两个寄存器,不需要什么编程就能实现这一步。这个过程不需要了解太多的USB相关知识,只需要精读该芯片的英文技术文档即可。

2、第二步让PC机识别你的USB设备,这一步是最关键的一步,也是需要大量USB知识的一步。这一步仅需要实现USB的端点0(称控制端点或默认端点)相关的功能即可。

如果没有USB基础的人,这一步必须要充电,必须要知道USB相关协议规范,否则你就会寸步难行。我这里推荐一下两个人的blog,一个是大名鼎鼎的USB研究专家圈圈,写的关于USB的文章都非常透彻,相关链接(http://group.ednchina.com/93/240.aspx );另一个是蔡军生的关于USB的文章,写的也非常好,对开发很有帮助(http://blog.csdn.net/caimouse/archive/2007/03/24/1539835.aspx )。其次我推荐,如果大家有条件就要购买一本周立功编著的《USB 2.0OTG规范及开发指南》,这可以说是一本USB2.0英文协议文档的翻译版,不过翻译的还不错(网上也流传了不少USB2.0中文协议文档,不过有些差强人意),可以相对比较准确地理解USB术语。对我来说,还是比较习惯读书的,在电脑上看大篇大篇的技术文档很容易看了后面忘了前面的。

这一步其实就是PC机对USB设备的盘查工作,有点类似公安局审犯人,如你是谁?什么背景?有什么能力等等。其中最关键的要问到USB设备的PIDVID,问到这一个才能安装相对应的驱动程序,当然获得相关的接口和端点配置也是非常重要的。详细的信息交互,这一步我就不多说了,协议上都说的非常清楚。这一步要说一点,就是设置地址这个环节最容易出错,PC机分配的地址收到后,一定要等返回相关ACK响应后,再修改设备的USB设备地址,否则很容易出问题。

这里推荐一下北航frank的文章《USB项目技术报告》,这个环节写的很清楚。

此外如果你手边有USB协议分析仪,那么你真是一个非常幸福的人,这一步就需要这个东东(我不太幸运,我是在调通USB驱动之后,才有的USB协议分析仪),Bus Hound工具虽然好用,但是在这一步却帮不上忙,它是要识别USB设备后才能正常监控USB数据流的,这对第三步的工作非常有帮助。

 

 

USB分析仪

 

USB通信过程一目了然,你会发现USB协议分析仪原来这么强大)。

 

Bus Hound

 

注:Micro FrameworkPAL层已实现相关通信交互的指令,你仅需要把USB通道打通即可,此外不要拘泥于MF porting kit中的USB驱动示例,要根据需要大胆一些调整相关逻辑。具体的要求请参见我以前的文章《MF PortingUSB驱动开发》http://blog.csdn.net/yefanqiu/archive/2009/01/04/3697445.aspx

 

第三步,安装驱动,如果第二步正确完成,PC机就会要求你安装USB驱动了。

 

      USB 驱动

二、PC USB驱动开发

Micro FrameworkPorting kit开发包中已经提供了MF 设备的USB驱动源码(MFUSB_PortingKitSample),你仅需要修改一下Inf文件(主要修改相关的PIDVID,记住PIDVID仅是设备和相关驱动关联用的,除此之外没有其它任何用处),此外需要安装Windows DDK开发包,用来编译该驱动程序。相关说明如下:

To compile the USB drivers you must

1) install the DDK

2) open a command window for building (build environment must be initialized for that cmd window by calling setenv.cmd on the appropriate client directory)

3) build with the script build_usb_drivers in %SPOCLIENT%/Tools/scripts directory

   usage: build_usb_drivers.cmd DDK_INSTALLDIR

   example: build_usb_drivers.cmd c:/WINDDK/6001.18001

Output directories are under the drivers' source tree. Please move the sys files in the corresponding sub-directories in the inf folder before installing.

NOTE: the build_usb_drivers script will only build the MFUSB_PortingKitSample driver.  The MFUSB_DualInterface_PortingKitSample driver is the same

as the previous one but can handle 4 endpoints instead of two and allows debugging over USB the first pair of endpoints while reading/writing

on the other pair.

    由于MF设备仅支持3个端点(012),所以要扩展功能或增加端点,就需要你修改此程序的相关源码了(当然MF设备的USB驱动你也要相应地修改)。

 

三、USB应用程序开发

很多网上的此类程序大部分都是基于VC的,几乎找不到C#相关的源代码,即使有也发现文不对题,根本实现不了和设备的直接通信,网上有一个ICSharpCode.USBlib的库可以在C#中引用,据说功能还很强大,不过我在VistaXP上好像没有测试成功,枚举USB设备时老出现异常。

幸好MFDeploy程序(MF SDK中的部署工具)是用C#开发的,所以深入研究该程序后,终于从中提取出一个USB读写类(MFDeploy程序太复杂了,我研究了好长时间才粗略理清相关逻辑脉络),终于很方便的用C#操作USB设备了。

 

 

C# USB

 

相关接口:

    public interface IControllerLocal : IController

    {

        Stream OpenPort();

    }

    public interface IController

    {

        void ClosePort();

        bool SendData(byte[] buf);

        int Available { get; }

        int ReadData(byte[] buf, int offset, int count);

        void Start();

        void Stop();

        bool IsPortConnected { get; }

        DateTime LastActivity { get; }

    }

    public interface IControllerHostLocal

    {

        Stream OpenConnection();

}

应用代码:

 

using System;

using System.Drawing;

using System.Windows.Forms;

using System.Collections;

using System.Threading;

using Microsoft.SPOT.Debugger;

 

namespace USBTest

{

    public partial class frmMain : Form

    {

        UsbEngine usb =null;

        ArrayList pds=null;

        private Thread m_ReadThread;

 

        public frmMain()

        {

            InitializeComponent();

            btnSend.Enabled = false;

            btnUpdata_Click(null, null);

        }

 

        private void btnUpdata_Click(object sender, EventArgs e)

        {

            pds = UsbEngine.Enumerate();

            cmbUSBList.Items.Clear();

            foreach (PortDefinition pd in pds)

            {

                cmbUSBList.Items.Add(pd.DisplayName);

            }

            if (cmbUSBList.Items.Count > 0 )cmbUSBList.SelectedIndex = 0;

            else btnSend.Enabled = false;

        }

 

        private void cmbUSBList_SelectedIndexChanged(object sender, EventArgs e)

        {

            if (usb != null)

            {

                btnSend.Enabled = false;

                usb.Dispose();

            }

            btnSend.Enabled = true;

            usb = new UsbEngine((PortDefinition)pds[cmbUSBList.SelectedIndex]);

            usb.Start();

            m_ReadThread = new Thread(new ThreadStart(this.ReadDataThread));

            m_ReadThread.IsBackground = true;

            m_ReadThread.Start();

        }

 

        private void ReadDataThread()

        {

            byte[] bytData = new byte[1024];

            while (btnSend.Enabled)

            {

                try

                {                  

                    if (usb.Available> 0)

                    {

                        int intRet = usb.ReadData(bytData, 0, usb.Available);

                        MethodInvoker method = delegate

                        {

                            string strData = "";

                            for (int i = 0; i < intRet; i++)

                            {

                                strData += bytData[i].ToString("X2") + " ";

                            }

                            txtRead.Text += strData;

                        };

                        this.txtRead.Invoke(method);

                    }

                    Thread.Sleep(100);

                }

                catch { }

            }

        }

 

        private void btnSend_Click(object sender, EventArgs e)

        {

            if (usb == null || txtSend.Text.Length == 0 ) return;

            try

            {

                string[] strData = txtSend.Text.Split(new char[] { ' ' });

                byte[] bytData = new byte[strData.Length];

 

                for (int i = 0; i < bytData.Length; i++)

                {

                    bytData[i] = (byte)Convert.ToInt32(strData[i], 16);

                }

 

                usb.SendData(bytData);

            }

            catch(Exception ex)

            {

                txtRead.Text = "Send Error:" + ex.Message.ToString();

            }

        }

        private void frmMain_FormClosing(object sender, FormClosingEventArgs e)

        {

            if (usb == null) return;

            btnSend.Enabled = false;

            usb.Stop();

        }     

    }

}

现在很多USB设备都是免驱的了,就是实现了HID封装,借助该通道和USB设备通信。我对该技术非常感兴趣,有时间可以深入研究一下。有此类经验的朋友也希望能分享一下。

 

还有一个值得高兴的事,Micro Framework美国微软研发团队终于向我们开放了TinyCLR源码,这是一个非常值得纪念的开始,意味着我们中国的MF团队又向美国的MF开发团队走近了一步,期待我们能在MF上走的更远。正如Lorenzo所说:We are very excited about this opportunity and we are confident that it will have a huge impact on our business.  This could be the beginning of a great collaboration.  

           

给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow

这里写图片描述
你好! 这是你第一次使用 **Markdown编辑器** 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。

新的改变

我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你用它写博客:

  1. 全新的界面设计 ,将会带来全新的写作体验;
  2. 在创作中心设置你喜爱的代码高亮样式,Markdown 将代码片显示选择的高亮样式 进行展示;
  3. 增加了 图片拖拽 功能,你可以将本地的图片直接拖拽到编辑区域直接展示;
  4. 全新的 KaTeX数学公式 语法;
  5. 增加了支持甘特图的mermaid语法1 功能;
  6. 增加了 多屏幕编辑 Markdown文章功能;
  7. 增加了 焦点写作模式、预览模式、简洁写作模式、左右区域同步滚轮设置 等功能,功能按钮位于编辑区域与预览区域中间;
  8. 增加了 检查列表 功能。

功能快捷键

撤销:Ctrl/Command + Z
重做:Ctrl/Command + Y
加粗:Ctrl/Command + B
斜体:Ctrl/Command + I
标题:Ctrl/Command + Shift + H
无序列表:Ctrl/Command + Shift + U
有序列表:Ctrl/Command + Shift + O
检查列表:Ctrl/Command + Shift + C
插入代码:Ctrl/Command + Shift + K
插入链接:Ctrl/Command + Shift + L
插入图片:Ctrl/Command + Shift + G

合理的创建标题,有助于目录的生成

直接输入1次#,并按下space后,将生成1级标题。
输入2次#,并按下space后,将生成2级标题。
以此类推,我们支持6级标题。有助于使用TOC语法后生成一个完美的目录。

如何改变文本的样式

强调文本 强调文本

加粗文本 加粗文本

标记文本

删除文本

引用文本

H2O is是液体。

210 运算结果是 1024.

插入链接与图片

链接: link.

图片: Alt

带尺寸的图片: Alt

当然,我们为了让用户更加便捷,我们增加了图片拖拽功能。

如何插入一段漂亮的代码片

博客设置页面,选择一款你喜欢的代码片高亮样式,下面展示同样高亮的 代码片.

// An highlighted block var foo = 'bar'; 

生成一个适合你的列表

  • 项目
    • 项目
      • 项目
  1. 项目1
  2. 项目2
  3. 项目3
  • 计划任务
  • 完成任务

创建一个表格

一个简单的表格是这么创建的:

项目 Value
电脑 $1600
手机 $12
导管 $1

设定内容居中、居左、居右

使用:---------:居中
使用:----------居左
使用----------:居右

第一列 第二列 第三列
第一列文本居中 第二列文本居右 第三列文本居左

SmartyPants

SmartyPants将ASCII标点字符转换为“智能”印刷标点HTML实体。例如:

TYPE ASCII HTML
Single backticks 'Isn't this fun?' ‘Isn’t this fun?’
Quotes "Isn't this fun?" “Isn’t this fun?”
Dashes -- is en-dash, --- is em-dash – is en-dash, — is em-dash

创建一个自定义列表

Markdown
Text-to- HTML conversion tool
Authors
John
Luke

如何创建一个注脚

一个具有注脚的文本。2

注释也是必不可少的

Markdown将文本转换为 HTML

KaTeX数学公式

您可以使用渲染LaTeX数学表达式 KaTeX:

Gamma公式展示 Γ ( n ) = ( n 1 ) ! n N \Gamma(n) = (n-1)!\quad\forall n\in\mathbb N 是通过欧拉积分

Γ ( z ) = 0 t z 1 e t d t &ThinSpace; . \Gamma(z) = \int_0^\infty t^{z-1}e^{-t}dt\,.

你可以找到更多关于的信息 LaTeX 数学表达式here.

新的甘特图功能,丰富你的文章

gantt
        dateFormat  YYYY-MM-DD
        title Adding GANTT diagram functionality to mermaid
        section 现有任务
        已完成               :done,    des1, 2014-01-06,2014-01-08
        进行中               :active,  des2, 2014-01-09, 3d
        计划一               :         des3, after des2, 5d
        计划二               :         des4, after des3, 5d
  • 关于 甘特图 语法,参考 这儿,

UML 图表

可以使用UML图表进行渲染。 Mermaid. 例如下面产生的一个序列图::

张三 李四 王五 你好!李四, 最近怎么样? 你最近怎么样,王五? 我很好,谢谢! 我很好,谢谢! 李四想了很长时间, 文字太长了 不适合放在一行. 打量着王五... 很好... 王五, 你怎么样? 张三 李四 王五

这将产生一个流程图。:

链接
长方形
圆角长方形
菱形
  • 关于 Mermaid 语法,参考 这儿,

FLowchart流程图

我们依旧会支持flowchart的流程图:

  • 关于 Flowchart流程图 语法,参考 这儿.

导出与导入

导出

如果你想尝试使用此编辑器, 你可以在此篇文章任意编辑。当你完成了一篇文章的写作, 在上方工具栏找到 文章导出 ,生成一个.md文件或者.html文件进行本地保存。

导入

如果你想加载一篇你写过的.md文件或者.html文件,在上方工具栏可以选择导入功能进行对应扩展名的文件导入,
继续你的创作。


  1. mermaid语法说明 ↩︎

  2. 注脚的解释 ↩︎

猜你喜欢

转载自blog.csdn.net/gfuugfd/article/details/84065263
今日推荐