工程从CAN接口方式转换为USART接口,IO口,时钟,中断,数据缓存等都做好了,但是USART接受数据老是不对,检查了波特率等设置,都没问题。
启动定时器测试,发现原因是芯片工作时钟频率不对。主频率根本就不是72M.而是比72M慢好几倍。
USART3_Configuration()应该不会出现问题,估计是时钟出现了问题,可是RCC_Configuration()我都是按照固件库函数来的怎么会出错呢?我从stm32f10x_rcc.h源头开始找起,发现默认初始化时钟函数SystemInit()里面有有问题,分频设置当然不会出现问题,问题出在时钟选择上,105/107属于互联网产品,Preprocessor Symbols用的是STM32F10X_CL,固件很多地方会针对这个STM32F10X_CL做出条件编译,其中SystemInit()默认选择外部时钟HSE,HSE的设置值HSE_VALUE在stm32f10x.h中宏定义默认是25MHz,我的板子用的是8MHz晶振,当然那里要改,所以我注释了原来,把8MHz加上。
#if !defined HSE_VALUE
#ifdef STM32F10X_CL
// #define HSE_VALUE ((uint32_t)25000000) /*!< Value of the External oscillator in Hz */
#define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */
#else
#define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */
#endif /* STM32F10X_CL */
#endif /* HSE_VALUE */
然后继续调试,发现还是不行,始终不对,然后继续跟踪SystemInit()函数,最后找到最终决定设置时钟频率的地方,stm32f10x_rcc.h的SetSysClockTo72(),默认选择最高72MHz,根据自己项目的需要的时钟是需要72MH,在里面的条件编译那里修改成这样:
#ifdef STM32F10X_CL
#if(0)
/* Configure PLLs ------------------------------------------------------*/
/* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */
/* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */
RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |
RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);
RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |
RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);
#else
/* PLL2 configuration: PLL2CLK = (HSE / 2) * 10 = 40 MHz */ //HSE = 8MHz
/* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */
RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |
RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);
RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV2 | RCC_CFGR2_PLL2MUL10 |
RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);
#endif
就可以了!!参考http://news.eeworld.com.cn/mcu/2018/ic-news081240692.html
问题2:IAP跳转到APP,老是不成功,一跳就死。中断、时钟什么的都关闭了,没有用。后来偶然发现另外一个工程可以,发现问题原因。
原来,跳转过来的APP工程中,代码是这样
main{
__enable_irq();
RCC_Configuration_107();
GPIO_Configuration();
I2C_Configuration();
CAN_Configuration((char *)ModID,0);//Connect to PC
// CAN2_Configuration((char *)ModID,0);//Connect to Module
NVIC_Configuration();
...
}
改成这样就可以了:
main
{
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x8003000);
RCC_Configuration_107();
GPIO_Configuration();
I2C_Configuration();
CAN_Configuration((char *)ModID,0);//Connect to PC
// CAN2_Configuration((char *)ModID,0);//Connect to Module
NVIC_Configuration();
__enable_irq();
}
增加一句话,并且在设置的NVIC后,再开启中断。就好了!!!!
原来失败的原因是,中断向量表没有及时设置地址!而是先开中断允许,又开了外设,然后才设置中断向量,中断一允许,外设的中断就要进入中断函数,这时相当于找错了中断入口地址!
原来如此!对于外设、中断、时钟、中断向量表原来还有这样一层先后顺序!!!!!