LPC1788—USB學(xué)習 第一章;開(kāi)發(fā)板和PC實(shí)現連接 第一篇:了解硬件 本開(kāi)發(fā)板是基于NXP的LPC1788FBD208基礎上研發(fā)的一款開(kāi)發(fā)板。LPC1788內部集成ARM Cortex-M3微控制器,是NXP 半導體針對各種高級通訊,高質(zhì)量圖像顯示等應用場(chǎng)合而設計的一款具有高集成度的SOC。居然是針對各種高級通訊,那么學(xué)習USB那就是可以的。 USB電路圖如下圖![]() 圖(1—1—1) 如果想要開(kāi)發(fā)USB Device需要把J19和J20兩個(gè)撥碼開(kāi)關(guān)的“1”和“2”接通,使USB的D2-和D2+連接到J16的USB Device接口。下面的J17是USB主機的,有人就會(huì )問(wèn)現在學(xué)USB Device把USB Host電路圖貼出來(lái)干嘛!不急等下我們就會(huì )說(shuō)到,現在先不用管它。 第二篇:USB基礎知識 當我們每次用到帶有USB接口的設備感覺(jué)就是兩個(gè)字“方便”。拿到USB數據線(xiàn)兩頭一插就OK,F在我們就從把數據線(xiàn)插入電腦的那一瞬間開(kāi)始說(shuō)起。那些什么同步啊拓撲結構啊啥的先拋開(kāi),嫩得我們費腦子胡思亂想,到后來(lái)想了半天不知道干嘛。 有細心的朋友可能都看到圖(1—1)電路圖,USB Device和USB Host兩個(gè)電路的不同,在USB Device電路中D2+的線(xiàn)上連接了一個(gè)1.5K電阻經(jīng)過(guò)了一個(gè)三級管Q1道3.3V(高電平),而在USB Host電路中D2-和D2+上各經(jīng)過(guò)了一個(gè)10K的電阻到地(低電平)。我們電腦上的USB接口就是USB Host,內部電路就和上圖的USB Host類(lèi)似。當我們把USB Device插入到電腦時(shí),電腦上的USB接口就會(huì )有一個(gè)5V電壓給我們的USB Device讓USB Device內部硬件初始化,而內部的硬件就會(huì )從USB_CONNECT2輸出一個(gè)信號給三極管Q1讓三極管導通把USB Device上D2+拉為高電平,這時(shí)電腦上USB Host上D2+由原來(lái)的低電平也變?yōu)楦唠娖。這時(shí)在電腦上就會(huì )檢測到發(fā)現新硬件,而且是一個(gè)無(wú)法正常運行的設備,如圖1—2—1。這設備管理器中的通用串行總線(xiàn)控制器會(huì )出現一個(gè)未知設備,如圖1—2—2。 ![]() 圖(1—2—1) ![]() 圖(1—2—2) 這個(gè)過(guò)程當中主機檢測到有設備插入就會(huì )向設備發(fā)送一些數據,而這些數據是設備剛插入主機時(shí)主機所要設備描述符的控制傳輸,F在我們的設備沒(méi)有任何驅動(dòng)程序來(lái)響應“組織的號召”,所以我們的“中央”就不知道如何來(lái)加載主機驅動(dòng)來(lái)管理我們的設備,“中央”就會(huì )把它拉入黑名單說(shuō),硬件安裝出現問(wèn)題,設備不能正常運行,所以在設備管理器中就冒出了一個(gè)未知設備。在未知設備上點(diǎn)右鍵屬性,在詳細信息選項卡中會(huì )看到VID和PID都是0。如圖2—3a,圖2—3b是枚舉成功的大容量存儲設備。 ![]() ![]() 圖(1—2—3a) 圖(1—2—3b) 第三篇:軟件配置 我們來(lái)看一下程序在悍馬1788是如何實(shí)現連接的。工程創(chuàng )建不講述。 /********************************************************************** 函數功能;主函數 函 數 名;main 函數參數;無(wú) 函數返回;無(wú) ***********************************************************************/ int main (void) { debug_frmwrk_init(); /*串口調試初始化, 用于打印調試信息 和主機發(fā)給開(kāi)發(fā)板 的數據還有開(kāi)發(fā)板 發(fā)給主機的數據。*/ print_menu(); //打印字符串。 USB_Init(); // 初始化USB USB_SetDevCondition(DEV_CON); // 鏈接USB while (1) { ; } } 看起來(lái)好像很簡(jiǎn)單,main函數里面關(guān)于USB的代碼就兩行,F在我們就來(lái)看下USB_Init(); /********************************************************************** 函數功能;初始化USB函數 函 數 名;USB_Init 函數參數;無(wú) 函數返回;無(wú) ***********************************************************************/ void USB_Init (void) { PINSEL_ConfigPin ( 0, 31, 1); //P0.31管腳設置為USB_D2+的功能 PINSEL_ConfigPin ( 0, 14, 3); //P0.14管腳設置為USB_CONNECT2功能 CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCUSB, ENABLE); //配置USB時(shí)鐘/電源 LPC_USB->USBClkCtrl = 0x1A; /*USB時(shí)鐘控制寄存器, 它控制了AHB、端口選 擇寄存器、設備時(shí)鐘, 這些時(shí)鐘的使能和失能。*/ while ((LPC_USB->USBClkSt & 0x1A) != 0x1A); /*USBClkSt 寄存器是 時(shí)鐘狀態(tài)寄存器,檢查 是否設置為0x1A。*/ LPC_USB->StCtrl = 0x3; //端口選擇寄存器我們用的USB2所以是就是0x3 } 在初始化函數里面就只有USB_D2+和USB_CONNECT2引腳被配置了,而USB_D2-和VBUS沒(méi)有配置。我們來(lái)看下LPC1788Data Sheet里對USB Device的管腳描述。 ![]() VBUS引腳描述的大概意思是,VBUS是一個(gè)輸入狀態(tài),在沒(méi)有IOCON寄存器,它的內部是上拉的。反正大概意思就是這樣。如果是上拉那么它就可以觸發(fā)內部的硬件。為了程序的簡(jiǎn)單我們就不對它進(jìn)行配置。VBUS可以不管那USB_D2-咋不配置呢?現在來(lái)看一下原理圖,如圖2—4。 ![]() 圖(1—2—4) 這個(gè)管腳是默認為USB_D2-,可以不用配置。LED管腳也不用配置,應為我們沒(méi)有用到LED燈。 接下來(lái)就是USB基本配置用庫函數的CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCUSB, ENABLE);來(lái)使能時(shí)鐘和電源,下一行是USBClkCtrl寄存器配置,這個(gè)寄存器是USB時(shí)鐘控制寄存器,它控制了AHB、端口選擇寄存器、設備時(shí)鐘,這些時(shí)鐘的使能和失能,下面就是USBClkSt寄存器,這個(gè)寄存器是時(shí)鐘狀態(tài)寄存器,只是用來(lái)檢測USBClkCtrl寄存器是否成功配置,還有一個(gè)是StCtrl寄存器,它是用來(lái)選擇是用那一個(gè)USB端口,我們用的USB2看下數據手冊,從寄存器里看設置為3是對的。 ![]() 實(shí)現簡(jiǎn)單的連接功能,初始化這些就可以搞定,F在分析USB_SetDevCondition(DEV_CON)函數; /********************************************************************** 函數功能;設置USB設備狀態(tài) 函 數 名;USB_SetDevCondition 函數參數;con;DEV_CON 0x01連接位表示設備的當前連接狀態(tài)。用于CONNECT輸出 DEV_CON_CH 0x02連接發(fā)生改變 DEV_SUS 0x04掛起位表示當前的掛起狀態(tài) DEV_SUS_CH 0x08掛起位(DEV_SUS)的變化指示, 設備進(jìn)入掛起狀態(tài)、設備斷開(kāi)連接、 設備在其上行端口上接收到恢復信號, 會(huì )發(fā)生翻轉 DEV_RST 0x10總線(xiàn)復位位 函數返回;無(wú) ***********************************************************************/ void USB_SetDevCondition(uint32_t con) { WrCmdDat(CMD_SET_DEV_STAT, DAT_WR_BYTE(con)); } 我們看到USB_SetDevCondition(DEV_CON);函數里面還調用了WrCmdDat(CMD_SET_DEV_STAT, DAT_WR_BYTE(con));函數這個(gè)函數是一個(gè)寫(xiě)命令數據函數。 /********************************************************************** 函數功能;寫(xiě)命令數據函數 函 數 名;WrCmdDat 函數參數;cmd;命令 val: 數據 函數返回;無(wú) ***********************************************************************/ void WrCmdDat (uint32_t cmd, uint32_t val) { LPC_USB->DevIntClr = 1<<4; /*DevIntClr寄存器是設備中斷清除寄存器 寫(xiě)相應的位就會(huì )清除DevIntSt設備中斷狀態(tài) 寄存器相應位,應為我們要寫(xiě)命令,所以我 們要把命令代碼寄存器為空中斷標志位清除*/ LPC_USB->CmdCode = cmd; /*寫(xiě)入命令*/ while ((LPC_USB->DevIntSt & 1<<4) == 0); /*等待命令代碼寄存器 為空中斷標志位置位*/ LPC_USB->DevIntClr = 1<<4; /*清除中斷*/ LPC_USB->CmdCode = val; /*寫(xiě)入數據*/ while ((LPC_USB->DevIntSt & 1<<4) == 0); /*清除中斷*/ } 在寫(xiě)命令數據函數里DevIntClr 寄存器有很詳細的注釋?zhuān)P(guān)鍵要看的就是CmdCode寄存器,下面就是CmdCode寄存器的描述。 ![]() /*命令格式 低八位保留。 8--15位是命令段, 0x02代表讀、0x01代表寫(xiě)、0x05代表命令。 16--23位是多用途字段, 當命令階段為0x05命令或0x02讀時(shí),該域包含著(zhù)命令代碼, 當命令階段為0x01寫(xiě)狀態(tài)時(shí),該域包含著(zhù)命令寫(xiě)數據。*/ 現在來(lái)看第一次給CmdCode寄存器賦值,后面的注釋是說(shuō),/*寫(xiě)入命令*/而我們的命令是這樣定義的,如下代碼。 #define CMD_SET_DEV_STAT 0x00FE0500 //FE設置設備狀態(tài),05命令 按照上面的命令格式分析。8—15位是命令段值是0x05說(shuō)明代表的是命令,16—23位是就是命令代碼了值是0xFE,F在看手冊上說(shuō)FE命令代表的是啥。 ![]() ![]() 再看描述的時(shí)候一定要注意,上面寫(xiě)的Command: 0xFE, Data: write 1 byte 意思是,命令0xFE,數據寫(xiě)入一個(gè)字節,而寫(xiě)入的一個(gè)字節是下一次向CmdCode寄存器執行寫(xiě)數據時(shí)就可以操作0xFE命令所提供的功能,注釋/*寫(xiě)入數據*/的那一行代碼。就是我們要實(shí)現的連接功能,現在來(lái)看下定義的數據是多少! #define DAT_WR_BYTE(x) (0x00000100 | ((x) << 16)) //x為要寫(xiě)入的數據,01寫(xiě)。 用前面說(shuō)的命令格式分析就知道這條命令是寫(xiě)命令。在main函數中調用的USB_SetDevCondition(DEV_CON);函數的參數DEV_CON的定義是; #define DEV_CON 0x01 //連接位表示設備的當前連接狀態(tài)。用于CONNECT輸出 這說(shuō)明寫(xiě)入0xFE命令所提供功能的數據是0x01,對照前面0xFE提供的功能可以知道這就是讓CONNECT輸出低電平。這樣就實(shí)現了D2+拉高了。 到此第一章的知識講完。結合代碼和數據手冊可以更好的理解。不足之處還請多多指點(diǎn)。此帖會(huì )不斷更新,以實(shí)現一個(gè)USB HID的整個(gè)過(guò)程。附件有實(shí)現本章的代碼! 開(kāi)發(fā)環(huán)境:集成開(kāi)發(fā)環(huán)境μVision4 IDE版本4.60.0.0。 主機系統:Microsoft Windows XP。 開(kāi)發(fā)平臺:旺寶悍馬1788開(kāi)發(fā)板。 ![]() |