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

发布时间:2024-08-09  

针对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上了。


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>