前言

在DSP的开发过程中,printf()函数对于程序的调试具有非常重要的作用。学过STM32的都了解,STM32串口文件中重定义了printf(),使得printf()打印的内容可以通过串口显示在PC端的串口调试助手上。

在没有LCD1602、12864以及其它液晶时,我们可以通过串口打印调试程序。我使用的是普中科技的TMS320F28335,现介绍几种在开发DSP的过程中使用printf()的方法。(注意:SCI配合重定向printf()方法并不能完全实现printf()的功能,其余的方法均可以实现printf()的功能)


注意以下内容均是我通过广泛阅读CSDN大佬的文章以及加入自己的思考和调试总结出来的,方法仅供大家参考!

1. printf重定向

大家在初始学C语言时,我们会用VS或者VC通过printf()将我们要打印的数据送到终端(CMD窗口)。所谓的printf()重定向是指:通过对printf()底层的修改,使printf()打印的数据不再送到终端,而是送到我们指定的位置,结合28335的SCI,我们可以将printf()重定向到SCI,这样printf()打印的数据就会送到SCI,再通过SCI将数据送到PC端的串口调试助手上。

对于printf()底层的修改,实际上就是对fputc()函数的修改。重定向代码如下:

#include "stdio.h"
/*
 * 注意:1.我使用的是SCIA与PC进行通信
 *       2.我启用了FIFO缓冲区
 */
int fputc(int _c, register FILE *_fp)
{
        while (SciaRegs.SCIFFTX.bit.TXFFST != 0);  //重定向到SCIA
                SciaRegs.SCITXBUF = _c;
        return _c;
}

重定向后,我们就可以调用printf()函数,通过写C的形式,将要显示的内容发送给PC并在串口调试助手上显示。

但是实际操作中,完成上述步骤后,编译会出错。此时需要我们配置工程属性以及修改原cmd文件。

这里要说明一下,有的人工程用F28335.cmd,即将程序下载到FLASH中,有的人用28335_RAM_lnk.cmd,即程序仅用于调试,这两种cmd文件的修改内容是不一样的;另外还需要注意,对于SCI的初始化以及其发送函数这里不再给出(我使用的是SCIA),我将在后续讲解SCI时,给出具体的初始化代码,这里仅提供修改工程关键的部分。
具体修改以及实现结果如下:

1.1 若cmd文件为F28335.cmd

工程属性修改为:
在这里插入图片描述
在这里插入图片描述
F28335.cmd文件修改为:
在这里插入图片描述
主函数程序为:

void main()
{
	InitSysCtrl();
	MemCopy(&RamfuncsLoadStart, &RamfuncsLoadEnd, &RamfuncsRunStart);
	InitFlash();

	SCIA_Init(4800);  //初始化SCIA
	while(1)
	{
		printf("Hello word! \r\n");
		printf("one:%d,two:%.4f,three:%3d\r\n",10000,23.157,12345);
		printf("four:0x%x,five:%o,six:%c,seven:%s\r\n",12,22,'d',"nihao");
		DELAY_US(500000);
	}
}

串口调试助手打印结果为:
在这里插入图片描述
分析:从结果可以看到只有字符串能正常打印,除%s外,所有的显示符均无效!原因未知!

1.2 若cmd文件为28335_RAM_lnk.cmd

工程属性修改为:
在这里插入图片描述
在这里插入图片描述
28335_RAM_lnk.cmd文件修改为:
在这里插入图片描述
在这里插入图片描述
主函数程序为:

void main()
{
	InitSysCtrl();
	SCIA_Init(4800);  //初始化SCIA
	while(1)
	{
		printf("Hello word! \r\n");
		printf("one:%d,two:%.4f,three:%3d\r\n",10000,23.157,12345);
		printf("four:0x%x,five:%o,six:%c,seven:%s\r\n",12,22,'d',"nihao");
		DELAY_US(500000);
	}
}

串口调试助手打印结果为:
在这里插入图片描述
分析:从结果可以看到只有字符串能正常打印,除%s外,所有的显示符均无效!原因未知!

2.自定义一个变参函数来代替printf()

函数的定义如下:

#include "stdio.h"
#define MAX_WRITE_LEN (528)
void uart_printf(char * fmt, ...) //自定义变参函数
{
    char * 	arg_ptr;
    unsigned int  i ,  len;
	static char	write_buf[MAX_WRITE_LEN];

    va_start(arg_ptr, fmt);
    len = vsprintf((char *)write_buf, fmt, arg_ptr);
    va_end(arg_ptr);

    for (i = 0; i < len; i++)
    {
        if ( '\0' != write_buf[i] )
		{
        	while (SciaRegs.SCIFFTX.bit.TXFFST != 0); //使用SCIA
        	SciaRegs.SCITXBUF=write_buf[i];
        }
    }
}

实际操作中需要修改原cmd文件,具体修改以及实现结果如下:

2.1若cmd文件为F28335.cmd

工程属性不需要修改
F28335.cmd文件修改为:
在这里插入图片描述
主函数程序为:

void main()
{
	InitSysCtrl();
	MemCopy(&RamfuncsLoadStart, &RamfuncsLoadEnd, &RamfuncsRunStart);
	InitFlash();

	SCIA_Init(4800);  //初始化SCIA
	while(1)
	{
		printf("Hello word! \r\n");
		printf("one:%d,two:%.4f,three:%6d\r\n",10000,23.157,12345);
		printf("four:0x%x,five:%o,six:%c,seven:%s\r\n",12,22,'d',"nihao");
		DELAY_US(500000);
	}
}

串口调试助手打印结果为:
在这里插入图片描述
分析:从结果可以看到所有的显示符均可正常显示!

2.2若cmd文件为28335_RAM_lnk.cmd

工程属性不需要修改
28335_RAM_lnk.cmd文件修改为:
在这里插入图片描述
在这里插入图片描述
主函数程序为:

void main()
{
	InitSysCtrl();
	SCIA_Init(4800);  //初始化SCIA
	while(1)
	{
		printf("Hello word! \r\n");
		printf("one:%d,two:%.4f,three:%6d\r\n",10000,23.157,12345);
		printf("four:0x%x,five:%o,six:%c,seven:%s\r\n",12,22,'d',"nihao");
		DELAY_US(500000);
	}
}

串口调试助手打印结果为:
在这里插入图片描述
分析:从结果可以看到所有的显示符均可正常显示!

3.直接使用printf(),从CIO观察结果

该方法无需将printf()重定向,也无需自定义一个函数,可直接按C的方法使用printf()。printf()输出的结果将在CIO()上显示。由于printf()未进行重定向,因此不使用SCI,此时的printf()仅用作调试用,将与printf()相关的程序下载到FLASH中将无意义,故只使用28335_RAM_lnk.cmd。

注意:使用printf()之前需要添加头文件#include “stdio.h”,然后就可以在主函数以及其它函数中调用printf(),进行调试时在CIO中查看打印结果。

实际操作中需要配置工程属性以及修改原cmd文件,具体修改以及实现结果如下:

工程属性修改为:
在这里插入图片描述
在这里插入图片描述
28335_RAM_lnk.cmd文件修改为:
在这里插入图片描述
在这里插入图片描述
主函数程序为:

void main()
{
	InitSysCtrl();
	while(1)
	{
		printf("Hello word! \r\n");
		printf("one:%d,two:%.6f,three:%6d\r\n",10000,23.157,12345);
		printf("four:0x%x,five:%o,six:%c,seven:%s\r\n",12,22,'d',"nihao");
		DELAY_US(500000);
	}
}

CIO打印结果为:
在这里插入图片描述

分析:从结果可以看到所有的显示符均正常显示!

总结

printf()重定向输出打印会出现一系列的问题。在进行程序调试时,建议用方法3,相较于方法2来说,此时无需RS232、SCI以及串口调试助手,在CCS的CIO中就可直接看打印结果;当需要将打印结果串口显示时,建议用方法2的2.1,此时可以将要打印的程序写入到FLASH中。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐