起初是发现红牛的官方例程的延时程序跑在arduino上时间是不对的 。
void Delay_10ms (u32 nCount)
{
volatile int i;//volatile表示编译器不要优化这个变量,即使没有用到变量。否则这种空循序编译器直接就删掉忽略了
for (i=0;i<nCount*800;i++);
} 它的定义1ms 是空循环80次。跑起来明显跟实际时间对不上。抛开红牛官方例程的自己时序。至少证明板子arduino没有跑在72M上。用hal函数验证下。
参考 (59条消息) STM32获取时钟频率_米兰的无线电的博客-CSDN博客_stm32查看时钟频率
uint32_t a; a = HAL_RCC_GetSysClockFreq(); Serial.println(a);
发现是48M。尝试在修改、f——cpi发现没有用
但是在把board从genericSTM32F103ZE 改成 vccgnd_f103zet6可以跑在72M上。
查看C:\Users\kyo\.platformio\packages\framework-arduinoststm32\boards.txt 里板子的区别。发现vccgnd的相比通用103
# Generic F103ZETx
GenF1.menu.pnum.GENERIC_F103ZETX=Generic F103ZETx
GenF1.menu.pnum.GENERIC_F103ZETX.upload.maximum_size=524288
GenF1.menu.pnum.GENERIC_F103ZETX.upload.maximum_data_size=65536
GenF1.menu.pnum.GENERIC_F103ZETX.build.board=GENERIC_F103ZETX
GenF1.menu.pnum.GENERIC_F103ZETX.build.product_line=STM32F103xE
GenF1.menu.pnum.GENERIC_F103ZETX.build.variant=STM32F1xx/F103Z(C-D-E)(H-T)
多了一句
GenF1.menu.pnum.VCCGND_F103ZET6.build.variant_h=variant_{build.board}.h
看来是多设置了board的变量。
查看C:\Users\kyo\.platformio\platforms\ststm32\boards下json文件的区别 发现是通用f103多了这些
"hwids": [ [ "0x1EAF", "0x0003" ], [ "0x1EAF", "0x0004" ] ],
没有啥线索 继续找出现VCCGND的文件的地方。在这里发现了线索 C:\Users\kyo\.platformio\packages\framework-arduinoststm32\variants\STM32F1xx\F103Z(C-D-E)(H-T)
这些variant都是用来stm32对应arduino api 的针脚的名字或者函数功能的 。可以看到arduino api用到了gpio,iic,spi ,tim,serial功能 。开启其他stm32特有的功能就需要在pio。ini里加 -D来开启。
原来那一句GenF1.menu.pnum.VCCGND_F103ZET6.build.variant_h=variant_{build.board}.h 是对应在这的开发板自己定义的。h文件。查看跟通用f103的区别 。原来是 variant_VCCGND_F103ZET6_XXX.cpp里多了rcc的设置。对比下跟generic_clock.c的区别
通用的是 注意是启用了usb
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI_DIV2; RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL12;
8/2*12=48 如果不开usb,会是8/2-16=64
vccgnd
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
8*9=72
这时候就要看时钟树了
默认的genercic f103 用的是hsi 内部高速晶振,vccgnd用的是 hse 外部晶振信号 。如果纯粹选择内部晶振,内部晶振也是8M,pll最多能12倍。主频到64M 所以要跑72满速 必须用hse外部晶振 。内部晶振另一个问题是随着芯片工作升温频率就变了
这里也能看出来 单片机也能是能超频的。经过测试单片机程序80M可以跑,但是usb不正常了 。
知道了原理 那就把代码代码抄过来。 注意weak这个关键词。他的意思是如果在别的地方定义了同名的东西那别的地方的生效。
贴上代码
#include <Arduino.h> #include "Gpio.h" uint32_t a;
void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {}; RCC_PeriphCLKInitTypeDef PeriphClkInit = {};
/** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB buses 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_DIV2; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) { Error_Handler(); } PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC | RCC_PERIPHCLK_USB; PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6; PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_PLL_DIV1_5; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) { Error_Handler(); } }
void setup() {
SystemClock_Config(); LED_Init(); Serial.begin(9600); a = HAL_RCC_GetSysClockFreq(); }
void loop() { // put your main code here, to run repeatedly: for (int i = 0; i < 5; i++) { digitalToggle(LED1_GPIO_PIN + i); delay(1000); Serial.print("主频:"); Serial.println(a); } }
实验测试主频确实是72m usb正常。
标签:HAL,arduino,menu,OscInitStruct,开发板,pnum,PLL,cpu,RCC From: https://www.cnblogs.com/kyo413/p/16633678.html