stm32调试使用printf向OLED打印信息(printf重定向)

#stm32调试使用printf向OLED打印信息(printf重定向),并简单实现转义字符“\n”和“\t”#

        printf 是 C 语言中用于格式化输出的函数,可以向标准设备输出各种类型的数据。使用printf在调试过程输出打印数据,可以大大简化调试过程。而且向OLED输出可以直观的观察数据的变化,但是我是用的是0.96寸小屏,只能显示4*16的ascii码能表示的字符;

1.使用Keil需要打开MicroLIB

        使用Keil的话需要打开MicroLIB,MicroLIB是ARM-MDK官网提供的一个为ARM基础的嵌入式应用程序编写的高度优化的库。MicroLIB专为深度嵌入式应用设计,优化了代码和数据存储器的使用。如果使用Stm32CubeIDE或者Stm32CubeMX直接生成的MDK-ARM工程可以直接使用printf();不用打开MicreLIB,但是依旧需要对printf进行重定向打印位置。

2.printf重定向 

         printf重定向,主要是通过对MicroLIB自带的库函数fputc()进行重定义,如果编译器检测到用户定义了与库函数同名的函数,会优先使用用户定义的函数。使用printf前需要先#include<stdio.h>

int fputc(int ch, FILE *f)        //fputc函数原型

        这个函数是printf对用户的想要达到的输出结果字符串,通过fputc一个字符一个字符的发送到标准输出设备上,但是对与嵌入式系统,通常没有标准输出设备,因此用户可以通过自定义fputc函数指定输出设备;

3.实现fputc 

         fputc函数代码实现;

static int gOled_PrintPosRow = 0;        //输出光标行位置
static int gOled_PrintPosCow = 0;        //输出光标列位置(列位置是128列)


int fputc(int ch, FILE *f){
	
	
	if( ch >= ' ' && ch <= '~') //其他不在字库中的ascii码禁止显示
	{
		gOled_PrintPosRow %= OLED_HEIGHT / 8;  //实现光标的自动换行
		gOled_PrintPosCow %= OLED_WIDTH;
		
		if( 0 == gOled_PrintPosCow && ' ' == ch) //默认第一列不显示空格
			return ch;
		
		draw_Char(gOled_PrintPosRow, gOled_PrintPosCow, (uint8_t)ch);
                            //字符发送函数,可以替换成自己的字符发送函数
		gOled_PrintPosCow += 8;
		if(gOled_PrintPosCow > 127) gOled_PrintPosRow += 2;
	}
	return ch;
}

         注意到 fputc函数接收的ch是int类型,32位数据,所以ch接收UTF-8类型的编码,因此可以输出中文,但是对于OLED,中文字库占的内存太大,所以只显示ASCII码;

4.使用printf的局限性

        printf只能向一个输出设备,但是很多情况下往往不会只想要在一个输出设备上打印信息,最好能在多个设备上打印信息,最好能自己指定在那个设备上打印信息;

5.为每个输出设备创建自己的输出函数

#include <stdarg.h>  //需要包含此头文件

//OLED打印函数
void OLED_printf(char *format, ...)
{
	static char StringBuff[STRINGBUFFSIZE] ;    //创建OLED打印BUFF
	va_list arg;
	va_start(arg, format);
	vsprintf(StringBuff, format, arg);        //将打印字符串写入到StringBuff中
	va_end(arg);
	
	OLED_SendString(StringBuff);              //调用自己的字符串发送函数,发送格式化输出字符串
}

static void OLED_SendString(char * String )//这里应该放在OLED_printf前面,为了说明暂时放在这里
{
	//发送 StringBuff
	int i, DataNum = 0;
	int RestDataNum;
	const char* DataArray = String;
	while(*DataArray != '\0')
	{
		DataArray ++;
		DataNum ++;
	}
	for(i = 0; i < DataNum; i ++)
	{
		if(String[i] == '\n' )//实现转义字符\n
		{
			if(gOled_PrintPosCow == OLED_WIDTH)
		{
			continue;
		}
			gOled_PrintPosRow += 2;
			gOled_PrintPosCow  = 0;
			continue;
		}
		
		if(String[i] == '\t' )//实现转义字符\t(两个空格)
		{
			if(gOled_PrintPosCow == OLED_WIDTH)
			{
				continue;
			}
			else if(gOled_PrintPosCow == OLED_WIDTH - 8)
			{
				gOled_PrintPosCow = OLED_WIDTH;
				continue;
			}
			else 
			{
				gOled_PrintPosCow +=16;
				continue;
			}	
		}
		gOled_PrintPosRow %= OLED_HEIGHT / 8;
		gOled_PrintPosCow %= OLED_WIDTH;
		
		draw_Char(gOled_PrintPosRow, gOled_PrintPosCow, String[i]);//字符发送函数
                                         //字符发送函数,可以替换成自己的字符发送函数
		gOled_PrintPosCow += 8;
		if(gOled_PrintPosCow >127) gOled_PrintPosRow += 2;
	}
}

6.效果展示 

        测试代码:

printf("Time:\t%d:%d:%d\n",Hour , Minute, Second);        //显示时间
printf("The ascii of 'A' is %#X\n ", 'A');                //%X显示十六进制数,%#X加上0x前缀
OLED_printf("Time:\t%d:%d:%d\n",Hour , Minute, Second);    //OLED_printf显示时间

 显示效果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值