#include #include #include "FreeRTOS.h" #include "audio_adc.h" #include "stm32f1xx.h" #include "task.h" #include "tusb.h" // System Clock Configuration void SystemClock_Config(void) { // Настройка на 72 MHz через HSE + PLL // 1. Включаем HSE (внешний кварц 8 МГц) RCC->CR |= RCC_CR_HSEON; while (!(RCC->CR & RCC_CR_HSERDY)); // 2. Настраиваем Flash: 2 цикла ожидания для 72 MHz FLASH->ACR = FLASH_ACR_LATENCY_2; // 3. Настраиваем PLL: 8 MHz * 9 = 72 MHz RCC->CFGR &= ~RCC_CFGR_PLLMULL; RCC->CFGR |= RCC_CFGR_PLLMULL9; RCC->CFGR |= RCC_CFGR_PLLSRC; // Источник PLL = HSE // 4. USB делитель: 72 MHz / 1.5 = 48 MHz RCC->CFGR &= ~RCC_CFGR_USBPRE; // USBPRE = 0 (делитель 1.5) // 5. Включаем PLL RCC->CR |= RCC_CR_PLLON; while (!(RCC->CR & RCC_CR_PLLRDY)); // 6. Переключаем системную частоту на PLL RCC->CFGR &= ~RCC_CFGR_SW; RCC->CFGR |= RCC_CFGR_SW_PLL; while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL); SystemCoreClock = 72000000; } // Audio Processing Callback // Буфер для отправки статистики через USB static char usb_tx_buffer[128]; static volatile uint32_t total_samples = 0; void audio_buffer_ready(audio_sample_t *buffer, uint32_t size) { // Эта функция вызывается из прерывания DMA // Не делать тяжелых операций здесь total_samples += size; // мин/макс значения uint16_t min_val = 4095; uint16_t max_val = 0; uint32_t sum = 0; for (uint32_t i = 0; i < size; i++) { uint16_t val = buffer[i]; if (val < min_val) min_val = val; if (val > max_val) max_val = val; sum += val; } uint16_t avg = sum / size; // Каждые 2 секунды отправляем статистику: каждый 100-й буфер static uint32_t report_counter = 0; report_counter++; if (report_counter >= 100) { report_counter = 0; snprintf( usb_tx_buffer, sizeof(usb_tx_buffer), "ADC Stats - Min: %4u, Max: %4u, Avg: %4u, Total samples: %lu\r\n", min_val, max_val, avg, total_samples); } } // FreeRTOS Tasks void usb_device_task(void *param) { (void)param; while (1) { tud_task(); vTaskDelay(pdMS_TO_TICKS(1)); } } void cdc_task(void *param) { (void)param; while (1) { if (tud_cdc_connected()) { // Отправка статистики если есть данные if (usb_tx_buffer[0] != '\0') { size_t len = strlen(usb_tx_buffer); if (tud_cdc_write_available() >= len) { tud_cdc_write(usb_tx_buffer, len); tud_cdc_write_flush(); usb_tx_buffer[0] = '\0'; // Очищаем буфер } } // Echo для тестирования if (tud_cdc_available()) { uint8_t buf[64]; uint32_t count = tud_cdc_read(buf, sizeof(buf)); tud_cdc_write(buf, count); tud_cdc_write_flush(); } } vTaskDelay(pdMS_TO_TICKS(10)); } } void led_task(void *param) { (void)param; while (1) { GPIOC->BSRR = GPIO_BSRR_BR13; // LED ON vTaskDelay(pdMS_TO_TICKS(100)); GPIOC->BSRR = GPIO_BSRR_BS13; // LED OFF vTaskDelay(pdMS_TO_TICKS(900)); } } // USB Reset void force_usb_reset(void) { RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; GPIOA->CRH &= ~GPIO_CRH_CNF12; GPIOA->CRH |= GPIO_CRH_MODE12_1; GPIOA->BSRR = GPIO_BSRR_BR12; for (volatile int i = 0; i < 500000; i++) __NOP(); GPIOA->CRH &= ~GPIO_CRH_MODE12; GPIOA->CRH |= GPIO_CRH_CNF12_0; } // Main int main(void) { SystemClock_Config(); // Настройка LED (PC13) RCC->APB2ENR |= RCC_APB2ENR_IOPCEN; GPIOC->CRH &= ~GPIO_CRH_CNF13; GPIOC->CRH |= GPIO_CRH_MODE13_1; force_usb_reset(); // Включаем USB RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; RCC->APB1ENR |= RCC_APB1ENR_USBEN; NVIC_SetPriority(USB_HP_CAN1_TX_IRQn, 6); NVIC_SetPriority(USB_LP_CAN1_RX0_IRQn, 6); NVIC_SetPriority(USBWakeUp_IRQn, 6); NVIC_EnableIRQ(USB_HP_CAN1_TX_IRQn); NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn); NVIC_EnableIRQ(USBWakeUp_IRQn); tusb_init(); // Инициализация Audio ADC if (!audio_adc_init(audio_buffer_ready)) { // Ошибка инициализации - быстро мигаем LED while (1) { GPIOC->BSRR = GPIO_BSRR_BR13; for (volatile int i = 0; i < 100000; i++); GPIOC->BSRR = GPIO_BSRR_BS13; for (volatile int i = 0; i < 100000; i++); } } // Запускаем захват аудио audio_adc_start(); // Создаем задачи FreeRTOS xTaskCreate( usb_device_task, "usbd", 256, NULL, configMAX_PRIORITIES - 1, NULL); xTaskCreate(cdc_task, "cdc", 256, NULL, configMAX_PRIORITIES - 2, NULL); xTaskCreate(led_task, "led", 128, NULL, 1, NULL); vTaskStartScheduler(); while (1); } // USB Interrupt Handlers void USB_HP_CAN1_TX_IRQHandler(void) { tud_int_handler(0); } void USB_LP_CAN1_RX0_IRQHandler(void) { tud_int_handler(0); } void USBWakeUp_IRQHandler(void) { tud_int_handler(0); }