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

发布者:MagicalSerenade最新更新时间:2024-08-09 来源: elecfans关键字:STM32工程  printf()函数  串口编程 手机看文章 扫描二维码
随时随地手机看文章

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


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


方法1:使用MicroLIB库



1.1 KEIL-MDK中的Use MicroLIB选项


在MDK开发环境中,


a012e421df6fcd6646a44e57360f1bd1_wKgaomVIoquAXF_hAADXx_I3Tu4388.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()函数的使用方法跟之前一样,运行结果:

091bafcd32639ac7d0b416f4db8a25e7_wKgaomVIoqyALM5pAACcrghcEKk336.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工程  printf()函数  串口编程 引用地址:STM32工程上printf()函数的方法实现

上一篇:STM32基于标准外设库的外部中断配置
下一篇:怎样调试STM32硬件错误HardFault

推荐阅读最新更新时间:2024-11-05 20:01

s3c2440学习之路-008 uart实现printf函数
1.基本原理 因为程序目前处于裸板阶段,只能输出字符串,没有C语言的printf函数可以调用。但是在调试程序时,想像C语言一样调用printf来调试,因此只能自己来实现了。 C语言中,printf函数的原型为: int printf(const char *format, ...); 1.1 可变参数 … 参数有2个, “const char *format” 和 “…”,这个“…”就是可变参数,下面先讲解一下如何识别这个可变参数。 参数的传递会顺序的放到栈里面,而printf函数可获取的参数只有 “const char *format” 和 “…”,不过format刚好指向了第1个参数的首地址,因此可以通过form
[单片机]
s3c2440学习之路-008 uart实现<font color='red'>printf</font><font color='red'>函数</font>
单片机使用printf函数的两种办法
今天就简单来说说怎么在51单片机中使用 printf 函数:包括使用自带的printf函数和自己动手写一个printf函数,再贴代码之前先介绍几个相关的知识,主要用于自己写printf函数。 ①C语言函数:vsprintf, 其原型为int vsprintf(char *string, char *format, va_list param);,作用为将param按格式format写入字符串string中,因此他可以用于将任何格式数据转化为字符串数据,比如把整数97转化为ASCII码的97的程序就像下面这样vsprintf(string, %d ,97),当然还有一点需要注意:在keil里面使用sprintf需要包含stdio.h
[单片机]
单片机使用printf函数进行串口打印输出
以前在使用keil编写51单片机程序的时候,经常使用printf函数打印输出一些关键的过程数据到电脑,方便监控程序的运行状况。最近使用IAR for MSP430 调试 MSP430G2553 程序的时候,发现了一些小问题,MSP430G2553单片机并没有按照我的预期输出数据到电脑。 带着疑惑我查看了keil的帮助文件里面的printf函数说明,原来printf函数最终是调用putchar函数来实现打印输出字符的。 putchar,该函数将制定的表达式的值所对应的字符输出到标准输出终端上。表达式可以是字符型或整型,它每次只能输出一个字符。我们来看keil标准函数库里的putchar函数的函数体。 根据说明提示,我在D:Keil
[单片机]
KeilC51中的库函数printf
在用keil仿真查看串口输出时,遇到了一个问题,代码如下: #include reg52.h #include stdio.h /* 为使用printf函数而加入*/ main() { SCON= 0x50;/*SCON:工作模式1,8-bit UART,允许接收*/ TMOD |= 0x20;/*TMOD:定时器T1,工作模式2, 8位自动重载方式*/ TH1= 0xf3;/*当波特率为2400时,定时器初值*/ TR1= 1;/*定时器T1开始运行*/ TI= 1;/*允许发送数据*/ printf( hello world ); } 上面代码调试运行后,串口不断输出 hello w
[单片机]
ubuntu下建立stm32开发环境:GCC安装以及工程Makefile建立
环境: ubuntu 13.10 stm32f103zet6 一 STM 32 GCC 安装 stm32 属于arm cortex-m系列thumb指令集,所以给arm用的arm-none-eabi就可以了,首先是下载 下载地址:https://launchpad .NET /gcc-arm-embedded/+download 下载其中的gcc-arm-none-eabi-version-linux.tar.bz2 解压到你知道的目录会产生 gcc-arm-none-eabi的文件夹 把该编译器添加到你的环境中:sudo gedit ~/.bashrc 在最后一行添加:因为我之前有添加过树莓派的编
[单片机]
51单片机实现printf函数
使用printf打印函数在调试的时候十分方便,因此在开发过程中首先实现此函数是非常有必要的。在经常整理网上资料后发现实现printf函数非常简单,首先添加stdio.h头文件,然后在串口函数中添加如下代码即可。 char putchar(char c) { Uart1_SendChar(c); return c; } 串口的发送函数可以使用这个: /*********************************************** *函数名称:Uart1_SendChar *功 能:串口1发送单个字符函数 *入口参数:Udat:欲发送的数据 *返 回 值:无 *备 注:无 ********
[单片机]
Keil MDK 中利用串口及c标准库函数printf为cortex-m3做调试输出
摘要: c标准库的printf是输出给显示器的,将printf函数进行修改,使其输出重定向至串口,就能实现目的。printf函数调用fputc函数完成实质输出单一字符的工作,因此将fputc函数修改使之完成串口单字符发送工作即可。 注: 本文方法性内容主要来自《Keil MDK环境下使用printf函数的解决方法》与《STM32串口使用Printf()函数问题》。除使用c标准库外,还可以使用keil mdk提供的microLib,在STM32串口使用Printf()函数问题》一文有介绍,另外,该文同时也提到如果使用c标准库函数,则要避免链接使用半主机模式的函数,retarge.c文件中的#pragma import(__use
[单片机]
工程STM32单片机学习手记(3):修修改改玩串口
  STM学习笔记——用定时器实现荧火虫灯   在第6篇笔记中,我用软件延时的方法实现了荧火虫,学了定时器,当然就要用一用定时器了,这里仍是用荧火虫灯为例。   用ST库所带的例子Tim中的TimBase为例来修改,这个例子的位置以及如何建立工程请参考第7篇笔记,这里就不再重复了,下面简述一下修改的过程。   (1) 由于我的板子上的灯是由PD8~PD11来控制的,因此,要将   void RCC_Configuration(void)   中的:   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); //打开GPIOC的时钟   改为   RCC_APB2Peri
[单片机]
<font color='red'>工程</font>师<font color='red'>STM32</font>单片机学习手记(3):修修改改玩串口
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

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

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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