0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

STM32工程上printf()函数的方法实现

lcdz66 来源:雨飞工作室 2023-11-06 16:22 次阅读

针对STM32的串口编程,可以通过USART1向计算机的串口调试助手打印数据,或者接收计算机串口调试助手的数据。

下面,我们可以实现STM32工程上的printf()函数了,方便用于程序开发中调试信息的打印。

方法1:使用MicroLIB库

1.1 KEIL-MDK中的Use MicroLIB选项

在MDK开发环境中,

fc5fb8de-7c7c-11ee-939d-92fbcf53809c.jpg

MicroLib是缺省c库的备选库,它可装入少量内存中,与嵌入式应用程序配合使用,且这些应用程序不在操作系统中运行。MicroLib进行了高度优化以使代码变得很小,功能比缺省c库少,不具备某些ISO C特性,部分库函数的运行速度也比较慢,如内存拷贝函数memcpy()。 MicroLib与缺省C库之间的主要差异如下:

(1) MicroLib不符合 ISO C库标准。不支持某些ISO特性,并且其他特性具有的功能也较少。

(2) MicroLib不符合IEEE 754二进制浮点算法标准。

(3) MicroLib进行了高度优化以使代码变得很小。

(4) 无法对区域设置进行配置。缺省C区域设置是唯一可用的区域设置。

(5) 不能将main() 声明为使用参数,并且不能返回内容。

(6) 不支持stdio,但未缓冲的stdin、stdout和stderr除外。

(7) MicroLib对C99函数提供有限的支持。 (8) MicroLib不支持操作系统函数。 (9) MicroLib不支持与位置无关的代码。

(10) MicroLib不提供互斥锁来防止非线程安全的代码。 (11) MicroLib不支持宽字符或多字节字符串。

(12) 与stdlib不同,MicroLib不支持可选择的单或双区内存模型。MicroLib只提供双区内存模型,即单独的堆栈和堆区。

MicroLib提供了一个有限的stdio子系统,它仅支持未缓冲的stdin、stdout和stderr,那么也就是说勾选了Use MicroLib选项后,在代码工程中就可以使用printf()函数咯?然而事实并非如此,这样直接使用printf()函数,其打印的字符串最终不知道打印到何处。我们要做的是将调试信息打印到USART1中,所以需要对printf()函数所依赖的打印输出函数fputc()重定向(MicroLib中的printf()函数打印操作依赖fputc() )。

1.2 重定向fputc函数

在MicroLib的stdio.h中,fputc()函数的原型为:

int fputc(int ch, FILE* stream)

此函数原本是将字符ch打印到文件指针stream所指向的文件流去的,现在我们不需要打印到文件流,而是打印到串口1。基于前面的代码:



#include 
int fputc(int ch, FILE* stream)
{
//USART_SendData(USART1, (unsigned char) ch);
//while (!(USART1->SR & USART_FLAG_TXE));
USART_SendChar(USART1, (uint8_t)ch);
return ch;
}
注意:需要包含头文件stdio.h,否则FILE类型未定义。

勾选了Use MicroLib选项,重定向fputc()函数后,我们就可以在工程代码中使用printf()函数了:


int main(void)
{
USART_Configuration();
printf("
stm32f103rct6
");
printf("
Cortex-M3
");
while (1);
return 0;
}
printf()函数的使用方法跟之前一样,运行结果:

fc8bc5c8-7c7c-11ee-939d-92fbcf53809c.jpg

方法2:不使用MicroLIB库

2.1 半主机模式

半主机模式是ARM的一种机制,实现将来ARM应用程序代码的输入/输出请求传送至运行着调试器的主机。例如,设置使用半主机模式下的ARM应用程序,可以使用printf()和scanf()来使用主机的显示器和键盘,而不需要在ARM系统上搭配显示器和键盘。

半主机通过一组定义好的软件指令(如SVC)来实现的,这些指令在程序控制下产生异常,ARM应用程序调用半主机对应的异常处理函数,然后调试代理处理该异常。

第二段话感觉理解起来有点模糊,但是第一段还是懂它在讲什么的。一般的ARM应用程序中并不需要半主机操作,在这里为确保ARM应用程序中没有链接MicroLib的半主机相关函数,我们要取消ARM的半主机工作模式。

2.2 实现代码

在工程中加上如下代码:



#pragma import(__use_no_semihosting)


struct __FILE {
int handle;
};


FILE __stdout;


_sys_exit(int x)
{
x = x;
}


int fputc(int ch, FILE *f){
while((USART1->SR&0X40)==0);
USART1->DR = (u8) ch;
return ch;
}
上面的代码摘自正点原子的范例程序,具体每一行的意义目前也不大清楚。这样操作后,在不使用MicroLib的前提下,仍能使用printf()函数将调试信息打印到USART1上了。







审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • STM32
    +关注

    关注

    2239

    文章

    10673

    浏览量

    348770
  • 串口调试
    +关注

    关注

    2

    文章

    263

    浏览量

    24473
  • printf函数
    +关注

    关注

    0

    文章

    30

    浏览量

    5827
  • USART1
    +关注

    关注

    0

    文章

    9

    浏览量

    3617

原文标题:使用KEIL-MDK开发STM32时,两种printf()函数重定向的方法

文章出处:【微信号:雨飞工作室,微信公众号:雨飞工作室】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    实现STM32工程printf()函数

    在前面学习了STM32的串口编程,通过USART1向计算机的串口调试助手打印数据,或者接收计算机串口调试助手的数据,接下来我们可以实现STM32工程
    发表于 08-24 06:53

    如何实现STM32工程printf()函数

    如何实现STM32工程printf()函数
    发表于 12-01 06:55

    printfstm32实现方法是什么?

    printfstm32实现方法是什么?
    发表于 12-01 07:52

    STM32 Printf函数利用标准库实现方法是什么?

    STM32 Printf函数利用标准库实现方法是什么?
    发表于 12-02 06:13

    基于STM32printf串口数据输出

    方法适用于 STM32实现了使用printf等标准C流函数输出数据的办法,极大的减少了输出 串口数据 时所需要做的数据处理。
    发表于 06-21 07:51 2w次阅读
    基于<b class='flag-5'>STM32</b>的<b class='flag-5'>printf</b>串口数据输出

    实现重定向printf()和scanf() 函数案例分析

    名字的函数时,优先采用用户编写的函数,这样用户就可以实现对库的修改了。为了实现重定向printf()和scanf()
    发表于 06-23 08:26 8606次阅读
    <b class='flag-5'>实现</b>重定向<b class='flag-5'>printf</b>()和scanf() <b class='flag-5'>函数</b>案例分析

    STM32中使用printf打印串口数据的实现原理及方法

    的寄存器中,便可以实现使用printf()函数STM32串口上输出数据的功能。 盘点一下实现print
    的头像 发表于 07-22 11:12 1.4w次阅读

    STM32单片机IAR环境下重定向printf函数

    STM32单片机IAR环境下重定向printf函数一、引言在项目开发中,使用printf函数通过串口打印调试信息,需要对
    发表于 12-03 10:36 15次下载
    <b class='flag-5'>STM32</b>单片机IAR环境下重定向<b class='flag-5'>printf</b><b class='flag-5'>函数</b>

    STM32使用串口重定向系统printf函数输出时出现一初始化或使用printf函数系统卡死的原因及解决办法

    STM32使用串口重定向系统printf函数输出时出现一初始化或使用printf函数系统卡死的原因及解决办法在
    发表于 12-09 10:06 12次下载
    <b class='flag-5'>STM32</b>使用串口重定向系统<b class='flag-5'>printf</b><b class='flag-5'>函数</b>输出时出现一初始化或使用<b class='flag-5'>printf</b><b class='flag-5'>函数</b>系统卡死的原因及解决办法

    STM32F103串口1 printf函数实现

    要怎么使用呢?能不能将这个函数和串口1对应起来,当然是有方法的。  下面就通过代码来演示一下如何在串口1上使用printf()函数的功能。void uart_init(u32 boun
    发表于 12-20 19:37 1次下载
    <b class='flag-5'>STM32</b>F103串口1 <b class='flag-5'>printf</b><b class='flag-5'>函数</b>的<b class='flag-5'>实现</b>

    STM32单片机基础09——重定向printf函数到串口输出的多种方法

    本文详细的介绍了如何重定向printf输出到串口输出的多种方法,包括调用MDK微库(MicroLib)的方法,调用标准库的方法,以及适用于 GNUC 系列编译器的
    发表于 12-27 19:22 8次下载
    <b class='flag-5'>STM32</b>单片机基础09——重定向<b class='flag-5'>printf</b><b class='flag-5'>函数</b>到串口输出的多种<b class='flag-5'>方法</b>

    stm32单片机串口使用printf及u3_printf

    无论是在51单片机还是在stm32,默认printf串口都是串口一。使用printf的时候头文件为&amp;quot;stdio.h&amp;quot;,但是一些
    发表于 12-27 19:24 1次下载
    <b class='flag-5'>stm32</b>单片机串口使用<b class='flag-5'>printf</b>及u3_<b class='flag-5'>printf</b>

    stm32printf函数的串口输出代码

    stm32f103串口一与串口二printf函数输出、本人是萌新,因项目需要特意配置了该段代码,不喜勿喷,纯属个人笔记。对于串口的代码网上也是很多,无非是配置问题,该代码
    发表于 12-28 19:10 13次下载
    <b class='flag-5'>stm32printf</b><b class='flag-5'>函数</b>的串口输出代码

    STM32中串行通讯中printf函数的使用

    由于最近使用到了串口屏,而它与STM32之间的连接是通过单片机之间的串行通讯实现的,具体而言我利用printf函数给串口屏发送数据,而printf
    发表于 12-29 19:31 6次下载
    <b class='flag-5'>STM32</b>中串行通讯中<b class='flag-5'>printf</b><b class='flag-5'>函数</b>的使用

    STM32printf函数重定向方法

    MicroLib提供了一个有限的stdio子系统,它仅支持未缓冲的stdin、stdout和stderr,那么也就是说勾选了Use MicroLib选项后,在代码工程中就可以使用printf()函数咯?
    的头像 发表于 07-10 16:22 1094次阅读
    <b class='flag-5'>STM32</b>的<b class='flag-5'>printf</b><b class='flag-5'>函数</b>重定向<b class='flag-5'>方法</b>