printf通过串口输出在MCU上的实现

        对mcu的开发调试过程中,通过串口打印运行过程中的一些信息,有时候比调试器好用。以及在产品使用中,通过对关键运行状态的输出,对于运行故障的判断分析,具有很高的价值。如何用printf或者类似这样函数来实现呢?

        先讲原理:printf本身不具备输出功能,只是式样化输出函数, 一般用于向准则输出设备按规定式样输出消息。例如语句:

uint8_t hour = 10, minute = 25, second = 3;
Printf("Now Time %02d:%02d:%02d\n", hour, minute, second);

只是转化为语句:Now Time 10:25:03 [换行],这个语句去哪了?由函数fputc处理了。

注:函数printf和fputc都是C语言的标准库函数(stdio.h)。

那么,如何实现串口的格式化输出呢?

方法1,重定向函数fputc

        上面提到,printf是格式化数据,然后通过fputc实现输出。可以输出到文件,显示器,串口等等,取决于fputc函数的功能。

        重新写一个fputc函数,将会自动替代标准库函数。(华大代码)

       

int fputc(int ch, FILE *f)
{
    (void)f;  /* Prevent unused argument compilation warning */
    return (Ok == UartPutChar(m_PrintfDevice, (char)ch)) ? ch: -1;
}

ch就是需要发送的一个字符,FILE *f这个参数不用管(将字符写入文件用的,文件描述符)。

根据mcu底层,将数据写入发送寄存器或者缓冲器。注意的是,一次发送一个字符,一个printf会频繁调用fputc,必须要串口的缓冲器为空才能写入。

可以看到,这种方法效率太低。等待前一个数据发出后,才能发送下一个。

另外一种方法就是在fputc函数中,把字符放到ringbuffer,再ringbuffer的数据通过串口发送出去,这样效率就非常高了。

方法2,写一个函数,格式化加串口发送

        根据以上的描述,我们了解了串口格式化输出的原理,自己写一个函数来实现。

void LogPrintfUser(const char *fmt, ...)
{
    va_list ap;
	int len = 0;
    uint8_t buffer[UART_LOG_MAX_LEN];

    if (fmt == NULL) return;

	memset(buffer, 0, UART_LOG_MAX_LEN);
	va_start(ap, fmt);
	len = vsnprintf((char *)buffer, UART_LOG_MAX_LEN, fmt, ap);
	va_end(ap);
	
	RingBuffer_InsertMult(&RB_Debug_TX, buffer, len);
	DBG_TxStart();
}

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值