OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 11010|回复: 11

STM32 USB通信之USB_Istr(void)函数解析

[复制链接]

3

主题

24

帖子

0

精华

初级会员

Rank: 2

积分
56
金钱
56
注册时间
2014-7-14
在线时间
0 小时
发表于 2015-5-28 18:12:16 | 显示全部楼层 |阅读模式
5金钱
我现在初学USB,也看了原子的“触控USB鼠标实验”、“USB读卡实验”、“USB声卡实验”这几个实验介绍的都比较简单,主函数里面也基本没啥类容,对怎么通信的也没说。我现在就想简单的实现一个单纯的像上位机发送数据,但是一直没有实现。我改的“触控USB鼠标实验”虽然能实现我想发送的数据发送,但是PC机上像应得鼠标也动,这是我不想要的,我只想要单纯的发送数据。我改了几天代码,也下了好多版本不过没移植成功。原子的STM32开发指南对USB实验中的很多函数都没介绍。我今天看见一个函数“USB_Istr(void)”自认为他挺关键的,但是找不到解析,自己单看也看不懂。希望哪位大神给我解释下,更希望哪位大神给我提供点好的学习方法和学习技巧和这方面的资料。我的邮箱446310852@qq.com
USB_Istr(void)函数(触控USB鼠标实验中的)代码:
void USB_Istr(void)
{  
  wIstr = _GetISTR();

#if (IMR_MSK & ISTR_RESET)
  if (wIstr & ISTR_RESET & wInterrupt_Mask)
  {
    _SetISTR((u16)CLR_RESET);
    Device_Property.Reset();
#ifdef RESET_CALLBACK
    RESET_Callback();
#endif
  }
#endif
  /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if (IMR_MSK & ISTR_DOVR)
  if (wIstr & ISTR_DOVR & wInterrupt_Mask)
  {
    _SetISTR((u16)CLR_DOVR);
#ifdef DOVR_CALLBACK
    DOVR_Callback();
#endif
  }
#endif
  /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if (IMR_MSK & ISTR_ERR)
  if (wIstr & ISTR_ERR & wInterrupt_Mask)
  {
    _SetISTR((u16)CLR_ERR);
#ifdef ERR_CALLBACK
    ERR_Callback();
#endif
  }
#endif
  /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if (IMR_MSK & ISTR_WKUP)
  if (wIstr & ISTR_WKUP & wInterrupt_Mask)
  {
    _SetISTR((u16)CLR_WKUP);
    Resume(RESUME_EXTERNAL);
#ifdef WKUP_CALLBACK
    WKUP_Callback();
#endif
  }
#endif
  /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if (IMR_MSK & ISTR_SUSP)
  if (wIstr & ISTR_SUSP & wInterrupt_Mask)
  {

    /* check if SUSPEND is possible */
    if (fSuspendEnabled)
    {
      Suspend();
    }
    else
    {
      /* if not possible then resume after xx ms */
      Resume(RESUME_LATER);
    }
    /* clear of the ISTR bit must be done after setting of CNTR_FSUSP */
    _SetISTR((u16)CLR_SUSP);
#ifdef SUSP_CALLBACK
    SUSP_Callback();
#endif
  }
#endif
  /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if (IMR_MSK & ISTR_SOF)
  if (wIstr & ISTR_SOF & wInterrupt_Mask)
  {
    _SetISTR((u16)CLR_SOF);
    bIntPackSOF++;

#ifdef SOF_CALLBACK
    SOF_Callback();
#endif
  }
#endif
  /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if (IMR_MSK & ISTR_ESOF)
  if (wIstr & ISTR_ESOF & wInterrupt_Mask)
  {
    _SetISTR((u16)CLR_ESOF);
    /* resume handling timing is made with ESOFs */
    Resume(RESUME_ESOF); /* request without change of the machine state */

#ifdef ESOF_CALLBACK
    ESOF_Callback();
#endif
  }
#endif
  /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/
#if (IMR_MSK & ISTR_CTR)
  if (wIstr & ISTR_CTR & wInterrupt_Mask)
  {
    /* servicing of the endpoint correct transfer interrupt */
    /* clear of the CTR flag into the sub */
    CTR_LP();
#ifdef CTR_CALLBACK
    CTR_Callback();
#endif
  }
#endif
} /* USB_Istr */

非常感谢!!
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2015-5-28 22:47:15 | 显示全部楼层
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

3

主题

24

帖子

0

精华

初级会员

Rank: 2

积分
56
金钱
56
注册时间
2014-7-14
在线时间
0 小时
 楼主| 发表于 2015-5-29 08:09:32 | 显示全部楼层
USB技术现状已经是很成熟的技术了,希望哪位大哥哥姐姐帮帮我!
回复

使用道具 举报

3

主题

24

帖子

0

精华

初级会员

Rank: 2

积分
56
金钱
56
注册时间
2014-7-14
在线时间
0 小时
 楼主| 发表于 2015-6-1 19:59:26 | 显示全部楼层
求解释   求顶
回复

使用道具 举报

3

主题

24

帖子

0

精华

初级会员

Rank: 2

积分
56
金钱
56
注册时间
2014-7-14
在线时间
0 小时
 楼主| 发表于 2015-6-4 18:22:36 | 显示全部楼层
是我太单纯了  USB的复杂元超出我的想象
回复

使用道具 举报

3

主题

24

帖子

0

精华

初级会员

Rank: 2

积分
56
金钱
56
注册时间
2014-7-14
在线时间
0 小时
 楼主| 发表于 2015-6-4 18:23:14 | 显示全部楼层
本帖最后由 追风 于 2010-12-4 17:30 编辑?
一、USB的“JoyStickMouse”例程结构分析
1、例程的结构
(1)底层结构
包括5个文件:usb_core.c(USB总线数据处理的核心文件),usb_init.c,usb_int.c(用于端点数据输入输入中断处理),usb_mem.c(用于缓冲区操作),usb_regs.c(用于寄存器操作)。它们都包含了头文件“usb_lib.h”。在这个头文件中,又有以下定义:
#include "usb_type.h"
#include "usb_regs.h"
#include "usb_def.h"
#include "usb_core.h"
#include "usb_init.h"
#include "usb_mem.h"
#include "usb_int.h"
usb_lib.h中又包含了七个头文件,其中usb_type.h中主要是用typedef为stm32支持的数据类型取一些新的名称。usb_def.h中主要是定义一些相关的数据类型。
还有一个未包含在usb_lib.h中的头文件,usb_conf.h用于USB设备的配置。
(2)上层结构
上层结构总共5个文件:hw_config.c(用于USB硬件配置)、usb_pwr.c(用于USB连接、断开操作)、usb_istr.c(直接处理USB中断)、usb_prop.c(用于上层协议处理,比如HID协议,大容量存储设备协议)、usb_desc.c(具体设备的相关描述符定义和处理)。
可见,ST的USB操作库结构十分清晰明了,我先不准备直接阅读源代码。而是先利用MDK的软件模拟器仿真执行,先了解一下设备初始化的流程。
2、设备初始化所做的工作
(1)Set_System(void)
这个是main函数中首先调用的函数,它位于hw_config.c文件中。它的主要功能是初始化时钟系统、使能相关的外围设备电源。
配置了JoyStickMouse所用到的5个按键,并且配置了两个EXTI中断,一个是用于把USB从挂起模式唤醒,还有一个用途未知。
(2)USB_Interrupts_Config();
这个是main函数中调用的第二个函数,它也位于hw_config.c文件中。主要功能是配置USB所用到的中断。
跟踪到代码中,主要设配置了USB低优先级中断和唤醒中断,又有一个EXTI中断功能未知。
(3)Set_USBClock()
这个是main函数中调用的第三个函数,它也位于hw_config.c文件中。它的功能是配置和使能USB时钟。
(4)USB_Init(void)
这个是main函数中调用的第四个函数,它也位于usb_init.c文件中。它初始化了三个全局指针,指向DEVICE_INFO、USER_STANDARD_REQUESTS和DEVICE_PROP结构体。
后面两个是函数指针结构体,里面都是USB请求实现、功能实现的函数指针。
void USB_Init(void)
{

pInformation = &Device_Info;

pInformation->ControlState = 2;


pProperty = &Device_Property;


pUser_Standard_Requests = &User_Standard_Requests;

/* Initialize devices one by one */


pProperty->Init();
}
这三个结构体都是与具体设备枚举和功能实现相关的,定义在usb_prop.c和usb_desc.c文件中。
DEVICE_PROP Device_Property?=

{

Joystick_init,

Joystick_Reset,

Joystick_Status_In,

Joystick_Status_Out,

Joystick_Data_Setup,

Joystick_NoData_Setup,

Joystick_Get_Interface_Setting,

Joystick_GetDeviceDescriptor,

Joystick_GetConfigDescriptor,

Joystick_GetStringDescriptor,

0,

0x40 /*MAX ACKET SIZE*/

};
USER_STANDARD_REQUESTS User_Standard_Requests?=

{

Joystick_GetConfiguration,

Joystick_SetConfiguration,

Joystick_GetInterface,

Joystick_SetInterface,

Joystick_GetStatus,

Joystick_ClearFeature,

Joystick_SetEndPointFeature,

Joystick_SetDeviceFeature,

Joystick_SetDeviceAddress

};
Usb_init()函数调用pProperty->Init()(实质上就是Joystick_init)完成设备的初始化。
上层程序调用下次函数是常规性的操作。而下层函数(usb_init相对于usb_prop是输入底层操作文件)调用上层文件函数我们称之为回调。
回调函数的意义在于同一种操作模式、提供不同的回调函数则可以实现不同的功能。Windows中处理消息,好像也用到了这种模式。
回调函数的实现方法是函数指针数组。这是指针的高级应用。
这是函数的代码:
void Joystick_init(void)
{/* Update the serial number string descriptor with the data from the unique
ID*/


Get_SerialNum();
//获取设备序列号,转变为unicode字符串

pInformation->Current_Configuration = 0;

/* Connect the device */

PowerOn();
//连接USB设备,实质是能让主机检测到了。

/* USB interrupts initialization */

_SetISTR(0);
/* clear pending interrupts */

wInterrupt_Mask = IMR_MSK;

_SetCNTR(wInterrupt_Mask); /* set interrupts mask */

bDeviceState = UNCONNECTED;
}
实质上,代码执行到这里,开发板已经可以响应主机发来的数据了。但我还是先把main()函数的代码看完吧。
(5)SysTick_Config();
这个函数调用主要是为程序中用到的精确延时作配置。
3、进入主循环
进入主循环的工作就两个:
Joystick_Send(JoyState())。
JoyState()用来获取按键的状态。
Joystick_Send(JoyState())用来把按键状态发到主机。当然这里真正的发送工作并不是由该代码完成的。它的工作只是将数据写入IN端点缓冲区,主机的IN令牌包来的时候,SIE负责把它返回给主机。
主要代码如下:

UserToPMABufferCopy(Mouse_Buffer, GetEPTxAddr(ENDP1), 4);
//从用户复制四个字节到端点1缓冲区,控制端点的输入缓冲区。

SetEPTxValid(ENDP1);?/* enable endpoint for transmission */
4、中断处理过程大致理解
(1)usb_istr()函数中的中断处理简单分析
有用的代码大概以下几段,首先是处理复位的代码,调用设备结构中的复位处理函数。

wIstr = _GetISTR();

if (wIstr & ISTR_RESET & wInterrupt_Mask)

{

_SetISTR((u16)CLR_RESET); //清复位中断


Device_Property.Reset();

}
处理唤醒的代码:

if (wIstr & ISTR_WKUP & wInterrupt_Mask)

{

_SetISTR((u16)CLR_WKUP);

Resume(RESUME_EXTERNAL);

}
处理总线挂起的代码:

if (wIstr & ISTR_SUSP & wInterrupt_Mask)

{

if (fSuspendEnabled) /* check if SUSPEND is possible */

{

Suspend();

}

else

{

/* if not possible then resume after xx ms */


Resume(RESUME_LATER);

}

/* clear of the ISTR bit must be done after setting of CNTR_FSUSP */

_SetISTR((u16)CLR_SUSP);

}
处理端点传输完成的代码,这段是最重要的,它调用底层usb_int.c()文件中的CTR_LP()函数来处理端点数据传输完成中断。

if (wIstr & ISTR_CTR & wInterrupt_Mask)

{

CTR_LP();?/* servicing of the endpoint correct transfer interrupt */

}
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2015-6-4 22:09:03 | 显示全部楼层
帮顶。。。。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

3

主题

24

帖子

0

精华

初级会员

Rank: 2

积分
56
金钱
56
注册时间
2014-7-14
在线时间
0 小时
 楼主| 发表于 2015-6-8 16:24:35 | 显示全部楼层
回复【7楼】正点原子:
---------------------------------
原子哥  你能不能告诉我怎么用USB向PC发送一个数据,就只单纯的发送接收一个数据  不涉及鼠标、键盘的也不做读卡器。就像串口一样单纯的发送数据
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2015-6-8 22:58:00 | 显示全部楼层
回复【8楼】午夜之孤魂:
---------------------------------
用usb虚拟串口吧。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

3

主题

24

帖子

0

精华

初级会员

Rank: 2

积分
56
金钱
56
注册时间
2014-7-14
在线时间
0 小时
 楼主| 发表于 2015-6-11 18:09:48 | 显示全部楼层
回复【9楼】正点原子:
---------------------------------
老是的要求就是用USB做  上位机也是写用USB接收
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2015-6-11 21:13:29 | 显示全部楼层
回复【10楼】午夜之孤魂:
---------------------------------
USB虚拟串口也是USB啊
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
9
金钱
9
注册时间
2016-7-23
在线时间
0 小时
发表于 2016-9-2 16:15:46 | 显示全部楼层
正在学习中,官网源代码没看大懂,论坛来查查资料
回复

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-30 03:10

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表