[其他MCU] LPC1788—USB学习

[复制链接]
 楼主| quray1985 发表于 2015-12-28 20:11 | 显示全部楼层 |阅读模式
第一章;开发板和PC实现连接
开发环境:集成开发环境µVision4 IDE版本4.60.0.0
主机系统:Microsoft Windows XP
开发平台:旺宝悍马1788开发板

一:了解硬件

本开发板是基于NXPLPC1788FBD208基础上研发的一款开发板。LPC1788内部集成ARM Cortex-M3微控制器,NXP 半导体针对各种高级通讯,高质量图像显示等应用场合而设计的一款具有高集成度的SOC。居然是针对各种高级通讯,那么学习USB那就是可以的。

 楼主| quray1985 发表于 2015-12-28 20:12 | 显示全部楼层
USB电路图如下图;
图(111
如果想要开发USB Device需要把J19J20两个拨码开关的“1”和“2”接通,使USBD2-D2+连接到J16USB Device接口。下面的J17USB主机的,有人就会问现在学USB DeviceUSB Host电路图贴出来干嘛啊!不急等下我们就会说到,现在先不用管它。

 楼主| quray1985 发表于 2015-12-28 20:13 | 显示全部楼层
二:USB基础知识
当我们每次用到带有USB接口的设备感觉就是两个字“方便”。拿到USB数据线两头一插就OK。现在我们就从把数据线插入电脑的那一瞬间开始说起。那些什么同步啊拓扑结构啊啥的先抛开,嫩得我们费脑子胡思乱想,到后来想了半天不知道干嘛。
有细心的朋友可能都看到图(11)电路图,USB DeviceUSB Host两个电路的不同,在USB Device电路中D2+的线上连接了一个1.5K电阻经过了一个三级管Q13.3V(高电平),而在USB Host电路中D2-D2+上各经过了一个10K的电阻到地(低电平)。我们电脑上的USB接口就是USB Host,内部电路就和上图的USB Host类似。当我们把USB Device插入到电脑时,电脑上的USB接口就会有一个5V电压给我们的USB DeviceUSB Device内部硬件初始化,而内部的硬件就会从USB_CONNECT2输出一个信号给三极管Q1让三极管导通把USB DeviceD2+拉为高电平,这时电脑上USB HostD2+由原来的低电平也变为高电平。这时在电脑上就会检测到发现新硬件,而且是一个无**常运行的设备,如图121。这设备管理器中的通用串行总线控制器会出现一个未知设备
 楼主| quray1985 发表于 2015-12-28 20:13 | 显示全部楼层
如图122
图(121

图(122

 楼主| quray1985 发表于 2015-12-28 20:15 | 显示全部楼层
这个过程当中主机检测到有设备插入就会向设备发送一些数据,而这些数据是设备刚插入主机时主机所要设备描述符的控制传输。现在我们的设备没有任何驱动程序来响应“组织的号召”,所以我们的“中央”就不知道如何来加载主机驱动来管理我们的设备,“中央”就会把它拉入黑名单说,硬件安装出现问题,设备不能正常运行,所以在设备管理器中就冒出了一个未知设备。在未知设备上点右键属性,在详细信息选项卡中会看到VIDPID都是0如图123a。图123b是枚举成功的大容量存储设备。
图(123a

 楼主| quray1985 发表于 2015-12-28 20:15 | 显示全部楼层
2015-5-7 14:34 上传
下载附件 (27.24 KB)

图(123b
三:软件配置
我们来看一下程序在悍马1788是如何实现连接的。工程创建不讲述。

 楼主| quray1985 发表于 2015-12-28 20:16 | 显示全部楼层
  1. /**********************************************************************
  2. 函数功能;主函数
  3. 函 数 名;main
  4. 函数参数;无
  5. 函数返回;无
  6. ***********************************************************************/
  7. int main (void)
  8. {
  9.         debug_frmwrk_init();                /*串口调试初始化,
  10. 用于打印调试信息
  11. 和主机发给开发板
  12. 的数据还有开发板
  13. 发给主机的数据。*/
  14.         print_menu();                                        //打印字符串。
  15.         USB_Init();                              // 初始化USB
  16.         USB_SetDevCondition(DEV_CON);        // 链接USB                     
  17.         while (1)
  18.         {      
  19.                 ;
  20.         }
  21. }


 楼主| quray1985 发表于 2015-12-28 20:17 | 显示全部楼层
看起来好像很简单,main函数里面关于USB的代码就两行。现在我们就来看下USB_Init();
  1. /**********************************************************************
  2. 函数功能;初始化USB函数
  3. 函 数 名;USB_Init
  4. 函数参数;无
  5. 函数返回;无
  6. ***********************************************************************/
  7. void USB_Init (void)
  8. {      
  9.         PINSEL_ConfigPin ( 0, 31, 1);                        //P0.31管脚设置为USB_D2+的功能
  10.         PINSEL_ConfigPin ( 0, 14, 3);                        //P0.14管脚设置为USB_CONNECT2功能
  11.         CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCUSB, ENABLE);        //配置USB时钟/电源
  12.           LPC_USB->USBClkCtrl = 0x1A;        /*USB时钟控制寄存器,
  13. 它控制了AHB、端口选
  14. 择寄存器、设备时钟,
  15. 这些时钟的使能和失能。*/
  16.           while ((LPC_USB->USBClkSt & 0x1A) != 0x1A);                /*USBClkSt 寄存器是
  17. 时钟状态寄存器,检查
  18. 是否设置为0x1A。*/
  19.           LPC_USB->StCtrl = 0x3;                             //端口选择寄存器我们用的USB2所以是就是0x3
  20. }


 楼主| quray1985 发表于 2015-12-28 20:17 | 显示全部楼层
在初始化函数里面就只有USB_D2+USB_CONNECT2引脚被配置了,而USB_D2-VBUS没有配置。我们来看下LPC1788Data Sheet里对USB Device的管脚描述。


 楼主| quray1985 发表于 2015-12-28 20:18 | 显示全部楼层
VBUS引脚描述的大概意思是,VBUS是一个输入状态,在没有IOCON寄存器,它的内部是上拉的。反正大概意思就是这样。如果是上拉那么它就可以触发内部的硬件。为了程序的简单我们就不对它进行配置。VBUS可以不管那USB_D2-咋不配置呢?现在来看一下原理图,如图24
图(124

 楼主| quray1985 发表于 2015-12-28 20:19 | 显示全部楼层
这个管脚是默认为USB_D2-,可以不用配置。LED管脚也不用配置,应为我们没有用到LED灯。
接下来就是USB基本配置用库函数的CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCUSB, ENABLE);来使能时钟和电源,下一行是USBClkCtrl寄存器配置,这个寄存器是USB时钟控制寄存器,它控制了AHB、端口选择寄存器、设备时钟,这些时钟的使能和失能,下面就是USBClkSt寄存器,这个寄存器是时钟状态寄存器,只是用来检测USBClkCtrl寄存器是否成功配置,还有一个是StCtrl寄存器,它是用来选择是用那一个USB端口,我们用的USB2看下数据手册,从寄存器里看设置为3是对的。


 楼主| quray1985 发表于 2015-12-28 20:20 | 显示全部楼层
  1. 实现简单的连接功能,初始化这些就可以搞定。现在分析USB_SetDevCondition(DEV_CON)函数;
  2. /**********************************************************************
  3. 函数功能;设置USB设备状态
  4. 函 数 名;USB_SetDevCondition
  5. 函数参数;con;DEV_CON      0x01连接位表示设备的当前连接状态。用于CONNECT输出
  6. DEV_CON_CH  0x02连接发生改变
  7.   DEV_SUS      0x04挂起位表示当前的挂起状态
  8.                           DEV_SUS_CH  0x08挂起位(DEV_SUS)的变化指示,
  9.                                                                   设备进入挂起状态、设备断开连接、                                                                                                  设备在其上行端口上接收到恢复信号,                                                                                                  会发生翻转
  10.                            DEV_RST      0x10总线复位位
  11. 函数返回;无
  12. ***********************************************************************/
  13. void USB_SetDevCondition(uint32_t con)
  14. {
  15.   WrCmdDat(CMD_SET_DEV_STAT, DAT_WR_BYTE(con));
  16. }


 楼主| quray1985 发表于 2015-12-28 20:21 | 显示全部楼层
我们看到USB_SetDevCondition(DEV_CON);函数里面还调用了WrCmdDat(CMD_SET_DEV_STAT, DAT_WR_BYTE(con));函数这个函数是一个写命令数据函数。
  1. /**********************************************************************
  2. 函数功能;写命令数据函数
  3. 函 数 名;WrCmdDat
  4. 函数参数;cmd;命令
  5.                   val: 数据
  6. 函数返回;无
  7. ***********************************************************************/
  8. void WrCmdDat (uint32_t cmd, uint32_t val)
  9. {
  10.   LPC_USB->DevIntClr = 1<<4;                /*DevIntClr寄存器是设备中断清除寄存器
  11.                                                                         写相应的位就会清除DevIntSt设备中断状态
  12.                                                                 寄存器相应位,应为我们要写命令,所以我
  13.                                                                 们要把命令代码寄存器为空中断标志位清除*/
  14.   LPC_USB->CmdCode = cmd;                /*写入命令*/
  15.   while ((LPC_USB->DevIntSt & 1<<4) == 0);        /*等待命令代码寄存器
  16. 为空中断标志位置位*/
  17.   LPC_USB->DevIntClr = 1<<4;                                /*清除中断*/                                               
  18.   LPC_USB->CmdCode = val;                                /*写入数据*/      
  19.   while ((LPC_USB->DevIntSt & 1<<4) == 0);        /*清除中断*/
  20. }
 楼主| quray1985 发表于 2015-12-28 20:22 | 显示全部楼层
在写命令数据函数里DevIntClr 寄存器有很详细的注释,关键要看的就是CmdCode寄存器,下面就是CmdCode寄存器的描述。


 楼主| quray1985 发表于 2015-12-28 20:23 | 显示全部楼层
/*命令格式
低八位保留。
8--15位是命令段,
0x02代表读、0x01代表写、0x05代表命令。
16--23位是多用途字段,
当命令阶段为0x05命令或0x02读时,该域包含着命令代码,
当命令阶段为0x01写状态时,该域包含着命令写数据。*/
现在来看第一次给CmdCode寄存器赋值,后面的注释是说,/*写入命令*/而我们的命令是这样定义的,如下代码。
#define CMD_SET_DEV_STAT  0x00FE0500        //FE设置设备状态,05命令
按照上面的命令格式分析。8—15位是命令段值是0x05说明代表的是命令,16—23位是就是命令代码了值是0xFE。现在看手册上说FE命令代表的是啥。
 楼主| quray1985 发表于 2015-12-28 20:24 | 显示全部楼层
 楼主| quray1985 发表于 2015-12-28 20:25 | 显示全部楼层
再看描述的时候一定要注意,上面写的Command: 0xFE, Data: write 1 byte
意思是,命令0xFE,数据写入一个字节,而写入的一个字节是下一次向CmdCode寄存器执行写数据时就可以操作0xFE命令所提供的功能,注释/*写入数据*/的那一行代码。就是我们要实现的连接功能,现在来看下定义的数据是多少!

#define DAT_WR_BYTE(x)   (0x00000100 | ((x) << 16))        //x为要写入的数据,01写。

用前面说的命令格式分析就知道这条命令是写命令。在main函数中调用的USB_SetDevCondition(DEV_CON);函数的参数DEV_CON的定义是;

#define DEV_CON  0x01        //连接位表示设备的当前连接状态。用于CONNECT输出

这说明写入0xFE命令所提供功能的数据是0x01,对照前面0xFE提供的功能可以知道这就是让CONNECT输出低电平。这样就实现了D2+拉高了。

您需要登录后才可以回帖 登录 | 注册

本版积分规则

156

主题

1488

帖子

5

粉丝
快速回复 在线客服 返回列表 返回顶部

156

主题

1488

帖子

5

粉丝
快速回复 在线客服 返回列表 返回顶部