// Hello World - Echo Test von S.F. webseite, aber mit dem neuen usb_vcp // https://www.mikrocontroller.net/topic/513315?goto=6623438#6623438 #include #include "stm32f0xx.h" #include "usb_vcp.h" // Delay some milliseconds void delay_ms(int ms) { //[ALEX] uint32_t start=systick_count; uint32_t start=HAL_GetTick(); while (HAL_GetTick()-startCR2, RCC_CR2_HSI48ON); while (!READ_BIT(RCC->CR2, RCC_CR2_HSI48RDY)); // switch SYSCLK to HSI48 MODIFY_REG(RCC->CFGR, RCC_CFGR_SW, RCC_CFGR_SW_HSI48); while (!READ_BIT(RCC->CFGR, RCC_CFGR_SWS_HSI48)); SystemCoreClock = 48000000; // Configure the USB clock source MODIFY_REG(RCC->CFGR3, RCC_CFGR3_USBSW, RCC_CFGR3_USBSW_HSI48); // testhalber die clk langsamer machen // SystemCoreClock = 24000000; // MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_CFGR_HPRE_DIV2); // clock teilen // Initialize system timer SysTick_Config(SystemCoreClock/1000); // Peripheral: Enable SYSCFG CLK SET_BIT(RCC->APB2ENR, RCC_APB2ENR_SYSCFGEN); while (!READ_BIT(RCC->APB2ENR, RCC_APB2ENR_SYSCFGEN)); // Peripheral: Enable Power Interface Clock SET_BIT(RCC->APB1ENR, RCC_APB1ENR_PWREN); while (!READ_BIT(RCC->APB1ENR, RCC_APB1ENR_PWREN)); // remap pins for USB SYSCFG->CFGR1 |= (SYSCFG_CFGR1_PA11_PA12_RMP); // Setup Clock Recovery System CRS to sync with USB SOF // enable CRS SET_BIT(RCC->APB1ENR, RCC_APB1ENR_CRSEN); while (!READ_BIT(RCC->APB1ENR, RCC_APB1ENR_CRSEN)); // reset CRS RCC->APB1RSTR |= (RCC_APB1RSTR_CRSRST); RCC->APB1RSTR &= ~(RCC_APB1RSTR_CRSRST); CRS->CFGR = 0 | // prescaler: no divider CRS_CFGR_SYNCSRC_1 | // source: USB SOF CRS_CFGR_SYNCPOL | // polarity: falling (47999U << CRS_CFGR_RELOAD_Pos) | // reload value (34 << CRS_CFGR_FELIM_Pos); // error limit value // reload value = f_{target} / f_{sync} - 1 // reload value = 48e6/1e3 - 1 = 47999 // error limit value: from cubeMx code generator // Adjust HSI48 oscillator smooth trimming MODIFY_REG(CRS->CR, CRS_CR_TRIM, (32 << CRS_CR_TRIM_Pos)); // trim value: from cubeMx code genererator // START AUTOMATIC SYNCHRONIZATION SET_BIT(CRS->CR, CRS_CR_AUTOTRIMEN | CRS_CR_CEN); // enable automatic trimming & frequency error counter /* // Use TIM14 to generate the reference CLK: 614kHz Signal to PB1 // enable TIM14 SET_BIT(RCC->APB1ENR, RCC_APB1ENR_TIM14EN); while (!READ_BIT(RCC->APB1ENR, RCC_APB1ENR_TIM14EN)); // reset TIM14 RCC->APB1RSTR |= (RCC_APB1RSTR_TIM14RST); RCC->APB1RSTR &= ~(RCC_APB1RSTR_TIM14RST); // divide 48MHz by 78 = 615.4kHz TIM14->ARR = 77; // period: 78 cycles TIM14->CCR1 = 39; // 50% duty cycle TIM14->CCMR1 = 0; // reset value MODIFY_REG(TIM14->CCMR1, TIM_CCMR1_OC1M, (0b110 << TIM_CCMR1_OC1M_Pos)); // PWM MODE 1 (mode 2 is just inverted) //SET_BIT(TIM14->CCMR1, TIM_CCMR1_OC1PE); // preload enable // wird nie geändert // enable Cap-Comp CH1 SET_BIT(TIM14->CCER, TIM_CCER_CC1E); TIM14->CR1 = 0; // reset value //SET_BIT(TIM14->CR1, TIM_CR1_ARPE | TIM_CR1_CEN); // auto reload & counter enable SET_BIT(TIM14->CR1, TIM_CR1_CEN); // counter enable // ensure TIM14CH1 -> PB1 is set to AF0 ! */ } void init_io() { // Enable USB SET_BIT(RCC->APB1ENR, RCC_APB1ENR_USBEN); // enable GPIOB CLK SET_BIT(RCC->AHBENR, RCC_AHBENR_GPIOBEN); while (!READ_BIT(RCC->AHBENR, RCC_AHBENR_GPIOBEN)); /* // einfach rüberkopiert -> PWM-Ausgang auf PB1 GPIO_InitTypeDef GPIO_InitStruct = {0}; //Configure GPIO pin : PB1 GPIO_InitStruct.Pin = GPIO_PIN_1; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; // alternate functino: TIM14 GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); */ } // Alternative: Redirect standard output to the USB port, e.g. from puts() or printf() int _write(int file, char *ptr, int len) { for (int i=0; iCFGR1 |= (SYSCFG_CFGR1_PA11_PA12_RMP); init_io(); UsbSetup(); SET_BIT(USB->BCDR, USB_BCDR_DPPU); // enable pullup USB while (1) { delay_ms(100); UsbStrOut("Hello World!\n"); // Send echo of received characters back while (UsbRxAvail()) { char c=UsbGetChar(); UsbCharOut(c); } delay_ms(900); } }