jqchris 发表于 2018-9-19 11:25:00

关于F4的 USB虚拟串口

在F407上调试成功的虚拟串口程序,在F446上跑不起来!问题就是不能识别驱动,446上面D+上面都没有高电平出现(F4内部是集成1.5K上拉电阻的)。
我使用的是标准外设库,USB外设库是USB_HOST-Device_LibV2.1和V2.2。很多网友说用CubeMX一配置就配置出来,是的没错,我也试了。证明了我的硬件是OK的!
但是我已经用标准外设库把整个工程写了百分之九十,如果就是因为虚拟串口驱动装不上去,换成HAL库那就太耽误项目进度了!
贴代码分析原因吧。
如下为主函数。
USB_OTG_CORE_HANDLEUSB_OTG_dev;

int main(void)
{
SystemInit();

USBD_Init(&USB_OTG_dev,
            USB_OTG_FS_CORE_ID,
            &USR_desc,
            &USBD_CDC_cb,
            &USR_cb);

while(1)
{
   
}

}      宏是这么定义的!      STM32F40_41xxx
      USE_USB_OTG_FS如果要换成F446的话直接改成STM32F446xx。
      对于两个不同的宏,预编译就只能在SystemInit();里面了。
      先看时钟配置吧!

#if defined(STM32F40_41xxx) || defined(STM32F427_437xx) || defined(STM32F429_439xx) || defined(STM32F469_479xx)
/* #define DATA_IN_ExtSRAM */
#endif /* STM32F40_41xxx || STM32F427_437x || STM32F429_439xx || STM32F469_479xx */

#if defined(STM32F427_437xx) || defined(STM32F429_439xx) || defined(STM32F446xx) || defined(STM32F469_479xx)
/* #define DATA_IN_ExtSDRAM */
#endif /* STM32F427_437x || STM32F429_439xx || STM32F446xx || STM32F469_479xx */

#if defined(STM32F410xx) || defined(STM32F411xE)
/*!< Uncomment the following line if you need to clock the STM32F410xx/STM32F411xE by HSE Bypass
   through STLINK MCO pin of STM32F103 microcontroller. The frequency cannot be changed
   and is fixed at 8 MHz.
   Hardware configuration needed for Nucleo Board:
   ?SB54, SB55 OFF
   ?R35 removed
   ?SB16, SB50 ON */
/* #define USE_HSE_BYPASS */

#if defined(USE_HSE_BYPASS)   
#define HSE_BYPASS_INPUT_FREQUENCY   8000000
#endif /* USE_HSE_BYPASS */   
#endif /* STM32F410xx || STM32F411xE */
   
/*!< Uncomment the following line if you need to relocate your vector Table in
   Internal SRAM. */
/* #define VECT_TAB_SRAM */
#define VECT_TAB_OFFSET0x00 /*!< Vector Table base offset field.
                                 This value must be a multiple of 0x200. */
/******************************************************************************/

/************************* PLL Parameters *************************************/
#if defined(STM32F40_41xxx) || defined(STM32F427_437xx) || defined(STM32F429_439xx) || defined(STM32F401xx) || defined(STM32F469_479xx)
/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */
#define PLL_M      8
#elif defined(STM32F412xG) || defined (STM32F446xx)
#define PLL_M      8
#elif defined (STM32F410xx) || defined (STM32F411xE)
#if defined(USE_HSE_BYPASS)
#define PLL_M      8   
#else /* !USE_HSE_BYPASS */
#define PLL_M      8
#endif /* USE_HSE_BYPASS */
#else
#endif /* STM32F40_41xxx || STM32F427_437xx || STM32F429_439xx || STM32F401xx || STM32F469_479xx */

/* USB OTG FS, SDIO and RNG Clock =PLL_VCO / PLLQ */
#define PLL_Q      7

#if defined(STM32F446xx)
/* PLL division factor for I2S, SAI, SYSTEM and SPDIF: Clock =PLL_VCO / PLLR */
#define PLL_R      7
#elif defined(STM32F412xG)
#define PLL_R      2
#else
#endif /* STM32F446xx */

#if defined(STM32F427_437xx) || defined(STM32F429_439xx) || defined(STM32F446xx) || defined(STM32F469_479xx)
#define PLL_N 336
//#define PLL_N 360
/* SYSCLK = PLL_VCO / PLL_P */
#define PLL_P      2
#endif /* STM32F427_437x || STM32F429_439xx || STM32F446xx || STM32F469_479xx */

#if defined (STM32F40_41xxx)
#define PLL_N336
/* SYSCLK = PLL_VCO / PLL_P */
#define PLL_P      2
#endif /* STM32F40_41xxx */

#if defined(STM32F401xx)
#define PLL_N      336
/* SYSCLK = PLL_VCO / PLL_P */
#define PLL_P      4
#endif /* STM32F401xx */

#if defined(STM32F410xx) || defined(STM32F411xE) || defined(STM32F412xG)
#define PLL_N      400
/* SYSCLK = PLL_VCO / PLL_P */
#define PLL_P      4   
#endif /* STM32F410xx || STM32F411xE */

/******************************************************************************/
再看SystemInit();函数
/* FPU settings ------------------------------------------------------------*/
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
    SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2));/* set CP10 and CP11 Full Access */
#endif
/* Reset the RCC clock configuration to the default reset state ------------*/
/* Set HSION bit */
RCC->CR |= (uint32_t)0x00000001;

/* Reset CFGR register */
RCC->CFGR = 0x00000000;

/* Reset HSEON, CSSON and PLLON bits */
RCC->CR &= (uint32_t)0xFEF6FFFF;

/* Reset PLLCFGR register */
RCC->PLLCFGR = 0x24003010;

/* Reset HSEBYP bit */
RCC->CR &= (uint32_t)0xFFFBFFFF;

/* Disable all interrupts */
RCC->CIR = 0x00000000;

#if defined(DATA_IN_ExtSRAM) || defined(DATA_IN_ExtSDRAM)
SystemInit_ExtMemCtl();
#endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */
         
/* Configure the System clock source, PLL Multiplier and Divider factors,
   AHB/APBx prescalers and Flash settings ----------------------------------*/
SetSysClock();

/* Configure the Vector Table location add offset address ------------------*/
#ifdef VECT_TAB_SRAM
SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
#else
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
#endif
}    再看SetSysClock();static void SetSysClock(void)
{
/******************************************************************************/
/*            PLL (clocked by HSE) used as System clock source                */
/******************************************************************************/
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;

/* Enable HSE */
RCC->CR |= ((uint32_t)RCC_CR_HSEON);

/* Wait till HSE is ready and if Time out is reached exit */
do
{
    HSEStatus = RCC->CR & RCC_CR_HSERDY;
    StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));

if ((RCC->CR & RCC_CR_HSERDY) != RESET)
{
    HSEStatus = (uint32_t)0x01;
}
else
{
    HSEStatus = (uint32_t)0x00;
}

if (HSEStatus == (uint32_t)0x01)
{
    /* Select regulator voltage output Scale 1 mode */
    RCC->APB1ENR |= RCC_APB1ENR_PWREN;
    PWR->CR |= PWR_CR_VOS;

    /* HCLK = SYSCLK / 1*/
    RCC->CFGR |= RCC_CFGR_HPRE_DIV1;
   
    /* PCLK2 = HCLK / 2*/
    RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;   
   
    /* PCLK1 = HCLK / 4*/
    RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;   //到这里没有区别


#if defined(STM32F40_41xxx) || defined(STM32F427_437xx) || defined(STM32F429_439xx) || defined(STM32F401xx) || defined(STM32F469_479xx)   
    /* Configure the main PLL */
    RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |
                   (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
#endif /* STM32F40_41xxx || STM32F401xx || STM32F427_437x || STM32F429_439xx || STM32F469_479xx */

#ifdefined(STM32F412xG) || defined(STM32F446xx)
    /* Configure the main PLL */
    RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |
                   (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24) | (PLL_R << 28);//这里不过是PLL_R给I2S使用
   
#endif /* STM32F412xG || STM32F446xx */   
   
    /* Enable the main PLL */
    RCC->CR |= RCC_CR_PLLON; //把主PLL开启,那么给USB的第二个PLL的相关配置在哪
    //答:主PLL出来时钟之后,直接去配置Q就出来给USB_OTG_FS使用,并不存在开启第二个PLL。
    /* Wait till the main PLL is ready */
    while((RCC->CR & RCC_CR_PLLRDY) == 0)
    {
    }
   
#if defined(STM32F427_437xx) || defined(STM32F429_439xx) || defined(STM32F446xx) || defined(STM32F469_479xx)
    /* Enable the Over-drive to extend the clock frequency to 180 Mhz */
    PWR->CR |= PWR_CR_ODEN;
    while((PWR->CSR & PWR_CSR_ODRDY) == 0)
    {
    }
    PWR->CR |= PWR_CR_ODSWEN;
    while((PWR->CSR & PWR_CSR_ODSWRDY) == 0)
    {
    }                                           //这里只是针对了电源
    /* Configure Flash prefetch, Instruction cache, Data cache and wait state */
    FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;
#endif /* STM32F427_437x || STM32F429_439xx || STM32F446xx || STM32F469_479xx */

#if defined(STM32F40_41xxx)|| defined(STM32F412xG)   
    /* Configure Flash prefetch, Instruction cache, Data cache and wait state */
    FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;
#endif /* STM32F40_41xxx|| STM32F412xG */

    /* Select the main PLL as system clock source */
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
    RCC->CFGR |= RCC_CFGR_SW_PLL;

    /* Wait till the main PLL is used as system clock source */
    while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);
    {
    }
}
else
{ /* If HSE fails to start-up, the application will have wrong clock
         configuration. User can add here some code to deal with this error */
}

/* STM32F40_41xxx || STM32F427_437xx || STM32F429_


jqchris 发表于 2018-9-19 11:31:26

       我现在也只能怀疑是时钟的问题了!因为对于同样是F4的单片机来说,相关OTG_FS无论是引脚配置,时钟,中断向量表还是寄存器肯定是相同的!
       我甚至打印对照相关OTG_FS的寄存器发现并没有什么大的区别。
      

馒头弟 发表于 2018-9-20 09:12:36

时钟没啥问题诶,你用的高速还是全速

wenyangzeng 发表于 2018-9-20 09:53:53

F407的主频是168MHZ,F446主频是180MHZ.楼主要检查一下F446系统时钟分频后的USB时钟频率是否正确。

xiaoshen-372360 发表于 2018-9-20 13:33:40

过来学习学习
页: [1]
查看完整版本: 关于F4的 USB虚拟串口