————————————————

华大HC32L13系列国产32单片机开启串口打印(汇总多种方法)

————————————————

官方demo存在的问题

使用keil5 MDK进行开发时,无法使用printf()函数进行串口调试,按照网上关于ARM单片机的相关教程,在使用微库(即打开keil软件中的Use MicroLIB选项)时测试发现依然无用。查看代码:
发现Debug_Output()函数被注释掉了!

即使去掉注释也无法使用printf()函数。

解决方法一

参考下面内容修改库文件ddl.c下的Debug_Output()函数(大概在173行),然后再配置UART0的RXD和TXD引脚即可使用UART0进行串口打印。如果要替换成其他串口,则需要将Debug_Output()函数中的UART0替换成其他的串口即可。

void Debug_Output(uint8_t u8Data)
{//M0P_UART0->SCON_f.REN = 0;//M0P_UART0->SBUF = u8Data;////while (TRUE != M0P_UART0->ISR_f.TI)//{//    ;//}//M0P_UART0->ICR_f.TICLR = 0;   M0P_UART0->SCON_f.REN = 0;M0P_UART0->SBUF = u8Data;while (TRUE != M0P_UART0->ISR_f.TC){;}M0P_UART0->ICR_f.TCCF = 0;
}

亲测,当打开keil MDK中的有关微库(即Use MicroLIB选项)时候,仅仅更改Debug_Output()函数即可。

但如果没有开启微库(即Use MicroLIB选项)时候,则需要在库文件ddl.c中取消ARM的半主机工作模式(大概在208行):

#if defined (__CC_ARM)          //KEIL
#pragma import(__use_no_semihosting) //取消ARM的半主机工作模式
void _sys_exit(int x) //定义_sys_exit()以避免使用半主机模式
{x = x;
}
struct __FILE //标准库需要的支持函数
{int handle;/* Whatever you require here. If the only file you are using is *//* standard output using printf() for debugging, no file handling */
/* is required. */
};
/* FILE is typedef?d in stdio.h. */
FILE __stdout;#endif

解决方法二

在库文件ddl.h中添加引用:#include "uart.h",然后参考下面内容修改库文件ddl.c下的fputc()函数(大概在231行),再配置UART0的RXD和TXD引脚即可使用UART0进行串口打印。如果要替换成其他串口,则需要将该函数中的M0P_UART0替换成其他的串口(如M0P_UART1)即可。

#ifdef __DEBUG
/********************************************************************************** \brief  Re-target putchar function******************************************************************************/
int fputc(int ch, FILE *f)
{//    if (((uint8_t)ch) == '\n')
//    {//        Debug_Output('\r');
//    }
//    Debug_Output(ch);Uart_SendDataPoll(M0P_UART0, ch); //串口未启用发送中断模式,即查询模式发送数据
//  Uart_SendDataIt(M0P_UART0, ch); //串口开启了发送中断模式return ch;
}
#endif

亲测,当打开keil MDK中的有关微库(即Use MicroLIB选项)时候,仅仅更改fputc()函数即可,若关闭微库,则需要按照方法一中的内容打开ddl.c中208~224行的代码。此外,Uart_SendDataPoll()Uart_SendDataIt()函数只能打开其中之一,根据实际情况选择!

解决方法三

在库文件ddl.h中添加引用:#include "uart.h",然后参考下面内容修改库文件ddl.c下的fputc()函数(大概在231行),再配置UART0的RXD和TXD引脚即可使用UART0进行串口打印。如果要替换成其他串口,则需要将该函数中的M0P_UART0替换成其他的串口(如M0P_UART1)即可。

#ifdef __DEBUG
/********************************************************************************** \brief  Re-target putchar function******************************************************************************/
int fputc(int ch, FILE *f)
{//    if (((uint8_t)ch) == '\n')
//    {//        Debug_Output('\r');
//    }
//    Debug_Output(ch);while ( 0 == (M0P_UART0->ISR & 0x08)){;}M0P_UART0->SBUF_f.DATA = (unsigned char)ch;return ch;
}
#endif

亲测,当打开keil MDK中的有关微库(即Use MicroLIB选项)时候,仅仅更改fputc()函数即可,若关闭微库,则需要按照方法一中的内容打开ddl.c中208~224行的代码。

ddl.c原始位置:hc32l13x_ddl_Rev1.9.2 Lite\driver\src\ddl.c
ddl.h原始位置:hc32l13x_ddl_Rev1.9.2 Lite\driver\inc\ddl.h

扩展知识

1,ARM内核单片机的半主机模式

① 一种用于ARM处理器或者模拟器与PC主机之间进行输入输出(键盘输入和PC屏幕显示输出 )通信(通过串口、网口、通用总线、USB等的通信)的机制,即可将来自应用程序代码的输入/输出请求传送至运行调试器的主机。 例如,使用此机制可以启用 C 库中的函数,如 printf()scanf(),来使用主机的屏幕和键盘,而不是在目标系统上配备屏幕和键盘。

② ARM处理器的模拟器使用的是半主机模式,使得我们无需添加某些头文件或者指令即可使用半主机模式中的一些接口或者命令,比如HLT、SVC、BKPT等。但是那是适用于模拟器的,并不适用于一个实际的嵌入式硬件开发板,因为大多情况下我们的开发板是不会接入一个键盘来获取数据的, 比如我们要实现的调试串口的驱动,我们希望调用printf()函数来让UART输出数据, 我们需要重写fputc()这个函数才行。

③ 非半主机模式下运用C库,只需要在程序中任意地方添加以下代码即可:#pragma import(__use_no_semihosting),即取消ARM的半主机工作模式。关于如何重定向printf()(即重写fputc() ),在C库手册中有示例:

2,MicroLib

microlib是C库中的一种,它是默认C库的替代库文件(缺省c库的备选库),它提供了一个有限的stdio子系统,仅支持未缓冲的stdin、stdout和stderr。

特点:

① 主要用于那些基于极少内存映射的嵌入式应用程序,与嵌入式应用程序配合使用,且这些应用程序不在操作系统中运行;

② 高度优化以使代码变得很小,功能比缺省c库少,不具备某些ISO C特性,部分库函数的运行速度也比较慢,如内存拷贝函数memcpy()。与缺省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的话,嵌入式设备便不会使用半主机模式;

④ Microlib对于IO功能仅定义了_stdout和_stdin,用户重定向fputc() / fgetc() 的时候无需再重新定义_stdout/_stdin。

但是,keil MDK中勾选了Use MicroLib选项后,还是不能直接使用printf()函数,其打印的字符串最终不知道打印到何处。我们要做的是将调试信息打印到UART中,所以需要对printf()函数所依赖的打印输出函数fputc()重定向(MicroLib中的printf()函数打印操作依赖fputc())。

所以,ARM内核的嵌入式设备,若要使用 printf() 函数,归根到底只有2种方法:
方法一:开启MicroLib,且重定义fputc()函数;
方法二:关闭MicroLib,关闭半主机模式,且重定义fputc()函数。推荐使用方法二。

参考文档

  1. STM32的printf函数重定向_mybright_的博客-CSDN博客_stm32printf重定向
  2. STM32半主机模式_weixin_40093087的博客-CSDN博客_什么是半主机模式
  3. 系统时钟的配置、半主机模式(百问网7天物联网智能家居笔记3)_zhw_blog的博客-CSDN博客
  4. 华大单片机HC32L136如何做printf串口打印格式化输出_芯缘意码的博客-CSDN博客_华大单片机使用printf
  5. HC32L176之串口实现printf打印_無荏知晓的博客-CSDN博客
  6. 华大单片机HC32L136实现printf_oshan2012的博客-CSDN博客_华大单片机printf

【国产单片机】华大HC32L13系列使用printf进行调试(多种方法)相关推荐

  1. 国产单片机GD32系列开坑,带你零死角玩转GD32 第一章

    [开坑国产单片机GD32系列,带你零死角玩转GD32] 第一章 GD32基本资料介绍 目录 [开坑国产单片机GD32系列,带你零死角玩转GD32] 第一章 GD32基本资料介绍 前言 一.STM32 ...

  2. 国产单片机GD32系列开坑,带你零死角玩转GD32 第六章

    [开坑国产单片机GD32系列,带你零死角玩转GD32] 第六章 GD32F103C8T6串口开发板设计指南(二) 目录 [开坑国产单片机GD32系列,带你零死角玩转GD32] 第六章 GD32F103 ...

  3. 国产单片机GD32系列开坑,带你零死角玩转GD32 第五章

    [开坑国产单片机GD32系列,带你零死角玩转GD32] 第五章 GD32F103C8T6串口开发板设计指南(一) 目录 [开坑国产单片机GD32系列,带你零死角玩转GD32] 第五章 GD32F103 ...

  4. 国产单片机GD32系列开坑,带你零死角玩转GD32 第二章

    [开坑国产单片机GD32系列,带你零死角玩转GD32] 第二章 GD32开发环境的搭建,常用资料的获取,以及点亮LED! 目录 [开坑国产单片机GD32系列,带你零死角玩转GD32] 第二章 GD32 ...

  5. 国产超低功耗华大单片机HC32L136开发板上手入门

    今天介绍下国产超低功耗华大单片机HC32L136开发板上手后的入门操作(开发板可以在华大MCU应用交流群:164973950 免费申请).HC32L136开发板(如下图所示)分为板载调试模块(左半部分 ...

  6. 国产超低功耗华大单片机HC32F003开发板上手入门

    今天介绍下国产超低功耗华大单片机HC32F003开发板上手后的入门操作(开发板可以在华大MCU应用交流群:164973950 免费申请).HC32F003开发板(如下图所示)分为板载调试模块(左半部分 ...

  7. 国产超低功耗华大单片机HC32L110开发板上手入门

    今天介绍下国产超低功耗华大单片机HC32L110开发板上手后的入门操作(开发板可以在华大MCU应用交流群:164973950 免费申请).HC32L110开发板(如下图所示)分为板载调试模块(左半部分 ...

  8. 国产超低功耗华大单片机HC32F005开发板上手入门

    今天介绍下国产超低功耗华大单片机HC32F005开发板上手后的入门操作(开发板可以在华大MCU应用交流群:164973950 免费申请).HC32F005开发板(如下图所示)分为板载调试模块(左半部分 ...

  9. 国产单片机系列:上海灵动微电子MM32使用笔记

    上海灵动微电子MM32使用笔记 微信公众号:雍正不秃头,回复MM32模板获取本章内容下载链接. ~~~~~~~~        原本项目上使用了STM32F031F6P6这一款单片机,奈何ST的芯片疯 ...

  10. 国产单片机GD32系列开坑,带你零死角玩转GD32 第四章

    [开坑国产单片机GD32系列,带你零死角玩转GD32] 第四章 新朝雅政了属于是 目录 [开坑国产单片机GD32系列,带你零死角玩转GD32] 第四章 新朝雅政了属于是 (1)前言 (1)前言 知莫大 ...

最新文章

  1. 车辆贷款违约预测挑战赛
  2. 计算机图像抠图有什么作用,图像处理 抠图|傲软抠图 v1.1.13.1电脑版 - 系统天堂...
  3. Windows核心编程 第五章 作业(上)
  4. C++二维数组做形参
  5. java学习(105):字符串indexof,spilt,substring方法
  6. C++的const修饰
  7. PostgreSQL 12系统表(9)pg_settings
  8. jdk版本修改不生效
  9. 密钥短语密码加密,解密同理。
  10. 判断是否为数组的 JavaScript 方法总结
  11. 微信小程序学习笔记:选项卡
  12. 微信公众号网页跳转及获取用户信息的接口设计
  13. gnome 如何自定义样式_在Gnome 3中自定义字体
  14. 如何找到计算机上的画图拦,机子里的画图和计算机没有了
  15. 打开excel提示损坏的映像的解决办法
  16. jQuery延迟加载(懒加载)
  17. 原码、反码、补码之间的转换和简单运算
  18. XMD DTD约束 实体学习X1 普通实体 参数实体 内部实体 外部实体 内置实体 解析实体 不解析实体 实体声明 实体引用 字符引用...
  19. 易经八卦解释鸿蒙,易懂中的五行与八卦
  20. 无线打印机服务器安装步骤,【DDwifi打印服务器】Windows 10系统添加打印机步骤(离线安装打印机驱动)...

热门文章

  1. Solidity ERC777标准
  2. java throw 和catch_Java catch与throw同时使用的操作
  3. Linux内核设计与实现 总结笔记(第六章)内核数据结构
  4. Html标签命名规范
  5. Android 4.0 人脸,Android 4.0.3!原道N90人脸识别试用
  6. 第三代航空轴承钢产品 css-42l,航空轴承钢的发展及热处理技术(一)
  7. Centos安装Wordpress
  8. Epub电子书实战解析
  9. ASA防火墙配置清除
  10. java exception message_Java 如何摆脱Exception.getMessage()输出带类名