【经验分享】鼠标HID例程简析(上)
本帖最后由 FSL_TICS_ZP 于 2014-9-16 08:59 编辑鼠标HID例程简析
大家好,此文内容紧跟《FSL USB Stack 简介》一文,如果网友们先前没有浏览过《FSL USB Stack 简介》,建议先下载浏览,然后再浏览本篇内容。本篇是以飞思卡尔的USB协议栈Freescale USB Stack v4.1.1中的鼠标HID例程为例,介绍USB Stack层式架构中的USB Application、HID Class Drivers 和 USB Drivers是如何各司其职,相互配合确保例程,本例程路径:<dir_stall>\USBFreescale USB Stack v4.1.1\ Source\Device\app\hid\cw10\kinetis_l2k
1. USB Stack文件介绍
图1为在CW10.6中打开的kinetis_l2k例程, 从中可看出,在USB Stack层式架构中,USB Application、HID Class Drivers 和 USB Drivers都有属于本层的文件,表一则对各层的文件进行了归纳。
图1 USB Stack 文件
表一
2. 鼠标HID例程代码
主程序
*****************************************************************************
* This function initializes the system, enables the interrupts and calls the
* application
*****************************************************************************/
#ifdef __GNUC__
int main(void)
#else
void main(void)
#endif
{
/* Initialize the system */
SYS_Init(); //时钟配置:PEE模式,CORE_CLOCK、SYSTEM_CLOCK、BUS_CLOCK、FLASH_CLOCK为48MHz
#ifdef SERIAL_DEBUG
sci_init();
#endif
#ifndef _SERIAL_AGENT_
/* Initialize USB module */
#if HIGH_SPEED_DEVICE
USB_Init(ULPI);
#else
USB_Init(MAX3353);//USB模块初始化
#endif
#else
SIM_SOPT2|= (SIM_SOPT2_USBSRC_MASK | SIM_SOPT2_PLLFLLSEL_MASK);
#endif
/* Initialize GPIO pins */
GPIO_Init(); //按键引脚初始化:PTA4、PTC3
#if MAX_TIMER_OBJECTS
(void)TimerQInitialize(0);
#endif
/* Initialize the USB Test Application */
TestApp_Init();//鼠标HID应用运行开始,内含USB_Class_HID_Init()函数
while(TRUE)
{
Watchdog_Reset();
/* Call the application task */
TestApp_Task();//应用任务函数
}
#ifdef __GNUC__
return 0;
#endif
}
pll_init()
SYS_Init()函数中包含pll_init()函数用于配置PEE时钟模式和
各个时钟源的频率。
static int pll_init()
{
#elif (defined MCU_MKL25Z4)
/* Update system prescalers */
SIM_CLKDIV1= SIM_CLKDIV1_OUTDIV4(1);
SIM_CLKDIV1 |= SIM_CLKDIV1_OUTDIV1(1);
/* First FEI must transition to FBE mode
Enable external oscillator, RANGE=02, HGO=, EREFS=, LP=, IRCS= */
MCG_C2 = MCG_C2_RANGE0(2) | MCG_C2_EREFS0_MASK | MCG_C2_IRCS_MASK;
/* Select external oscillator and Reference Divider and clear IREFS
* to start external oscillator
* CLKS = 2, FRDIV = 3, IREFS = 0, IRCLKEN = 0, IREFSTEN = 0
*/
MCG_C1 = MCG_C1_CLKS(2) | MCG_C1_FRDIV(3);
/* MCG_C4: DMX32=0,DRST_DRS=0 */
MCG_C4 &= (uint8_t)~(uint8_t)0xE0U;
/* MCG_C5: ??=0,PLLCLKEN=0,PLLSTEN=1,PRDIV=0x3, external clock reference = 8/4 = 2MHz */
MCG_C5 = (uint8_t)0x23U;
/* MCG_C6: LOLIE=0,PLLS=0,CME=0,VDIV=0x18 */
MCG_C6 = (uint8_t)0x18U;
while((MCG_S & MCG_S_IREFST_MASK) != 0x00U) { /* Check that the source of the FLL reference clock is the external reference clock. */
}
while((MCG_S & 0x0CU) != 0x08U) { /* Wait until external reference clock is selected as MCG output */
}
/* Switch to PBE Mode */
/* MCG_C1: CLKS=2,FRDIV=3,IREFS=0,IRCLKEN=0,IREFSTEN=0 */
MCG_C1 = MCG_C1_CLKS(2) | MCG_C1_FRDIV(3);
/* MCG_C2: ??=0,??=0,RANGE=2,HGO=0,EREFS=0,LP=0,IRCS=1 */
MCG_C2 = MCG_C2_RANGE0(2) | MCG_C2_EREFS0_MASK | MCG_C2_IRCS_MASK;
/* MCG_C5: ??=0,PLLCLKEN=0,PLLSTEN=1,PRDIV=0x03 */
MCG_C5 = (uint8_t)0x23U;
/* MCG_C6: LOLIE=0,PLLS=1,CME=0,VDIV=0x18 */
MCG_C6 = (uint8_t)0x58U;
while((MCG_S & 0x0CU) != 0x08U) { /* Wait until external reference clock is selected as MCG output */
}
while((MCG_S & MCG_S_LOCK0_MASK) == 0x00U) { /* Wait until locked */
}
/* Switch to PEE Mode */
/* MCG_C1: CLKS=0,FRDIV=3,IREFS=0,IRCLKEN=0,IREFSTEN=0 */
MCG_C1 = (uint8_t)0x18U;
/* MCG_C2: ??=0,??=0,RANGE=2,HGO=0,EREFS=0,LP=0,IRCS=1 */
MCG_C2 = MCG_C2_RANGE0(2) | MCG_C2_EREFS0_MASK | MCG_C2_IRCS_MASK;
/* MCG_C5: ??=0,PLLCLKEN=0,PLLSTEN=1,PRDIV=0x03 */
MCG_C5 = (uint8_t)0x23U;
/* MCG_C6: LOLIE=0,PLLS=1,CME=0,VDIV=0x18 */
MCG_C6 = (uint8_t)0x58U;
while((MCG_S & 0x0CU) != 0x0CU) { /* Wait until output of the PLL is selected */
}
/* MCG_C6: CME=1 */
MCG_C6 |= (uint8_t)0x20U; /* Enable the clock monitor */
/*** End of PE initialization code after reset ***/
return 0;
/* end MCU_MKL25Z4 */
}
USB_Init()
static void USB_Init(uint_8 controller_ID)
{
if(controller_ID == MAX3353)
{
#ifdef MCU_MK70F12
/* MPU is disabled. All accesses from all bus masters are allowed */
MPU_CESR=0;
SIM_SOPT2 |= SIM_SOPT2_PLLFLLSEL(1) /** PLL0 reference */
| SIM_SOPT2_USBFSRC(0) /** MCGPLLCLK as CLKC source */
| SIM_SOPT2_USBF_CLKSEL_MASK; /** USB fractional divider like USB reference clock */
SIM_CLKDIV2 = USB_FRAC | USB_DIV; /** Divide reference clock to obtain 48MHz */
/* Enable USB-OTG IP clocking */
SIM_SCGC4 |= SIM_SCGC4_USBFS_MASK;
#else
#ifndef MCU_MKL25Z4
SIM_CLKDIV2 &= (uint32_t)(~(SIM_CLKDIV2_USBFRAC_MASK | SIM_CLKDIV2_USBDIV_MASK));
#endif /* MCU_MKL25Z4 */
#ifdef MCGOUTCLK_72_MHZ
/* Configure USBFRAC = 0, USBDIV = 0 => frq(USBout) = 2 / 3 * frq(PLLin) */
SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(2) | SIM_CLKDIV2_USBFRAC_MASK;
#else
#ifndef MCU_MKL25Z4
/* Configure USBFRAC = 0, USBDIV = 0 => frq(USBout) = 1 / 1 * frq(PLLin) */
SIM_CLKDIV2 = SIM_CLKDIV2_USBDIV(0);
#endif /* MCU_MKL25Z4 */
#endif /* MCGOUTCLK_72_MHZ */
/* 1. Configure USB to be clocked from PLL */
SIM_SOPT2 |= SIM_SOPT2_USBSRC_MASK | SIM_SOPT2_PLLFLLSEL_MASK;
#if PLL_96
/* 2. USB freq divider */
SIM_CLKDIV2 = 0x02;
#endif /* PLL_96 */
/* 3. Enable USB-OTG IP clocking */
SIM_SCGC4 |= (SIM_SCGC4_USBOTG_MASK);
/* old documentation writes setting this bit is mandatory */
USB0_USBTRC0 = 0x40;
/* Configure enable USB regulator for device */
#if(defined MCU_MK20D5)
SIM_SOPT1CFG |= SIM_SOPT1CFG_URWE_MASK; /* Enable SOPT1 to be written */
#endif
SIM_SOPT1 |= SIM_SOPT1_USBREGEN_MASK;
}
#endif
GPIO_Init()
static void GPIO_Init()
{
#if defined(MCU_MKL25Z4)
/* Enable clock gating to PORTA, PORTB, PORTC, PORTD and PORTE */
SIM_SCGC5 |= (SIM_SCGC5_PORTA_MASK
| SIM_SCGC5_PORTB_MASK
| SIM_SCGC5_PORTC_MASK
| SIM_SCGC5_PORTD_MASK
| SIM_SCGC5_PORTE_MASK);
/* LEDs settings */
PORTA_PCR5=PORT_PCR_MUX(1);
PORTA_PCR16 =PORT_PCR_MUX(1);
PORTA_PCR17 =PORT_PCR_MUX(1);
PORTB_PCR8=PORT_PCR_MUX(1);
GPIOA_PDDR |= (1<<5) | (1<<16) | (1<<17);
GPIOB_PDDR |= (1<<8);
/* Switch buttons settings */
/* Set input on PORTC pin 3 */
#ifndef _USB_BATT_CHG_APP_H_
PORTC_PCR3 =PORT_PCR_MUX(1);
GPIOC_PDDR &= ~((uint_32)1 << 3);
/* Pull up enabled */
PORTC_PCR3 |= PORT_PCR_PE_MASK | PORT_PCR_PS_MASK;
/* GPIO_INT_EDGE_HIGH */
PORTC_PCR3 |= PORT_PCR_IRQC(9);
/* Set input on PORTA pin 4 */
PORTA_PCR4 =PORT_PCR_MUX(1);
GPIOA_PDDR &= ~((uint_32)1 << 4);
/* Pull up */
PORTA_PCR4 |= PORT_PCR_PE_MASK | PORT_PCR_PS_MASK;
/* GPIO_INT_EDGE_HIGH */
PORTA_PCR4 |= PORT_PCR_IRQC(9);
/* Clear interrupt flag */
PORTC_ISFR = (1 << 3);
PORTA_ISFR = (1 << 4);
/* Enable interrupt port A */
NVIC_ICPR = 1 << 30;
NVIC_ISER = 1 << 30;
#endif
#endif
}
文档下载:
参考文献:
Freescale USB Device Stack Users Guide
Freescale USB Stack Device API Reference Manual
FSL USB Stack 4.1.1
如有什么错误或者不足,欢迎网友指正,请在后面跟帖! BSP的相关配置代码是PE生产的么?用惯了st的库,看起来眼晕。 嗯,不错,不过在USB 描述符 这个方面没有 详细的分析,描述符能不能看懂,会不会改是做HID设备时很重要的一环啊
最近都在做USB有关的程序,很希望哪位能详细分析下HID相关的描述符,这样就不用看文档看得那么辛苦{:lol:} 我现在感觉少量数据通讯HID还真是方便。以前开发编程器的时候,就考虑过,后来已经开发了一半了,也就没有推倒重来。HID不需要驱动,对少量数据交换还是很方便的。现在的很多读卡器都是采用这样的模式了。很方便。 非常好,顶 能把程序完整的给出来么?看的有点不知所措{:titter:} 学习一下 下载下来参考下 fengyunyu 发表于 2014-9-15 11:55
BSP的相关配置代码是PE生产的么?用惯了st的库,看起来眼晕。
这个例程不是基于PE的,我会将USB stack 4.1.1的链接在帖子中给出,你可以自己看一下。 帮顶~~~~不错~~ weiwei4 发表于 2014-9-15 17:14
嗯,不错,不过在USB 描述符 这个方面没有 详细的分析,描述符能不能看懂,会不会改是做HID设备时很重要的 ...
在这一次不会讲相关描述符的内容,但在之前我们已经针对USB的基础知识作了两篇文章,进行详细的介绍啊,
相信对你应该很有帮助,链接如下。
http://www.amobbs.com/thread-5575630-1-1.html
http://www.amobbs.com/thread-5578354-1-1.html ccrt 发表于 2014-9-15 21:50
能把程序完整的给出来么?看的有点不知所措
文章没有写完,所以例程没有完全给出,
但你你可以根据我在帖子中,给出的USB stack 4.1.1下载链接,下载后,打开工程看看代码。 ltmooner 发表于 2014-9-16 09:01
帮顶~~~~不错~~
谢谢支持! 谢谢,努力学习。。。 mark 。。。。。 看着好像有点库文件的意思,飞思卡尔的这款芯片是不是也有封装库了? yzb1019 发表于 2014-9-16 09:27
看着好像有点库文件的意思,飞思卡尔的这款芯片是不是也有封装库了?
这不是库文件。 FSL_TICS_ZP 发表于 2014-9-16 10:05
这不是库文件。
那应该是USB库文件? FSL_TICS_ZP 发表于 2014-9-16 09:02
在这一次不会讲相关描述符的内容,但在之前我们已经针对USB的基础知识作了两篇文章,进行详细的介绍啊,
...
原来在官方例程里有对USB这么详细分析的文档,官方例程没看完,所以不知道后面有这么好的内容,谢谢版主了
下载下来参考下
页:
[1]