首要,咱们来看看usb的作业进程。
当usb设备接入到主机时,主机开端枚举usb设备,并向usb设备宣布指令要求获取usb设备的相关描绘信息,其间包含设备描绘(device descriptor)、装备描绘(configuration descriptor)、接口描绘(interface descriptor)、端点描绘(endpoint descriptor)等。这些信息是经过端点0(endpoint 0)传送到主机的。获取各种描绘信息后,操作系统会为其装备相应的资源。这样主机就可以与设备之间进行通讯了。
usb通讯有四种通讯方法操控(control)、中止(interrupt)、批量(bulk)和同步(synchronous)。usb通讯是经过管道(pipe)完结的。管道是一个笼统的概念,指的是主机与设备之间通讯的虚拟链路。比如说一个usb通讯主机A和设备B,其间有bulk in(批量输入)、bulk out(批量输出)、control out(操控输出)三种通讯方法,那么A与B之间的通讯管道就有三个。(这儿清晰一个概念,在usb通讯中数据流向都是相对设备来说的,in表明设备向主机传送数据,out表明表明主机箱设备传输数据)。在设备一端,每个管道对应一个端点,端点装备相关的寄存器和缓冲区。在通讯之前需对端点进行相关设置。在通讯中,只需向缓冲写或读数据,并置位相关比特位即可。
下面详细从usb的中止输入输出来叙述依据keil C mdk开发环境的stm32的USB接口单片机程序设计。值得一提的是,st或相关公司给咱们供给许多封装函数和相关比如,咱们可以依据其间的比如并进行修正即可完结咱们自己需求的usb通讯程序。
1.usb描绘符装备
从上面的叙述可以看出,usb描绘符是usb通讯的条件。主机必须先了解设备后才干与其进行通讯。在st供给的比如中,描绘符都在usb_des.c文件进行界说,下面就其间的Joystick比如阐明usb描绘负的装备。
1.1设备描绘符
const u8 Joystick_DeviceDescriptor[JOYSTICK_SIZ_DEVICE_DESC] =
{
0x12,
USB_DEVICE_DESCRIPTOR_TYPE,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x84,
0x19,
0x06,
0x04,
0x00,
0x02,
1,
2,
3,
0x01
}
设备描绘符两个重要参数是生产商ID和产品ID,主机将依据以上两个ID为设备挑选相应驱动程序。在咱们的运用中,咱们一般只需修正比如中的这儿两个参数即可完结设备描绘符的设置。
1.2装备描绘符
const u8 Joystick_ConfigDescriptor[JOYSTICK_SIZ_CONFIG_DESC] =
{
0x09,
USB_CONFIGURATION_DESCRIPTOR_TYPE,
JOYSTICK_SIZ_CONFIG_DESC,
0x00,
0x01,
0x01,
0x00,
0xE0,
0x32,
0x09,
USB_INTERFACE_DESCRIPTOR_TYPE,
0x00,
0x00,
0x02,
0x00,
0x00,
0x00,
0,
0x07,
USB_ENDPOINT_DESCRIPTOR_TYPE,
0x81,
0x03,
0x08,
0x00,
0x20,
0x07,
USB_ENDPOINT_DESCRIPTOR_TYPE,
0x01,
0x03,
0x40,
0x00,
0x20,
}
装备描绘符中包含了接口、端点的装备。假如设备为HID设备,在装备描绘符中还应参加HID描绘,详细描绘可以参照Joystick比如的装备。
还有一些其他装备可以参可相关材料与比如加以了解。
2.USB通讯的履行进程。
首要,当主机数据传送到USB设备,USB怎样接纳指令和数据呢?USB首要会发生一个中止,这个中止在stm32fxxx_it.c文件的USB_HP_CAN_TX_IRQHandler和USB_LP_CAN_RX0_IRQHandler中界说,一般运用USB_LP_CAN_RX0_IRQHandler。在这个函数中持续调用USB_Istr()函数,这个函数是usb通讯的要害。它接纳到主机指令,指使调度相应函数进行处理。关于这一点,详细进程我现在还不是很理解。假如今后搞懂了再补述。
当USB设备接入主机时,主机要枚举该USB设备,他将要求USB设备供给本身相关信息,这是经过endpoint0完结的。endpoint0是一个特别的端点,每一个接口(interface)必须有endpoint0。一般情况下,咱们需求运用多个端点(如前所述,装备描绘符界说了端点的数目、类型、传输数据巨细等)。在运用端点前需对端点进行初始化。这个进程在usb_prop.c文件中的xxx_reset()函数界说。如我界说端点1的两种传输方法:
SetEPType(ENDP1, EP_INTERRUPT);
SetEPRxAddr(ENDP1, ENDP1_RXADDR);
SetEPRxCount(ENDP1, 8);
SetEPRxStatus(ENDP1, EP_RX_VALID);
SetEPType(ENDP1, EP_INTERRUPT);
SetEPTxAddr(ENDP1, ENDP1_TXADDR);
SetEPTxCount(ENDP1, 64);
SetEPTxStatus(ENDP1, EP_TX_NAK);
在界说完端点后,咱们就可以运用端点进行数据传输了。
向主机输入数据(in):IN传输进程是
1.向缓冲区填入数据;
2.设定USB数据计数器:
3.设置USB输出有用。
XXX_send()
{
UserToPMABufferCopy(sendBuffer, ENDP1_TXADDR, 2);
SetEPTxCount(ENDP1, 2);
SetEPTxValid(ENDP1);
}
留意一般情况下,端点的输入输出缓冲区地址没有界说,须在usb_conf.h中界说详细界说可以参阅端点0的界说。
读从主机输出的数据(out):out传输进程是
1.界说out回调函数;
2.从缓冲区读出数据:
3.设置USB输入有用。
void EP1_OUT_Callback(void)
{
u8 DataLen;
DataLen = GetEPRxCount(ENDP1);
PMAToUserBufferCopy(rcvData, ENDP1_RXADDR, DataLen);
SetEPRxValid(ENDP1);
}
留意在一般情况下,EPX_OUT_Callback()回调函数的声明为空履行函数。需将usb_conf.h中#define EPX_IN_CallbackNOP_Process隐掉。再在适宜的当地重新界说void EP1_OUT_Callback(void)(适宜的方位是指界说之后运转不会呈现EP1_OUT_Callback为声明的过错就行)。
总结,在此将stm32芯片的usb通讯进行了简略的论述。自己水平有限,以上不免会有过错,期望我们活跃留言,一起讨论,一起进步。这篇文章是时断时续写的,给我们带来不方便,在此向我们抱歉了。不管怎样期望这篇文章可以对那些还在对stm32usb编程开始探索的朋友有一点协助。
声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/ceping/baogao/256435.html