OpenEdv-开源电子网

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

STM32F4系列,如何实现usb host和usb device动态切换

[复制链接]

10

主题

98

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
319
金钱
319
注册时间
2017-1-20
在线时间
51 小时
发表于 2017-2-8 15:10:10 | 显示全部楼层 |阅读模式
1金钱
第一次发帖,请大家解答多谢;
STM32F4系列,如何实现usb host和usb device动态切换;
硬件设计是共用一个usb;
软件实现host和device的动态切换;
单独的host 和 device都是ok的;
而host切换到device也是好的;
device切到host不行??
请问切换需要注意什么么?

最佳答案

查看完整内容[请看2#楼]

特此过来截贴; 关于usb otg 实现master(host)和 slave(device)的切换,简单总结下; 1 需要确认硬件环境,host 和device的通路,是不是DP(D+) ,DM(D-)复用,是要采用fs(full speed)还是hs (high speed),还是都使用等;DP &DM 的硬件控制信号上面,是否有上拉电阻,以及其他的控制逻辑;如果有,一定要梳理清楚,因为,device的识别需要DP上拉15k电阻到3.3v;而host识别,DP & DM 则不需要上下拉; 2 需要分别将hos ...
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

10

主题

98

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
319
金钱
319
注册时间
2017-1-20
在线时间
51 小时
 楼主| 发表于 2017-2-8 15:10:11 | 显示全部楼层
特此过来截贴;
关于usb otg 实现master(host)和 slave(device)的切换,简单总结下;
1 需要确认硬件环境,host 和device的通路,是不是DP(D+) ,DM(D-)复用,是要采用fs(full speed)还是hs (high speed),还是都使用等;DP &DM 的硬件控制信号上面,是否有上拉电阻,以及其他的控制逻辑;如果有,一定要梳理清楚,因为,device的识别需要DP上拉15k电阻到3.3v;而host识别,DP & DM 则不需要上下拉;
2 需要分别将host 和 device 都基于 stm32 的lib实现后,我们再讨论融合的事情;具体可以参考原子哥的实验,如 15# 楼;
3 都实现后,融合切换时,可以先参考 7# 的代码,再次先感谢了;
4 融合是,大致的思路是,
默认host即可;即初始化host,
host切换到device;流程为,关中断=》stop host=》关VBUS=》deinit host =》 init device =》init gpio(上拉DP)=》 start device;
device到host,也一样;关中断=》stop device=》deinit device =》 init host =》 init gpio(确认DP &DM信号无上下拉,无干扰)=》打开vbus =》 start host;
5 我在融合过程中,遇到了几个问题,
device的调试时,DP上拉电阻电源没有打开;
切换到host时,DP信号上拉没有关闭,因为我们使用GPIO打开上拉电源,所以,关闭device时,要配置这个GPIO输入高阻;同事host的vbus也一定要打开
usb device 和 host的识别,都是通过DP&DM信号完成,包括一些状态机的切换,所以一定要保证DP&DM的信号稳定,时序准确;
回复

使用道具 举报

3

主题

177

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1604
金钱
1604
注册时间
2016-1-28
在线时间
265 小时
发表于 2017-2-8 16:40:18 | 显示全部楼层
帮顶!!!
回复

使用道具 举报

10

主题

98

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
319
金钱
319
注册时间
2017-1-20
在线时间
51 小时
 楼主| 发表于 2017-2-8 17:38:40 | 显示全部楼层
现在发现的情况是  void OTG_FS_IRQHandler(void) 在动态切换的时候一直在触发;
请问 void OTG_FS_IRQHandler(void) 触发的条件是什么呢?和硬件的什么状态没有复位有关系么?
因为第一次初始化为host的时候,并没有void OTG_FS_IRQHandler(void)一直触发的问题;
回复

使用道具 举报

10

主题

98

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
319
金钱
319
注册时间
2017-1-20
在线时间
51 小时
 楼主| 发表于 2017-2-9 15:29:42 | 显示全部楼层
现在device到host的切换已经没有一直触发中断了;因为配置了device的D+不上拉;
但是切换到host后,发现usbh 一直枚举不成功;
if ( USBH_Get_DevDesc(phost, 8) == USBH_OK)的时候,一直是USBH_BUSY;
请大神帮忙解答;
回复

使用道具 举报

10

主题

98

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
319
金钱
319
注册时间
2017-1-20
在线时间
51 小时
 楼主| 发表于 2017-2-9 15:56:22 | 显示全部楼层
请大神支持啊;
备注下,硬件上host和device都采用OTG FS;只是软件上的切换实现;
回复

使用道具 举报

10

主题

98

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
319
金钱
319
注册时间
2017-1-20
在线时间
51 小时
 楼主| 发表于 2017-2-10 14:50:53 | 显示全部楼层
今天更换了一个u盘发现可以识别了,不过之前的还是不行,怀疑是兼容性的问题;请问谁知道usb host枚举不到,可能是兼容性的哪个问题么?
回复

使用道具 举报

30

主题

156

帖子

0

精华

高级会员

Rank: 4

积分
783
金钱
783
注册时间
2012-6-14
在线时间
206 小时
发表于 2017-2-10 15:56:00 | 显示全部楼层
[mw_shl_code=c,true]
void        usb_application(void)
{
    /*host*/
    if(!usb.host_device)
    {
        USBH_Init(&USB_OTG_Core,
#ifdef USE_USB_OTG_FS
                  USB_OTG_FS_CORE_ID,
#else
                  USB_OTG_HS_CORE_ID,
#endif
                  &USB_Host,
                  &USBH_MSC_cb,
                  &USBH_USR_cb);
                                /*使能管脚,控制为Vbus管脚供电*/
                                GPIO_ResetBits(GPIOC, GPIO_Pin_9);
                                GPIOA->MODER=(GPIOA->MODER&0xfff3ffff);
                                GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,0) ;
                                /*等待电平稳定*/
                                os_dly_wait(10);
    }
    /*device*/
    else        if(usb.host_device == 1)
    {
        USBD_Init(&USB_OTG_Core,
#ifdef USE_USB_OTG_FS
                  USB_OTG_FS_CORE_ID,
#elif defined USE_USB_OTG_HS
                  USB_OTG_HS_CORE_ID,
#endif
                  &USR_desc,
                  &USBD_CDC_cb,
                  &USBD_USR_cb);               
                       
                        /*使能管脚,控制不为Vbus管脚供电*/
                        GPIO_SetBits(GPIOC, GPIO_Pin_9);
                        GPIOA->MODER=(GPIOA->MODER&0xfff3ffff)|0x00080000;
                        GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_OTG1_FS) ;
                        /*等待电平稳定*/
                        os_dly_wait(10);
    }
}


/*****************************************************************
** 函 数 名:    TaskUSBCommu
** 输    入:    无
** 输    出:    无
** 功能描述:    USB的通讯任务
** 作    者:
** 修改日期:    2008-09-30 15:19
****************************************************************/
__task        void TaskUSBCommu(void)
{
    OS_RESULT result;
    __IO uint32_t i = 0;
    u16 event,TaskTime=0xffff;
    u8 init_num=0;
//        u8 vcp_connect = 0;        /*表示虚拟串口线第一次插入*/
       
        /*初始化*/
        usb.connect = 0;
        usb.host_device=1;
        usb.sec_time=0;
    if((ProgUpdateStr.RTXSTCHECK&0x80000020)==0x80000020)        ProgUpdateStr.RTXSTCHECK&=0xffffffdf;
    while(1)
    {
        ClrHardDog();
                RTXTASKCheck.TaskUSBCommu_RT=0;
        result = os_evt_wait_or (0xffff, TaskTime);
        RTXTASKCheck.TaskUSBCommu_RT=0x8258;        //10分钟
                if(result==OS_R_EVT)        //有事件发生
        {
            event=os_evt_get ();        //获取事件标志
            os_evt_clr (event, tID_TaskEventManage);                //清除已取出的事件
            /*当有事件发生的时候,下面的也只执行一次即可*/
            if(event&0x0001)        //秒轮询事件
            {
                /*每次插拔U盘或者转换状态的时候,都需要重新进行一次初始化工作*/
                if((init_num == 0))
                {
                    init_num = 1;
                    usb_application();
                }
                                usb.sec_time++;                               
                                /*-------------------USB host状态------------------------------------------*/
                if(!usb.host_device)
                {
                    /*插入U盘检测U盘已经插入*/
                    if((HCD_IsDeviceConnected(&USB_OTG_Core) == 1))
                    {
                        USBStatus=1;
                        usb.connect = 1;
                            /*USB已经连接上了*/
                                                while(usb.connect == 1)
                                                {
                                                        /* Host Task handler */
                                                        USBH_Process(&USB_OTG_Core, &USB_Host);                /*USB的周期轮询任务*/
                                                        if(HCD_IsDeviceConnected(&USB_OTG_Core) == 0)        break;
                                                }
                    }
                    /*U盘已经拔出*/
                    else if((HCD_IsDeviceConnected(&USB_OTG_Core) == 0)&&(usb.connect))
                    {
                        usb.connect = 0;
                        init_num = 0;
                        USBStatus=0;
                        usb.sec_time=0;
                        usb.host_device=1;
                    }
                }
                                /*---------------------------USB vcp状态---------------------------------------*/
                else if(usb.host_device == 1)
                {
                                        /*检测到了串口线插上了*/
                                        if((GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_9) == Bit_SET))
                                        {
                                                usb.connect = 1;                                               
                                        }
                                        /*未检出到串口线插上*/
                                        else if((GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_9) != Bit_SET))
                                        {
                                                if(usb.connect)
                                                {
                                                        usb.connect = 0;
                                                        init_num = 0;
                                                        usb.sec_time=0;
                                                }
                                                if(usb.sec_time>30)        //未检测到串口线,且非信息输出状态
                                                {
                                                        usb.host_device=0;        //切换为host
                                                        init_num = 0;        //重新初始化
                                                        InfoOutputMode=0;
                                                }
                                        }
                }
            }
        }
        else        //超时
        {

        }
    }
}[/mw_shl_code]
回复

使用道具 举报

30

主题

156

帖子

0

精华

高级会员

Rank: 4

积分
783
金钱
783
注册时间
2012-6-14
在线时间
206 小时
发表于 2017-2-10 15:58:39 | 显示全部楼层
这个是我当时操作device和host切换的时候做的主函数,你可以参考一下,使用的是供电电源来区分的device和host设备,实现其进行软切换,进入到不同的设备状态,自动切换没有办法,只能自己手动的进行切换的操作,因为开发板上面缺一根USB ID线
回复

使用道具 举报

10

主题

98

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
319
金钱
319
注册时间
2017-1-20
在线时间
51 小时
 楼主| 发表于 2017-2-10 16:33:04 | 显示全部楼层
嗯,我现在也是准备用软件手动切换;
目前的思路是在host 到device的时候,关闭host,打开device;
device到host的时候,关闭device,打开host;
现在单独关闭,打开 host或者device,功能都是正常的,可就是整合一起的时候,device到host的不行;
我最新的发现,感觉还是一些状态不对;
正常时;在host中断识别的时候,会先生成一个 Host port interrupt 再生成一个 Host channels interrupt;
而异常的时候,只有  Host port interrupt ;
请问了解么?
回复

使用道具 举报

10

主题

98

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
319
金钱
319
注册时间
2017-1-20
在线时间
51 小时
 楼主| 发表于 2017-2-10 16:33:45 | 显示全部楼层
jiafangshi 发表于 2017-2-10 15:58
这个是我当时操作device和host切换的时候做的主函数,你可以参考一下,使用的是供电电源来区分的device和ho ...

这个有需要配置usb id信号么?
我的理解usb id信号应该是对于MCU是输入的状况吧?
回复

使用道具 举报

30

主题

156

帖子

0

精华

高级会员

Rank: 4

积分
783
金钱
783
注册时间
2012-6-14
在线时间
206 小时
发表于 2017-2-10 16:43:49 | 显示全部楼层
tt朝花夕拾 发表于 2017-2-10 16:33
这个有需要配置usb id信号么?
我的理解usb id信号应该是对于MCU是输入的状况吧?

开发板上面的,都是4线的USB,5线的才带ID线,所以没有办法实现自动切换,就更不用说配置了,ID信号应该就是个高低电平信号吧,具体的我也没有深入去研究
回复

使用道具 举报

30

主题

156

帖子

0

精华

高级会员

Rank: 4

积分
783
金钱
783
注册时间
2012-6-14
在线时间
206 小时
发表于 2017-2-10 16:47:05 | 显示全部楼层
融合方面的问题,你可以参考我提供的主函数代码,我自己做的比较成熟的产品,比较稳定来着,只是前年做的,时间有点长了,有些地方不好详细的回答你
回复

使用道具 举报

10

主题

98

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
319
金钱
319
注册时间
2017-1-20
在线时间
51 小时
 楼主| 发表于 2017-2-10 17:08:00 | 显示全部楼层
感谢回复,
看了你的code,在host和device切换的时候需要对应重新初始化,另外就是vbus的控制了;
对吧?
我现在发现我device切换到host后,会有一个Handle Host Disconnect Interrupts 的中断出来,而正常的不会有;这个可能是哪个硬件信号不对么?
回复

使用道具 举报

10

主题

98

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
319
金钱
319
注册时间
2017-1-20
在线时间
51 小时
 楼主| 发表于 2017-2-10 17:34:11 | 显示全部楼层
jiafangshi 发表于 2017-2-10 16:47
融合方面的问题,你可以参考我提供的主函数代码,我自己做的比较成熟的产品,比较稳定来着,只是前年做的, ...

hi,jiafangshi;
请问你的设备上在做为device的时候,D+是否有上拉信号呢?
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2017-2-10 18:47:07 | 显示全部楼层
参考我们综合实验吧,综合实验的USB,可以做host(接U盘,接游戏手柄),也可以做device(接电脑)
自动切换(进入USB功能,就切换为Device,否则为Host)
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

10

主题

98

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
319
金钱
319
注册时间
2017-1-20
在线时间
51 小时
 楼主| 发表于 2017-2-13 09:02:45 | 显示全部楼层
正点原子 发表于 2017-2-10 18:47
参考我们综合实验吧,综合实验的USB,可以做host(接U盘,接游戏手柄),也可以做device(接电脑)
自动切 ...

好的,感谢原子哥;
多谢回复;
我这面已经参考了实验,初步已经实现,已经在整理验证了,
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-7-12 11:08

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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