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

华大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. CMOS图像传感器理解
  2. 实现HttpHandlerFactory的方法
  3. hdfs mv命令_大数据入门:HDFS文件管理系统简介
  4. 爬虫python下载-如何用Python爬虫实现百度图片自动下载?
  5. Chrome 浏览器提示adobe flash player不是最新版本
  6. 如何计算Java对象所占内存的大小
  7. 三元环计数四元环计数
  8. 更改临时文件夹的路径
  9. IDEA 修改项目名称
  10. 使用Specflow 和XUnit 进行BDD测试项目配置方法
  11. itext pdf 基本使用实战
  12. 韦根协议W26|W34通讯CPU卡读头HX-W26CPU在门禁梯控设备集成安装注意事项
  13. python源文件的扩展名是什么_python源文件后缀是什么
  14. [GIS原理] 8 GIS基本空间分析-叠置分析|缓冲区分析|窗口分析
  15. 2018-11-15-mqtt-mosquitto系列11之配置基于ca证书的桥接
  16. 心理学 | (1)焦虑症和恐惧症--一种认知的观点
  17. 关于actor模型的优缺点分析
  18. H5页面微信授权登录——前端部分
  19. 设计Course类:处理课程信息,每门课都有一个名字以及选课的学生,要能够向/从这个课程添加/删除一个学生
  20. 建立标准编码规则(二)-DiagnosticAnalyzer 增加诊断分析代码

热门文章

  1. 过犹不及,别再在编程中高射炮打蚊子
  2. 团队作业7-Alpha冲刺之事后诸葛亮
  3. 蓝牙耳机连接笔记本音量大的问题
  4. 18年第十二届东北四省赛
  5. throw在java用法_throw()使用小结
  6. 学习笔记 java学习(三)
  7. 披着“云”衣裳的狗——搜狗输入法“云”版本尝鲜记
  8. 杭州自己缴纳社保五险条件
  9. 从实例学Kettle(一):获取股票行情数据
  10. python删除第一行_python学习之删除DataFrame某一行/列内容