在嵌入式中printf 这种功能强大的函数可谓是c语言库函数的中的一股清流!也就是太好用了吧!今天分享的例程有 stm32f4ZG 和 cc2530f256,这个两款芯片的移植例程和移植教程!相信你看完后也可以移植到别的芯片去!

  • 使用的keil版本为:5.21a
  • IAR for 8051 version 为 10.10.1

可能会因为有些版本不同配置就略有所不同!(f4)串口1:

(f4)串口2:

下面这个是TI 的cc2530(就先跑着寄存器版本的吧,协议栈里头配置差不太多!):

为啥要移植呢!相信学过实时操作系统的都有所了解,有个叫互斥信号量的东西!就是为了防止同一时间内有两个寄存器(那十来个寄存器,不是指外设!)在访问同一块内存!这个很严重的,可能会导致程序死机,或者卡在了某个死循环里面!

我们所使用的 printf 就是首先通过 vsprinf 对我们传进来的参数进行格式化,我们传进去多少数据,他按照我们传进来的格式,格式化后统统存放在一个buf里,如果我们定义了重定向,它就会把这个buf发送至你要发送的地方!

想象一下,如果在某个系统中有一个线程在vsprintf里面运行,突然有一个任务级别比他高的任务把它运行的时间抢了过去!而任务优先级高的任务也在printf里面使用了那个buf,那就会产生上述的问题!

那就意味着我们所使用的 printf 存在不安全问题!当然我们在系统中可以通过临界保护区来处理,也可以通过信号量等等处理!

但是目前有一个线程安全的函数,摆在你面前,就问你用不用?

那我们的上边 printf_u1 它是怎么处理的呢?毫无疑问,看代码就能知道,它是直接发送的,也就是说你传进来的每一个参数它都会顺手就发送出去(当然要看你配置),它的数据将不会存放在一个 buf 里边,在发送。这就是他给力的地方了!

keil移植printf

首先,我们到文章的末尾获取到源代码后,打开 keil 软件, 点击 project > Options for… 就能打开一下页面:

点击 C/C++,选择c99标准。到此为止编译器配置完毕!

下面来配置代码部分,打开头文件为printf.h:

1,添加这个两个文件的路径还有头文件,如果不懂可以搜搜!2,点击图片上面的printf_ 去它定义的地方,我们要做出一定的修改。

来到这里之后我们可以看到_vsprintf 这个代码里面最复杂的就是这一串函数了!

//我们只需要关心第一个参数即可!它是一个函数指针
static int _vsnprintf(out_fct_type out, char* buffer, const size_t maxlen, const char* format, va_list va)
//指向了一个参数为下图的函数,返回值为void
typedef void (*out_fct_type)(char character, void* buffer, size_t idx, size_t maxlen);

我们只要修改这_putchar 里面的内容即可。参数二是我加上去的为了区分不同的串口类型,有多少个串口就的写多少个_out_char 这样的函数(这个是我的方法):

static inline void _out_char(char character, void* buffer, size_t idx, size_t maxlen)
{(void)buffer; (void)idx; (void)maxlen;if (character) {_putchar(character,1);}
}

上图是串口1的。再来看看串口2的:

int printf_u2(const char* format, ...)
{va_list va;va_start(va, format);char buffer[1];const int ret = _vsnprintf(u2_out_char, buffer, (size_t)-1, format, va);va_end(va);return ret;
}
//注意vsprintf第一参数
static inline void u2_out_char(char character, void* buffer, size_t idx, size_t maxlen)
{(void)buffer; (void)idx; (void)maxlen;if (character) {_putchar(character,2);}
}

而_putchar 就是我们数据最终流向的地方了!我是这样写的。

void _putchar(char character,char sw)
{// send char to console etc.if(sw == 1){while((USART1->SR&0X40)==0);//循环发送,直到发送完毕USART1->DR = (u8) character;}if(sw == 2){while((USART2->SR&0X40)==0);//循环发送,直到发送完毕USART2->DR = (u8) character;}if(sw == 3){while((USART3->SR&0X40)==0);//循环发送,直到发送完毕USART3->DR = (u8) character;}
}

这个 USART3->DR 为stm32串口的寄存器!读者可参照自己的芯片来配置!

简单就完了!

资料直通车:Linux内核源码技术学习路线+视频教程内核源码

学习直通车:Linux内核源码内存调优文件系统进程管理设备驱动/网络协议栈

IAR 配置方法

首先添加文件:

我在这里起名字为 C_Library。然后在添加文件:

选择 printf.c (反正就是添加这个文件,放到哪里看你自己):

接着就是添加编译器头文件路径:

在选择第一个大框框右边的那个:

点击Click to add。选择头文件路径所在的文件夹后 select,接着就会回到这里:

上面是配置头文件路径的,第一个是绝对路径,也就是说你工程文件移动了,就回到不到了,第二个是相对路径!选第二个吧!接着编译就会发现报错了!!!不要慌!我们首先选择Options > General Options:

此时在编译一次,就会发现也还是错了!说什么没定义。经研究,哦,原来是stdint.h这个头文件在for 8051 这款工具上,没有定义64为的无符号整形,那个怎么办啊!经发现,哦 ,原来注释这个宏就行!

程序编译通过!printf_u0 和stm32 配置类型,无非就是修改一下数据的流向!读者自己研究一下吧!!

教程示例:嵌入式软件移植 printf相关推荐

  1. 乐鑫代理启明云端分享:用ESP32单片机控制LED教程示例

    提示:准备好开发板和LED灯 1.可以选择启明云端推出的ESP32开发板,上手简单 原因: 启明云端WT-ESP32-DevKitC V4开发板,这是一款基于ESP32的小型开发板,集WIFI+蓝牙方 ...

  2. java泛型方法 通配符_Java泛型教程–示例类,接口,方法,通配符等

    java泛型方法 通配符 泛型是Java编程的核心功能之一,它是Java 5中引入的.如果您使用的是Java Collections ,并且版本5或更高版本,则可以肯定使用了它. 将泛型与集合类一起使 ...

  3. Java泛型教程–示例类,接口,方法,通配符等

    泛型是Java编程的核心功能之一,它是Java 5中引入的.如果您使用的是Java Collections ,并且版本5或更高版本,则可以肯定使用了它. 在集合类中使用泛型非常容易,但是它提供了比仅创 ...

  4. SkyWalking--告警--使用/教程/示例

    原文网址:SkyWalking--告警--使用/教程_IT利刃出鞘的博客-CSDN博客 简介 说明 本文介绍SkyWalking的告警功能的用法. SkyWalking支持WebHook.gRPC.微 ...

  5. maven--profile--使用/教程/示例

    原文网址:maven--profile--使用/教程/示例_IT利刃出鞘的博客-CSDN博客 简介 说明         本文用示例说明maven的profile的使用. mavan的profile作 ...

  6. Jackson--使用/教程/示例

    原文网址:Jackson--使用/教程/示例_IT利刃出鞘的博客-CSDN博客 简介 说明         本文用实例介绍Jackson的使用. 项目中我们经常会用到JSON,比如:将JSON字符串反 ...

  7. Angular官网教程示例知识点总结

    Angular官网教程示例知识点总结 1.背景 2.知识点 2.1 应用的外壳 2.1.1 使用 Angular CLI 创建初始的应用结构 2.1.2 启动应用服务器 2.1.3 双花括号表达式 2 ...

  8. 教程示例:控制存储空间和文件夹的访问权限

    本教程示例详细演示了如何控制用户对 OSS 存储空间和文件夹的访问.在示例中,我们首先创建一个存储空间和文件夹,然后使用阿里云主账号创建访问管理 (RAM) 用户,并为这些用户授予对所创建 OSS 存 ...

  9. SkyWalking--OAL--使用/教程/示例

    原文网址:SkyWalking--OAL--使用/教程/示例_IT利刃出鞘的博客-CSDN博客 简介 说明         本文介绍SkyWalking的OAL语法的用法. 官网 OAL介绍 http ...

最新文章

  1. 零基础学python爬虫-我是如何零基础开始能写Python爬虫的
  2. Java线程池--ThreadPoolExecutor
  3. 设置让php能够以root权限来执行exec() 或者 shell_exec()
  4. 枚举法 之Java实现凑硬币
  5. 打印机可以打印不能扫描怎么弄_为什么打印机可以通过电脑打印可不能扫描呢...
  6. Implicit conversion from enumeration type 'enum CGImageAlphaInfo' to different enumeration type 'CGB
  7. mysql用supervisor管理_使用Supervisor管理进程
  8. 大V怒怼银行服务太差,一怒取走500万现金!上海银行回应了
  9. c++访问私有(private)成员变量的常用方法
  10. 机器学习笔记(十九):逻辑回归
  11. 数据结构——线性链表/单链表设计
  12. 网络安全等级符合三级等保要求套餐
  13. windows 键盘快捷键
  14. CRM系统更换服务器,CRM系统三种常见安装实施解决方式
  15. transition动画无效 iphone6
  16. 【Linux】常用配置文件路径
  17. 军事ar虚拟现实电子沙盘系统的功能
  18. Excel电子表格隔行自动填充底色
  19. (37)DWD 层(业务数据)
  20. 怎么选择适合自己的SDWAN部署方案

热门文章

  1. 浮动广告(页面中一张广告图片不断的变化位置)
  2. 华东交通大学c语言程序设计,2016年华东交通大学理学院C语言程序设计考研复试题库...
  3. QGC的ScreenToolsController
  4. 软件介绍 CamStudio (屏幕录制工具)
  5. 黎明杀机一直无法连接在线服务器,黎明杀机无法连接-崩坏3IOS无法连接服务器...
  6. OceanBase-安装
  7. Pylint 常见问题文档
  8. 【免费送书】小白也能学会的Webpack 应用瘦身技巧
  9. Python Smbus库简介
  10. LaTeX: Missing } or { inserted. ^^I\For