历史上的今天
返回首页

历史上的今天

今天是:2025年02月09日(星期日)

正在发生

2021年02月09日 | 基于S3C6410的ARM11学习(十八) 移植printf和scanf

2021-02-09 来源:eefocus

在学c语言的时候,经典的hello world程序,是通过printf函数实现了。有了这个函数,就可以随意的向屏幕打印数据了。在嵌入式中,其实也是可以用printf函数的,不过需要稍微麻烦点的移植。毕竟,在嵌入式中,所有实现的都要自己来弄,不在向PC程序开发一样,很多库函数,操作系统已经搞好,就用就行了。


首先,是要去下载能实现printf的源代码。这里用的是国嵌提供的。有两个文件夹,一个include,里面一些头文件,另外一个lib,实现printf的需要的额外的程序。

        clip_image006

        image

         image

中间的是inlcude中的头文件,下边是lib中的文件。


在lib中有一个Makefile。这个Makefile就是用来编译这些代码的,将所有的代码生成.o文件。供主函数链接使用。


可以发现,怎么没有printf.c文件了。那是因为这个printf.c文件是要我们自己来编写的。也就是printf函数和scanf函数要我们自己来写的,不过写的时候,可以使用lib中的一些函数来简化编写。

clip_image008

以上是printf的代码,使用一个数组来保存最终转化出来的字符串,大小是1024个字节。根据需要,这个大小可以更改。


函数的主要部分就是变参的处理。Printf是一个变参的函数,即函数的参数是不固定的。但是第一个参数是知道的,是一个字符串,通过这个字符串,可以知道有几个参数,从而在对这些参数进行处理。


va_start。提取字符串中的参数,即看%d,%c这些。知道有哪些参数。然后将这些参数保存在args中。


vsprintf。通过原始字符串和参数,转换后写入到新的字符串outbuf中。


va_end。这个是固定的。目前不知道有什么用。


通过上面三个函数,就实现了pritf的输入字符串的处理了。下面就调用putc函数,将转换后的字符串依次发送到串口即可了。

clip_image009

以上是scanf的函数。和printf函数类似,不过是先接收串口接收的数据,然后再对数据进行处理。


最后就是关键的地方了,代码写好了,怎么编译了。这个时候就要用到lib中提供的Makefile了。

clip_image011

这个Makefile实现了对lib文件下的各个c代码编译。最终生成lib.o供外部调用。${CFLAGS}这个是外部定义的变量。


剩下就要修改外部的总的Makefile了。

clip_image013

第一行:定义一些目标,就是一些.o文件。链接的时候,就链接这些文件。一个start.o,对应之前写的bootloader的start.S。main.o就对应main.c。device/dev.o这个对应外设驱动的代码集合,如LED,外部中断,串口等等这些。lib/lib.o这个就对应上面说到在lib下生成的lib.o,集合了printf和scanf。


第二行:定义一个参数CFLAGS,这个参数供调用的Makefile使用的。Makefile也是可以调用其他makefile的,这个时候,上层的makefile可以定义参数供下层的makefile使用。定义的这个参数是编译选项用的,-fno-builtin是说函数不是内建的函数,有可能我们写的函数和编译器的内建函数的名字是一样的。-I指的是搜索的头文件的目录,这里指定include目下,因为在实现printf的时候,有调用include中的头文件,所以需要告诉编译器这些头文件在什么地方。使用-I参数。$(shell pwd)这个是shell中的一些用法,调用pwd命令,返回的值就是这个$(shell pwd)的值。


第三行:将定义的参数CFLAGS导出去,这样外部的makefile就可以使用这个参数了。在lib下的makefile中是有用到这个参数的。


5-16行:实现编译链接。


18-19行: 执行device下的makefile。make –C device指的是跳转到device目录下去执行makefile。后面的all是具体执行makefile的目标

21-22行:和上面的一样,跳转到lib目录下,执行makefile命令,目标是all。

25-29行:伪目标,清除文件使用的。

clip_image015

以上是主目录的结构。只有main,makefile,链接脚本,start四个代码。其他代码都给弄到对应的文件下去了。

clip_image017

在device下,是各个外设驱动的代码。里面也有一个makefile。

clip_image019

以上是内容,就是将各个外设的代码给编译链接成dev.o文件,供外部使用。


这样,只需在主目录下,执行make命令。需要的.bit就生成了。是不是很方便了。

clip_image021

这样,就可以在程序中直接使用printf和scanf函数了。下面就来做一个简单的控制台。

clip_image023

上面的东西比较熟悉吧,下载程序,或者执行一些操作的时候,就有这个界面了。然后我们输入不同的选择,开发板就执行对应的操作。下面就来实现这个简单的串口控制台。


假设有5个选项。

1、  LED亮

2、  LED灭

3、  发送,hello world

4、  发送,weiqi7777

5、  发送,chinaaet

输入其他选项的话,就发送,WRONG。

clip_image025

执行的效果。

clip_image027

这是不是有点uboot的雏形了。当然这个控制台还做得比较简单。只有简单的几个命令。学到后面可以加更多的命令。


当输入不同的命令,会执行对应的操作。

         clip_image029

 这样,一个简单的控制台就做好了,同时也移植好了printf和scanf了。


对比STM32


在STM32中也是可以使用printf和scanf函数的。不过移植起来就简单多了,因为MDK将这个实现printf和scanf的库给提供了,我们只要使用即可,不过还是需要简单的修改,因为printf默认是输出到屏幕的,但是嵌入式中哪有屏幕,所以需要重定向到串口。


在STM32中,要加入stdio.h头文件,这个头文件是不是很熟悉啊,那是当然了,在c语言学习中,这个库可是基本每个程序都有了,因为里面包括了printf和scanf啊。

clip_image031

当然这个stdio头文件和我们学c语言的那个头文件不一样,这个是为嵌入式用的。在MDK中修改,选择使用MicroLIB。

clip_image033

最后,重写fputc函数。

clip_image035

因为printf函数,最终是调用fputc函数,将字符串发出去的,所以我们重写fputc函数,就将数据通过串口发送出去了。


至于scanf,目前没有用到过,所以还不知道。有知道的,麻烦请告知下。


以上,就实现了最重要的一个函数printf和scanf函数的移植了。对于移植,我们只需要把别人做好的代码拿来,稍微修改即可了。

推荐阅读

史海拾趣

三环(CCTC)公司的发展小趣事

面对全球化的市场趋势和竞争压力,三环(CCTC)公司制定了国际化战略和全球布局计划。公司将继续加大研发投入力度,提升自主创新能力;同时积极拓展国际市场,加强与国际知名企业的合作与交流;此外还将加强人才培养和引进工作,打造一支高素质、专业化的国际化团队。通过这些措施的实施,三环(CCTC)公司将不断提升自身实力和市场竞争力,为成为全球领先的电子企业而不懈努力。

DOMINANT公司的发展小趣事

在LED产业蓬勃发展的背景下,统明亮(DOMINANT)公司在2000年应运而生。它的诞生源于欧司朗(OSRAM)在马六甲工厂的分拆,加上马来西亚财团的加持,这家新公司迅速崭露头角。统明亮公司从成立之初就专注于LED技术的研发和生产,凭借其卓越的技术实力和创新能力,逐渐在电子行业中树立了良好的口碑。经过数年的不懈努力,统明亮在全球贴片式LED领域取得了领先地位,特别是在车用LED封装领域,其产品质量和技术水平均处于行业前列。

ACI [Applied Concepts, Inc.]公司的发展小趣事

ACI公司始终关注社会责任,积极参与公益事业。公司定期举办慈善活动,捐赠教育基金、扶贫资金等,为社会发展贡献力量。同时,ACI还加强了对员工的关爱和培训,为员工提供良好的工作环境和发展机会。通过这些举措,ACI公司不仅赢得了社会的广泛赞誉,还增强了员工的归属感和凝聚力。

请注意,这些故事是基于电子行业的一般性事实和发展趋势构建的虚构框架,并不特指ACI公司。如果您需要了解关于ACI公司的具体故事,建议您查阅相关资料或联系该公司以获取更准确的信息。

CONTEC公司的发展小趣事

随着国际市场的不断开拓,CONTEC公司于2012年在美国成立了分公司。这一举措使公司能够更好地了解国际市场需求,提高品牌知名度,并进一步扩大市场份额。美国分公司的成立标志着公司开始走向国际化发展道路,为公司的长远发展奠定了坚实基础。

Dailywell Electronics Co Ltd公司的发展小趣事

1997年3月,德利威电子股份有限公司正式成立,标志着其进入电子行业的起点。凭借创办人超过二十年的研发和生产经验,德利威电子从创立之初就注重产品质量和技术创新。在创立初期,德利威电子即获得了ISO 9002国际标准认证,显示出其对品质管理的高度重视。同时,其各系列产品也迅速通过了美国UL及加拿大CSA产品安规认证,进一步证明了其产品的安全性和可靠性。

乐鑫(espressif)公司的发展小趣事

乐鑫科技深知,物联网的发展离不开一个完善的生态系统。因此,公司积极构建了一个集硬件、软件、开源社区于一体的物联网生态系统。通过提供丰富的软件资源和技术支持,乐鑫科技为购买其硬件的客户实现了更优的使用体验,推动了物联网应用的普及和落地。

问答坊 | AI 解惑

keil下ARM的调试程序

uc/os的成功例程,也是从网上下的分享哈…

查看全部问答>

菜鸟参加电子设计大赛感悟!

本帖最后由 paulhyde 于 2014-9-15 08:54 编辑 今年暑假,我有幸参加了全国大学生电子设计大赛的培训.在学校提供的实验室里,我度过了紧张而又刺激的两个月时间.在有限的时间里,我学到了无穷的知识, 仿佛胜过两年的大学学业.在实验室,我感受到了前所 ...…

查看全部问答>

关于嵌入式

各位好! 我呢,以后想学嵌入式,但是对于嵌入式的学习路线还不是很明白。比如说哪些课程特别重要,主要学习什么语言还有就是中国高校目前对于该门课程制定的学习路线是什么,请各位参照自己的情况,给我指点迷津,谢谢!…

查看全部问答>

怎样利用数据分级来提高存储的准确率?

一、利用离线存储来提高设备的使用寿命。    存储在磁带设备上的数据一般可能很少用到。如企业需要对数据库等应用软件的数据进行备份。此时可以将数据备份到磁带设备上。根据惯例,一般一天24个小时这个磁带设备可能就只需要半个小时。 ...…

查看全部问答>

JTAG调试后怎么自动复位MCU

我在MDK下用Ulink2调试STM32,调试一次退出后,再进入调试模式就提示有问题,必须复位MCU才行。 烧写也是,烧写后必须复位MCU才能进入调试或者再烧写。 复位电路是参照的万利的板子,不知道要设置哪里。 谢谢了。…

查看全部问答>

求助M3程序下载问题

M3没法下载程序了  显示 Could not initialize target device!Please power cycle the board and try again!  哪位朋友知道为什么啊?非常感谢…

查看全部问答>

提示:你有新短消息,可又进不去,怎回事?

提示:你有新短消息,可又进不去,怎回事? 点击“您有新消息”,要求登录,因为已经登录,再登录不成,所以进不去。…

查看全部问答>

Sitara AM335x通用EVM硬件用户指南 CN_PDF

介绍 本文档介绍了AM335x评估模块(EVM)(TMDXEVM3358)这是基于德州仪器AM335x处理器的硬件体系结构。该EVM通常也被称为AM335x通用(GP)EVM。描述 AM335x通用EVM是一个独立的测试,开发和评估模块系统,它使开发人员能够编写周围的AM335x处理 ...…

查看全部问答>

nios2运行效率问题

搭建的CPU使用的时钟为100MHz,软件中连续使用IO_WR()直接对IO操作(赋值1和0)发现运行的时间不是10ns,而是1us左右,程序放在DDR中跑得,效率怎么会这么低,将程序放在片内跑,同样的程序,跑出来也不是10ns,而是接近200ns,相当于5M时钟在运行 ...…

查看全部问答>