完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
发现问题
这段时间在学习FreeRTOS,今天移植成功后,写了2个任务。一个是LED每隔1s闪烁任务,另一个是使用UART4每隔100ms发送字符串任务。下载成功后,发现LED闪烁间隔不对,串口打印间隔时间也不对。当时就很纳闷了:RCC是按标准库的例子来配置的,FreeRTOS的系统节拍也是配置正确的,不可能会出现这种问题。后来,仔细排查,用示波器测试串口的波形发现一个问题:程序代码配置的是115200波特率,但实际输出波形算出来是38400,相差3倍。到这就开始怀疑RCC配置了,这时,我把MCO引脚打开,让其出示SYSCLK时钟,示波器上面反应的是72MH。接着又让它输出APB1CLK时钟,是正常的36MHz。调试到这里就感觉莫名其妙了,后来仔细查看RCC配置代码,发现官方例子是使用的25MHz的晶振,于是我换上25Mhz,重算了下分频系数等。烧写后,就变正常了。这里说下官网的例子模板 问题解决 STM32F107的时钟树 从图中可以看出,STM32F107的SYSCLK时钟有2条配置路线。第一条可以使用8M外部晶振来配置系统72MHz。第二条可以使用25M外部晶振来配置系统72MHz时钟。起出使用的是第一条路线,系统时钟也是正确配置成72MHz了,但是串口时钟是不正确的(其实是HSE_VALUE值没修改)。换成25MHz晶振,按第二条线路配置后,串口就正常了 官方RCC配置例子代码 void RCC_Configuration(void) { RCC_ClocksTypeDef RCC_ClockFreq; /* RCC system reset(for debug purpose) */ RCC_DeInit(); /* Enable HSE */ RCC_HSEConfig(RCC_HSE_ON); /* Wait till HSE is ready */ HSEStartUpStatus = RCC_WaitForHSEStartUp(); if(HSEStartUpStatus != ERROR) { /* Enable Prefetch Buffer */ FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); /****************************************************************/ /* HSE=25MHz, HCLK=72MHz, PCLK2=72MHz, PCLK1=36MHz */ /****************************************************************/ /* Flash 2 wait state */ FLASH_SetLatency(FLASH_Latency_2); /* HCLK = SYSCLK */ RCC_HCLKConfig(RCC_SYSCLK_Div1); /* PCLK2 = HCLK */ RCC_PCLK2Config(RCC_HCLK_Div1); /* PCLK1 = HCLK/2 */ RCC_PCLK1Config(RCC_HCLK_Div2); /* ADCCLK = PCLK2/4 */ RCC_ADCCLKConfig(RCC_PCLK2_Div6); /* Configure PLLs *********************************************************/ /* PPL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */ RCC_PREDIV2Config(RCC_PREDIV2_Div5); RCC_PLL2Config(RCC_PLL2Mul_8); /* Enable PLL2 */ RCC_PLL2Cmd(ENABLE); /* Wait till PLL2 is ready */ while (RCC_GetFlagStatus(RCC_FLAG_PLL2RDY) == RESET) {} /* PPL1 configuration: PLLCLK = (PLL2 / 5) * 9 = 72 MHz */ RCC_PREDIV1Config(RCC_PREDIV1_Source_PLL2, RCC_PREDIV1_Div5); RCC_PLLConfig(RCC_PLLSource_PREDIV1, RCC_PLLMul_9); /* Enable PLL */ RCC_PLLCmd(ENABLE); /* Wait till PLL is ready */ while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) {} /* Select PLL as system clock source */ RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); /* Wait till PLL is used as system clock source */ while (RCC_GetSYSCLKSource() != 0x08) {} } RCC_GetClocksFreq(&RCC_ClockFreq); /* Enable USART2 clock */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); /* Enable ETHERNET clock */ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_ETH_MAC | RCC_AHBPeriph_ETH_MAC_Tx | RCC_AHBPeriph_ETH_MAC_Rx, ENABLE); /* Enable GPIOs clocks */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE| RCC_APB2Periph_AFIO, ENABLE); /* Enable ADC1 clock */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); } 可以发现官方的例子代码是使用25MHz外部晶振来配置的系统时钟,我在官方的代码基础上修改我的8M晶振配置就不能正常运行 我修改的代码 void bsp_RCC_Init(void) { RCC_ClocksTypeDef RCC_ClockFreq; /* RCC system reset(for debug purpose) */ RCC_DeInit(); /* Enable HSE */ RCC_HSEConfig(RCC_HSE_ON); /* Wait till HSE is ready */ if(RCC_WaitForHSEStartUp() != ERROR) { /* Enable Prefetch Buffer */ FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); /****************************************************************/ /* HSE=8MHz, HCLK=72MHz, PCLK2=72MHz, PCLK1=36MHz */ /****************************************************************/ /* Flash 2 wait state */ FLASH_SetLatency(FLASH_Latency_2); /* HCLK = SYSCLK */ RCC_HCLKConfig(RCC_SYSCLK_Div1); /* PCLK2 = HCLK */ RCC_PCLK2Config(RCC_HCLK_Div1); /* PCLK1 = HCLK/2 */ RCC_PCLK1Config(RCC_HCLK_Div2); /* ADCCLK = PCLK2/4 */ RCC_ADCCLKConfig(RCC_PCLK2_Div6); /* Configure PLLs *********************************************************/ /* PPL2 configuration: PLL2CLK = (HSE / 2) * 10 = 40 MHz */ RCC_PREDIV2Config(RCC_PREDIV2_Div2); RCC_PLL2Config(RCC_PLL2Mul_10); /* Enable PLL2 */ RCC_PLL2Cmd(ENABLE); /* Wait till PLL2 is ready */ while (RCC_GetFlagStatus(RCC_FLAG_PLL2RDY) == RESET) {} /* PPL1 configuration: PLLCLK = (HSE / 1) * 9 = 72 MHz */ RCC_PREDIV1Config(RCC_PREDIV1_Source_HSE, RCC_PREDIV1_Div1); RCC_PLLConfig(RCC_PLLSource_PREDIV1, RCC_PLLMul_9); /* Enable PLL */ RCC_PLLCmd(ENABLE); /* Wait till PLL is ready */ while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) {} /* Select PLL as system clock source */ RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); /* Wait till PLL is used as system clock source */ while (RCC_GetSYSCLKSource() != 0x08) {} } } 上面我修改的代码使用后就出现了串口波特率错误的问题。在keil调试查看寄存器发现UART-》BRR的数值与理论计算的不一样。追溯USART_Init()函数配置过程,发现获取的PCLK1时钟频率不是36MHz。 仔细查询源头代码,发现HSE_VALUE定义的是25000000,这就导致图中RCC_GetClockFreq()函数获取的PCLK1_Frequency的值计算出错。所以需将HSE_VALUE改成8000000。 另一种办法,更换外部8M晶振为25M,修改RCC配置为官方代码,就可以正常运行 总结 STM32F107具有以太网、USB OTG 等网络设备,以太网使用MII接口时需要提供25MHz时钟,STM32F107使用外部25MHz晶振来作为时钟源是最好不过了,官方也推荐使用25MHz。使用8M晶振需要修改HSE_VALUE值为8000000,然后配置相应的PLL时钟了。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1786 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1622 浏览 1 评论
1089 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
730 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1680 浏览 2 评论
1942浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
739浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
576浏览 3评论
598浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
560浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-25 12:42 , Processed in 0.700759 second(s), Total 44, Slave 39 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号