历史上的今天
返回首页

历史上的今天

今天是:2025年08月12日(星期二)

正在发生

2018年08月12日 | STM32F105串口USART3无法发送数据或数据错误问题

2018-08-12 来源:eefocus

关于STM32系列的例程网上有很多,大部分是103系列,使用USART3,而且都是直接抄袭书上3.0的固件库或者转载别人的,所以很少又遇到类似我的问题,由于我用105系列芯片,开发板上只有USART3引出来重映射PD8、PD9,用的3.5的固件库,所以调试起来特别麻烦,没有可以运行的例子参考,网上down了一下都发现有问题,自己摸索半天终于发现了解决方案,觉得自己应该做出一点事情,为来源社会略尽微薄之力,所以决定开始写技术博客,一定要我自己原创的,发现别人一般发现不了问题的,绝大多数人转载的那种就算了。



其实103和105/107系列差别很小,只在建立工程的时候要稍微设置一下,有空专门写一篇建工程的,总的来说要使105的USART3要注意几个地方:



1.如果没法收发数据,通常情况是执行printf以后,串口助手只显示空字符串,查看HEX是00,首先要检查硬件,做嵌入式最关键的一点是,在怀疑自己代码之前先看硬件有没有连错,很多时候这样可以省不少事情,像我自己就是刚开始板子上面只连出了RXD和TXD,我就很天真地用3根杜邦线,和9针的电脑串口2、3、5连了,忘了还需要MAX232转电平,调代码搞半天浪费了时间没解决真正的问题,后面找到别的板子的MAX232模块,硬件问题解决。



2.这时候还不能收发数据,查了网上大部分资料,跟预期的一样,都是103的USART1,解决不了我的105的USART3,后面发现有人用USART3出现过类似的问题,常见的代码我就不写出来了,只说发现的关键的地方,USART_Configuration()里面我的代码是:


RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_AFIO, ENABLE);

GPIO_PinRemapConfig(GPIO_FullRemap_USART3, ENABLE); //USART3 remap 

RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); 

通常例子都会把RCC_APB2Periph_AFIO忽略掉,在用到“复用重映射”的时候要先使能AFIO的时钟,包括一些淘宝上信誉很好的开发板的所谓例子,我真心怀疑那些人有没有真正调试过,或者调试过3.0版本的,为何不更新3.5的。其次是GPIO_PinRemapConfig(GPIO_FullRemap_USART3, ENABLE)也会有人忽略,重映射必须要这句,最后是开时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE)新手一般会写成APB2,因为是直接COPY过来的,人家用USART1写的APB2当然没错,可是具体用那个USART自己还需要多去琢磨DataSheet到底要怎么设置。



3.这时候数据终于收到了,可是都是乱码,点开HEX,发现每当我发一个byte的数据,它都会显示3个,怎么调试都不对,后面还是发现网上有人同样问题,但是他解决了,最狗日的是他自己说解决了但是不把方案PO出来,你要不回复就算了,反正大家也不知道,既然回复了说自己解决了干嘛不把解决方案放出来,还美滋滋地说自己解决了,太2了这帮人。数据不对多半是波特率的问题,MCU上使用115200波特率,我尝试着降低sscom33串口助手的波特率,发现在38400波特率可以接受到正常数据,印证了网上有个人的说法,用3.5的库设置USART3会出错,直接操作寄存器就好了,有的人说降低波特率,不知道有没有人知道为何?难道真的是3.5的库有问题?


这个时侯要记住,当你要质疑别人的时候,自己先Debug一下,免得成了嘲笑历史的人最终被历史所嘲笑,你要相信那些写STM固件库的人大都是国外名牌大学电子工程/计算机毕业的博士,不是蓝翔的屌丝,固件库都是经过很多压力测试的,很少会出大错,最多是注释有点误导的地方。所以我仔细分析了一下,波特率不对,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,根据自己项目的需要的时钟是需要72MHz还是56MHz去跟踪到底是改SetSysClockTo72()还是改SetSysClockTo56(),在里面的条件编译那里:

#ifdef STM32F10X_CL

#if(0) //chenrunshe 20141127  modify

    /* 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

即原来默认选择25MHz晶振的用的是上面的PLL分频设置,但是实际项目用了8MHz,就要改相应的寄存器设置,反正最后要实现8MHz*9倍分频=72MHz才是标准的,于是我也条件编译一下#if(0)把原来的注释掉,改自己的,这时候最好写上修改信息,涉及到改固件库的,免得后来的人用你的工程文件出问题可以找到原来你修改过这里。修改完以后基本时钟正确了,再来回答之前那个疑问,其实固件库也没有错,网友说的直接改寄存器不用固件库也没有错,但是不能因为改寄存器对就能判断固件库错,其实大家都没错,是你自己错了而已,狗日天杀的谁不按默认晶振设计板子,非得搞跟人家默认不一样,又不标明出来,无语了。


推荐阅读

史海拾趣

顺芯(Everest-semi)公司的发展小趣事

在技术创新的同时,顺芯公司也注重市场拓展和品牌建立。公司积极参加国内外各类展会和论坛,与潜在客户和合作伙伴建立了广泛的联系。同时,顺芯公司还加强了与渠道商的合作,提高了产品的市场覆盖率。通过一系列的市场推广活动,顺芯公司的品牌知名度和美誉度逐渐提升。

ARCOL公司的发展小趣事

随着电子技术的飞速发展,ARCOL公司意识到只有不断创新才能在激烈的市场竞争中立于不败之地。因此,公司加大了对研发的投入,积极引进先进的生产设备和技术,不断推出创新性的产品。通过不断优化生产工艺和提升产品质量,ARCOL的产品在市场上逐渐占据了领先地位。

GHI Electronics公司的发展小趣事

随着业务的不断拓展,GHI Electronics开始实施全球化战略。公司积极寻求与全球合作伙伴的合作机会,共同开拓新市场。同时,GHI Electronics还在多个国家和地区设立了分支机构或研发中心,以便更好地服务当地客户并快速响应市场需求。这种全球化战略布局不仅增强了GHI Electronics的市场竞争力,也为其带来了更多的商业机会和发展空间。

ESTEK公司的发展小趣事

ESTEK公司深知产品质量对于企业发展的重要性。因此,公司从源头上把控原材料的质量,并在生产过程中严格执行质量管理体系标准。通过一系列严格的质量管控措施,ESTEK公司的产品质量得到了有效保障。在市场上,ESTEK公司的产品以高质量、高可靠性著称,赢得了广大客户的信赖和好评。

Dover Corporation公司的发展小趣事

Dover Corporation自上市以来,一直保持着持续盈利和向投资者发放红利的记录。公司凭借其强大的业务能力和稳健的财务状况,赢得了投资者的信任和支持。这一成绩的取得不仅彰显了Dover在业务运营方面的实力,也为其未来的发展奠定了坚实的基础。

请注意,以上故事框架仅为概述性质,具体细节和数据可能需要根据Dover Corporation的实际情况进行调整和补充。

APM Hexseal公司的发展小趣事

APM Hexseal的创始人Milton Morse是一位自学成才的工程师和杰出的创新者。他敏锐地洞察到电子行业对密封解决方案的迫切需求,于是开始设计原始的密封开关“靴子”。这种模制的覆盖物能够保护拨动开关和安装面板免受各种液体和气体的渗透。这一创新产品迅速取得了巨大的成功,为APM Hexseal公司奠定了坚实的基础。

问答坊 | AI 解惑

WINCE 上传文件

请问有谁知道用C++开发WINCE上传文件,应该选择用什么类! 在MFC中好像有什么CHttpConnection,还是那个CHttp.但在WINCE都好像不支持这些类…

查看全部问答>

求助:wince如何创建没有标题的窗口

RT~~~希望创建一个没有标题栏的窗口,createwindowex中可以通过参数设置么?没有找到好的方法~~~~求讨教~…

查看全部问答>

如何查看编译器中c库包含哪些函数

如题,比如有个函数atoi(字符串转化为整形)相应的头文件我也包含过了。 比如我在MDK编译器下测试该函数发现它的输出一直为0,这是不对的。 难道在c库中这个函数是个空的函数,应该是定义且声明过,要不然编译应该报错。 编译器的c库中有的函数包 ...…

查看全部问答>

ppcboot的编译问题

我在编译编译PPCBOOT的时候报错,提示:needed by \'.depend\'.请问这是什么问题?.depend是什么东西?请高手指教!!…

查看全部问答>

请问如何复制文件,使用SHFileOperation编译出错

复制文件,如果文件存在可设置覆盖或者不覆盖,目前使用SHFileOperation,编译出错,提示: error LNK2019: unresolved external symbol SHFileOperationW referenced in function \"public: __cdecl CLoadguxingApp::CLoadguxingApp(void)\" (??0CLoad ...…

查看全部问答>

美资半导体企业高薪招聘Sr.FAE(北京/上海/深圳)

本人猎头,现受某美资半导体企业高薪急急急招聘Sr.FAE一职,职责与要求如下: RESPONSIBILITIES:1.      Coordinate with Sales and FAE group to implement automotive business strategy.2.      Devel ...…

查看全部问答>

AVR入门最好教材,没有之一

很不错的。配合CVAVR3.12版本使用 …

查看全部问答>

关于FR5969的ADC采样及傅里叶算法

第一次做傅里叶 现在我想采集125HZ和225HZ的信号  那么我的采样频率和采样点数应该设置成多少啊?大家可以帮我算下吗?最好写个公式 谢谢了 …

查看全部问答>

比特流超过内存容量

下载到板子上flash,出现这个问题,求问具体原因 …

查看全部问答>