#c #embedded #stm32 #system-clock
#c #встроенный #stm32 #системные часы
Вопрос:
Мой первоначальный проект, созданный на CubeMX, работал на частоте 32 МГц. Поскольку я пытаюсь реализовать АЦП с частотой 80 МГц, я решил увеличить системную частоту до 100 МГц. Изменения, которые я внес в исходный код, находятся в main.c:
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
/** Configure the main internal regulator output voltage
*/
if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48|RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSI48State = RCC_HSI48_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 12;
RCC_OscInitStruct.PLL.PLLN = 50;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
if (HAL_RCC_OscConfig(amp;RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(amp;RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
{
Error_Handler();
}
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_I2C1|RCC_PERIPHCLK_USB
|RCC_PERIPHCLK_ADC;
PeriphClkInit.I2c1ClockSelection = RCC_I2C1CLKSOURCE_PCLK1;
PeriphClkInit.AdcClockSelection = RCC_ADCCLKSOURCE_PLLSAI1;
PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_HSI48;
PeriphClkInit.PLLSAI1.PLLSAI1Source = RCC_PLLSOURCE_HSE;
PeriphClkInit.PLLSAI1.PLLSAI1M = 6;
PeriphClkInit.PLLSAI1.PLLSAI1N = 20;
PeriphClkInit.PLLSAI1.PLLSAI1P = RCC_PLLP_DIV2;
PeriphClkInit.PLLSAI1.PLLSAI1Q = RCC_PLLQ_DIV2;
PeriphClkInit.PLLSAI1.PLLSAI1R = RCC_PLLR_DIV2;
PeriphClkInit.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_ADC1CLK;
if (HAL_RCCEx_PeriphCLKConfig(amp;PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
}
Я только что изменил PLLM и PLLN для настройки на 100 МГц. Теперь, когда я отлаживаю программу в системном регистре, я вижу, что:
SYST_CSR = 7 SYST_RVR = 99999
Итак, я думаю, что галочки правильно показывают 100 МГц. Я не уверен, насколько это правильно, но, скажем, для выполнения простой строки:
i_flag=1;
требуется 7 циклов в соответствии с SYST_CVR-> CURRENT.
Учитывая некоторые проблемы с синхронизацией с АЦП, я полагаю, что я неправильно установил системные часы, и они по-прежнему 32 МГц. Есть идеи, верны ли мой код и проверки?
Комментарии:
1. В большинстве микроконтроллеров вам необходимо настроить состояния ожидания флэш-памяти при выходе за пределы ~ 50 МГц. Я не вижу этого в вашем коде, но, возможно, это обрабатывается оборудованием или драйверами? Нужны ли состояния ожидания в этой части и кто отвечает за их настройку?
2. (если вы неправильно определяете состояния ожидания, код обычно сразу же выходит из строя, программа зависает или выходит из строя)
3. Спасибо за ваше руководство! Я понятия не имел об этом. Уже установил его на 4 WS, поскольку это значение для моего процессора. Просто вставил его в конец SystemClock_Config(). Я все еще не уверен, что все работает правильно. Теперь для выполнения вышеупомянутой команды требуется 10 циклов. Я могу восстановить исходные 32 МГц или переделать CubeMX с чистой настройкой 100 МГц.
4. К сожалению, эти вредоносные библиотеки от поставщика в основном вредны. Вместо этого я бы рекомендовал поискать исходный код (на Github и т.д.), Который не использует ST HAL, но выполняет настройку часов вручную. Также могут быть примечания к приложению от ST. Если все остальное не удается, всегда есть руководство.