基于clion的野火stm32标准库开发(printf打印已解决)

发布者:HarmoniousDream最新更新时间:2025-11-05 来源: bilibili关键字:printf打印 手机看文章 扫描二维码
随时随地手机看文章

1、教程说明

        最近花了一些时间,重新学习野火stm32f4的1.8标准库视频,跟着火哥一起用keil5软件敲代码,还是用不习惯,就想着用clion折腾下标准库开发,顺便学习下重温cmake的用法。

        这里只说明基于nucleo f4板子标准库开发的一些注意事项,使用野火教程的模板。

        下面是成品图:

1_成品图


2、教程准备

        这里参考稚晖君的教程,把clion的环境配好。

        配置CLion用于STM32开发 【优雅の嵌入式开发

        以及网页链接up主的标准库  网页链接


3、注意使用

    (1)外设驱动库文件

        这里我们参考标准外设库STM32F4xx_DSP_StdPeriph_Lib_V1.8.0里面的SW4STM32的模板工程,找到f446RE的工程并打开,SW4STM32同样是GCC环境的。

2_SW4STM32

        参考STM32F4xx_StdPeriph_Driver中的c文件调用,把f446RE不支持的外设删除,相对应的头文件也要删除。然后复制到clion工程里面。

3_删除无用c文件

    (2)Cmake文件修改

        1)第一个是头文件路径修改,就是需要用到的头文件,都要把路径写到cmake文件里面,编译器才能识别到。剩下的板级支持包分开写,就是为了跟着火哥上课学习外设时,另外一个一个加,比如LED的头文件。

        这里我们说下这个,(复制跳转)include_directories的用法

https://cmake.org/cmake/help/latest/command/include_directories.html?highlight=include_directories#command:include_directories

5_头文件命令

        2)第二个是c文件,以及启动文件路径的修改,把相关源文件和启动文件链接到编译器。使用GLOB命令使用通配符模式匹配来查找文件。file(GLOB SOURCES "src/*.*")使用这个通配符,表示所有".*"结尾的文件都会包含到这个SOURCES变量。他的用法也可以参考上面的教程网址,在快速搜索哪里搜索关键词file或者GLOB。

6_源文件命令

        3)第三个是宏定义文件的修改。我们在使用keil5编译工程前都会添加两个头文件。

7_宏定义使用

        而在clion上面,当我们用cubemx生成代码的时候,我们会发现,在stm32f4xx.h这个头文件上面,添加两个宏定义#define USE_STDPERIPH_DRIVER 和 #include STM32F446xx。编译后,编译器会提示该头文件STM32F446xx重定义了,经过一番研究发现。原来在cubemx软件和clion生成代码的时候,已经在cmake文件上添加了相关的宏定义。我们按照图片修改就是了。

8_宏定义的使用

        下面是add_definitions命令的使用方法和解释。

9_宏定义的意思

(3)Printf串口打印

        1)主要问题

        我们一般使用printf打印log,用来调试程序。要解决的问题是将printf的输出重定向到串口,然后通过串口将数据发送出去。但是clion的printf打印函数,并不像keil5那样,他们对应的函数并不相同。所以用野火的keil5重定向函数,在clion并没有输出,反而会编译报错。

        通过查看编译器的报错提示,原来printf打印函数对应的底层调用函数,并没有定义。但是查看1.8标准库的SW4STM32例子,也没有看到相关的重定义函数和文件。进而找到HAL库的printf例子,发现工程里多了一个syscalls.c文件--该文件已经定义好了相关的函数。我们把这个文件复制到工程的User目录下,并编译,报错已经解决。

10_printf重定义

        虽然报错已经解决但是printf还是没有输出。与在keil5中重定义fputs()函数不一样,在GCC编译器中(stm32标准库)需要重定义的是__io_putchar(int ch)。

11_对应函数弱定义

         为什么可以确定是这个函数呢?我们通过查看stm官方的stm32f4的1.8标准库中的例程查到printf的使用方式。我们要学会使用官方的例程和文档,这种方式是一手途径,效率是最高的。

12_文件解释

        所以我们按照官方的做法,在串口定义的.c文件哪里,添加重定义函数。

13_添加相对重定义函数

        接着重写函数,这两个函数的写法是和野火教程的一模一样的。

14_野火格式printf

        到这里为止,我们一般就可以愉快的玩耍printf函数了,但是还有一些小问题要解决。


        2)次要问题

        第一个问题--printf打印不加n,没有输出。

        解决方式,在#include "bsp_debug_usart.h"开头包含头文件#include <stdio.h>,然后在串口初始化时调用setvbuf(stdout, NULL, _IONBF, 0),设置buffer缓存为0,这样一有数据就发送,不然会等到缓存满或有回车换行符才发送。如果没有这句,你的printf又没n,log就会打不出来。

15_解决问题1

        第二个问题,半主机模式,(这个模式存疑,网上很多教程)

        我没有禁用半主机模式,也是可以正常使用printf的,不知道这个原因是什么。

        半主机重定向    http://www.mculover666.cn/posts/2251182441/

        hal库的设置    https://shawnhymel.com/1873/how-to-use-printf-on-stm32/

        下面的内容都是存疑的:

        printf 函数使用了半主机模式,所以直接使用标准库会导致程序无法运行,因此必须提前告知编译器不使用半主机模式--在syscalls.c文件下添加其中一个。

        第一种方法(参考):

        不使用半主机模式 /* 告知连接器不从C库链接使用半主机的函数 */

        #pragma import(__use_no_semihosting)

        第二种方式:

        #if !defined(OS_USE_SEMIHOSTING) //如果定义了OS_USE_SEMIHOSTING

        中间是代码

        #endif //#if !defined(OS_USE_SEMIHOSTING)

16-解决问题2

        个人结论:既然官方例程在SW4STM32例子中和syscalls.c文件中没有撰写这个,还有本人在GCC环境编译也没有出现问题。我觉得这个可以暂时忽略掉,就是不用考虑半主机问题。


(4)测试效果

        printf输出没有问题,浮点数打印也没有问题。

结果


(4)F446RET6工程文件

链接:https://pan.baidu.com/s/1310oFNVDqsHYru2nMPkjHA

提取码:w747

cut-off

17_结尾图



关键字:printf打印 引用地址:基于clion的野火stm32标准库开发(printf打印已解决)

上一篇:STM32驱动WS2812B
下一篇:使用Rust开发STM32嵌入式程序入门教程

推荐阅读最新更新时间:2026-03-19 19:50

《SLAM导航机器人基础》第三章:单片机与STM32:串口Printf打印实验
3.5节串口Printf打印实验 我们在上一节内容里使用了串口,但输出的数据是十六进制数据,难以阅读,在我们想使用串口打印调试信息时并不合适,在这种情况下,我们可以使用printf函数。 a.实验准备:USB转串口模块,ST-Llink下载器,CHEAPX机器人控制板 b.实验目的:使用STM32串口进行printf打印 c.相关知识点: printf函数的使用,主要需要学习输出格式,详情在程序中介绍。我们在必应或百度上输入搜索关键字“printf输出格式”,就可以获得很多相关介绍。 d.编程及运行 (1)基于3.5节串口收发实验的程序进行修改,增加如下函数,即能使用printf()函数。 //重定
[单片机]
《SLAM导航机器人基础》第三章:单片机与<font color='red'>STM32</font>:串口<font color='red'>Printf</font><font color='red'>打印</font>实验
如何使用STM32单片机实现printf打印调试信息
在写单片机程序时我们一般喜欢使用printf来通过串口打印调试信息,但这个函数是不可以直接使用的,必须做点对库函数的改动。 STM32M CUBE是ST官方提供的库以及初始化工具,很好很强大,但是在UART方面值提供了如下函数: HAL_StatusTypeDefHAL_UART_Transmit(UART_HandleTypeDef*huart,uint8_t*pData,uint16_tSize,uint32_tTimeout); HAL_StatusTypeDefHAL_UART_Receive(UART_HandleTypeDef*huart,uint8_t*pData,uint16_tSize,uint32_tT
[单片机]
【GD32H757Z海棠派开发板使用手册】第九讲 USART-printf打印实验
9.1实验内容 通过本实验主要学习以下内容: 串口简介 GD32H757串口工作原理 使用printf打印信息 9.2实验原理 9.2.1串口简介 串口,从广义上看,指所有串行通信接口,比如RS232、RS422、RS485、SPI、IIC等。串行通讯是指仅用一根接收线和一根发送线就能将数据以位进行传输的通讯方式。和串行通讯相对应的是并行通讯,并行通信指一个传输接口可以传输8个bit即一个byte(有时甚至更多),虽然串行通信比并行通信慢,但是串口可以在仅仅使用两根线的情况下就能实现数据的传输。 对于GD32H757来说,串口一般特指USART(通用同步异步收发器 )和UART(通用异步收发器 )。USART/UART提供
[单片机]
【GD32H757Z海棠派<font color='red'>开发</font>板使用手册】第九讲 USART-<font color='red'>printf</font><font color='red'>打印</font>实验
STM32如何通过 printf 打印出浮点数
一、问题 使用 IAR 开发 STM32,发现无法通过 printf 重定向到串口打印出浮点数。代码如下: 输出结果如下: 可见,浮点数部分无法正常显示。 二、解决方法 这是由于 IAR 默认选择的 printf 库不支持浮点数的的输出。可在设置选项中修改。如下:默认使用 small,改为 auto 即可。 三、备注 在不修改设置的情况下,尝试过如下两种代码解决。一种是通过 sprintf 将浮点数转换成字符串输出,另一种是分解整数和小数部分,分别输出。第一种方法也是不可行的,只有分解可以。 代码如下: /* * cyang 2018/2/27 * mcu printf float value */ #include 《
[单片机]
STM32F103程序调用printf打印串口数据
程序开发过程中调试必不可少,一种简单直接的调试方式是使用串口发送数据,并使用串口助手进行观测。以前使用MSP430做项目时也同样使用printf打印数据,所以现在想在stm32 上实现。 通常串口发送单字节库函数:USART_SendData(USART1, (uint8_t) ch);对显示小数等数据比较复杂,如果能够直接使用C语言 stdio.h中的printf直接输出就可以省去大部分格式输出转化时间。下面将介绍如何调用printf打印串口数据。 建立USART.C和USART.H两个文件,分别编写串口设置程序与头文件 USART.C中需要添加如下代码: 对printf进行重定向; USART.H中需要添加如下代码
[单片机]
STM32F103程序调用<font color='red'>printf</font><font color='red'>打印</font>串口数据
野火STM32学习笔记(构建库函数模型第五节课)
解释初始化函数是怎么运作的 第四节课我们已经了解了如何通过固件库编程的方式初始化一个GPIO口,配置其速度,工作模式等等,这一切都有一个“幕后黑手”就是那一个一百多行的GPIO_Init()函数。我们再来一睹一下芳容: 第一部分 我们从第一行开始看: 大括号内第一二行都是存放这些变量的初始值,可以不用太在意。再看下面模式配置那边,第一行注释是把模式的低四位存入变量currentmode,这样做的目的是取出这些值(与0x0F相与取值),再判断它的bit4位是几(如下图),是0则是输入,是1则是输出,判断方式也很简单,即赋值给currentmode的值和0x10(二进制00010000)与运算,看看是不是0就知
[单片机]
STM32F103串口配置,并且使用printf进行打印
首先要配置串口时钟: // USART1 clock enable RCC_APB2PeriphClockCmd( RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE); 然后再配置端口,在配置串口,再使能即可。 void USART1_Init(void) { /////// config the gpio GPIO_InitTypeDef GPIO_InitStructure; /* PA9 USART1_Tx */ GPIO_InitStructure.GPIO_Pin =
[单片机]
STM32的UART读写及printf打印
0.摘要 本文以STM32F1x系列单片机为例,主要介绍了串口的初始化、串口中断、接收/发送、串口调试等内容,也顺带讲到中断分组、半主机模式以及微库MicroLIB。 1.串口初始化 串口初始化主要包括对IO、USART和中断的初始化。根据STM32F1x手册RM0008的P166,USART在全双工模式下,发送口TX要配置成复用推挽输出,接收口RX要配置成浮空输入或上拉输入。此外,本文不使用USART的硬件流控制,所谓硬件流控制就是通过加入额外的引脚(RTS和CTS)来控制数据的收发过程,在数据传输之前确认收发双方均准备好才进行通信,用于防止接收缓冲区满而导致的数据丢失问题。 /********************
[单片机]
<font color='red'>STM32</font>的UART读写及<font color='red'>printf</font><font color='red'>打印</font>
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved