543|1

504

帖子

4

TA的资源

纯净的硅(高级)

楼主
 

【瑞萨RA8D1开发板,基于M85内核的图形MCU】移植轻量标准输入输出函数库xprintf [复制链接]

前面我们实现了好用的串口收发接口,进一步我们来实现基于串口的输入输出,方便后面交互打印信息等。

 

参考微信公众号”嵌入式Lee”的文章

https://mp.weixin.qq.com/s/y4MHV3cd4T0b51L5M4J5Xg 极海半导体APM32F107VC开发板-移植超轻量级标准输入输出函数库xprintf

 

Xprintf.c如下

/*------------------------------------------------------------------------/
/  Universal String Handler for Console Input and Output
/-------------------------------------------------------------------------/
/
/ Copyright (C) 2021, ChaN, all right reserved.
/
/ xprintf module is an open source software. Redistribution and use of
/ xprintf module in source and binary forms, with or without modification,
/ are permitted provided that the following condition is met:
/
/ 1. Redistributions of source code must retain the above copyright notice,
/    this condition and the following disclaimer.
/
/ This software is provided by the copyright holder and contributors "AS IS"
/ and any warranties related to this software are DISCLAIMED.
/ The copyright owner or contributors be NOT LIABLE for any damages caused
/ by use of this software.
/
/-------------------------------------------------------------------------*/

#include "xprintf.h"

#define SZB_OUTPUT	32


#if XF_USE_OUTPUT
#include <stdarg.h>
void (*xfunc_output)(int);	/* Pointer to the default output device */
static char *strptr;		/* Pointer to the output memory (used by xsprintf) */


#if XF_USE_FP
/*----------------------------------------------*/
/* Floating point output                        */
/*----------------------------------------------*/
#include <math.h>


static int ilog10 (double n)	/* Calculate log10(n) in integer output */
{
	int rv = 0;

	while (n >= 10) {	/* Decimate digit in right shift */
		if (n >= 100000) {
			n /= 100000; rv += 5;
		} else {
			n /= 10; rv++;
		}
	}
	while (n < 1) {		/* Decimate digit in left shift */
		if (n < 0.00001) {
			n *= 100000; rv -= 5;
		} else {
			n *= 10; rv--;
		}
	}
	return rv;
}


static double i10x (int n)	/* Calculate 10^n */
{
	double rv = 1;

	while (n > 0) {		/* Left shift */
		if (n >= 5) {
			rv *= 100000; n -= 5;
		} else {
			rv *= 10; n--;
		}
	}
	while (n < 0) {		/* Right shift */
		if (n <= -5) {
			rv /= 100000; n += 5;
		} else {
			rv /= 10; n++;
		}
	}
	return rv;
}


static void ftoa (
	char* buf,	/* Buffer to output the generated string */
	double val,	/* Real number to output */
	int prec,	/* Number of fractinal digits */
	char fmt	/* Notation */
)
{
	int d;
	int e = 0, m = 0;
	char sign = 0;
	double w;
	const char *er = 0;


	if (isnan(val)) {			/* Not a number? */
		er = "NaN";
	} else {
		if (prec < 0) prec = 6;	/* Default precision (6 fractional digits) */
		if (val < 0) {			/* Nagative value? */
			val = -val; sign = '-';
		} else {
			sign = '+';
		}
		if (isinf(val)) {		/* Infinite? */
			er = "INF";
		} else {
			if (fmt == 'f') {	/* Decimal notation? */
				val += i10x(-prec) / 2;	/* Round (nearest) */
				m = ilog10(val);
				if (m < 0) m = 0;
				if (m + prec + 3 >= SZB_OUTPUT) er = "OV";	/* Buffer overflow? */
			} else {			/* E notation */
				if (val != 0) {		/* Not a true zero? */
					val += i10x(ilog10(val) - prec) / 2;	/* Round (nearest) */
					e = ilog10(val);
					if (e > 99 || prec + 6 >= SZB_OUTPUT) {	/* Buffer overflow or E > +99? */
						er = "OV";
					} else {
						if (e < -99) e = -99;
						val /= i10x(e);	/* Normalize */
					}
				}
			}
		}
		if (!er) {	/* Not error condition */
			if (sign == '-') *buf++ = sign;	/* Add a - if negative value */
			do {				/* Put decimal number */
				w = i10x(m);				/* Snip the highest digit d */
				d = val / w; val -= d * w;
				if (m == -1) *buf++ = XF_DPC;	/* Insert a decimal separarot if get into fractional part */
				*buf++ = '0' + d;			/* Put the digit */
			} while (--m >= -prec);			/* Output all digits specified by prec */
			if (fmt != 'f') {	/* Put exponent if needed */
				*buf++ = fmt;
				if (e < 0) {
					e = -e; *buf++ = '-';
				} else {
					*buf++ = '+';
				}
				*buf++ = '0' + e / 10;
				*buf++ = '0' + e % 10;
			}
		}
	}
	if (er) {	/* Error condition? */
		if (sign) *buf++ = sign;		/* Add sign if needed */
		do *buf++ = *er++; while (*er);	/* Put error symbol */
	}
	*buf = 0;	/* Term */
}
#endif	/* XF_USE_FLOAT */


/*----------------------------------------------*/
/* Put a character                              */
/*----------------------------------------------*/

void xputc (
	int chr				/* Character to be output */
)
{
	xfputc(xfunc_output, chr);	/* Output it to the default output device */
}


void xfputc (			/* Put a character to the specified device */
	void(*func)(int),	/* Pointer to the output function (null:strptr) */
	int chr				/* Character to be output */
)
{
	if (XF_CRLF && chr == '\n') xfputc(func, '\r');	/* CR -> CRLF */

	if (func) {
		func(chr);		/* Write a character to the output device */
	} else if (strptr) {
		 *strptr++ = chr;	/* Write a character to the memory */
	}
}



/*----------------------------------------------*/
/* Put a null-terminated string                 */
/*----------------------------------------------*/

void xputs (			/* Put a string to the default device */
	const char* str		/* Pointer to the string */
)
{
	xfputs(xfunc_output, str);
}


void xfputs (			/* Put a string to the specified device */
	void(*func)(int),	/* Pointer to the output function */
	const char*	str		/* Pointer to the string */
)
{
	while (*str) {			/* Put the string */
		xfputc(func, *str++);
	}
}



/*----------------------------------------------*/
/* Formatted string output                      */
/*----------------------------------------------*/
/*  xprintf("%d", 1234);			"1234"
    xprintf("%6d,%3d%%", -200, 5);	"  -200,  5%"
    xprintf("%-6u", 100);			"100   "
    xprintf("%ld", 12345678);		"12345678"
    xprintf("%llu", 0x100000000);	"4294967296"	<XF_USE_LLI>
    xprintf("%lld", -1LL);			"-1"			<XF_USE_LLI>
    xprintf("%04x", 0xA3);			"00a3"
    xprintf("%08lX", 0x123ABC);		"00123ABC"
    xprintf("%016b", 0x550F);		"0101010100001111"
    xprintf("%*d", 6, 100);			"   100"
    xprintf("%s", "String");		"String"
    xprintf("%5s", "abc");			"  abc"
    xprintf("%-5s", "abc");			"abc  "
    xprintf("%-5s", "abcdefg");		"abcdefg"
    xprintf("%-5.5s", "abcdefg");	"abcde"
    xprintf("%-.5s", "abcdefg");	"abcde"
    xprintf("%-5.5s", "abc");		"abc  "
    xprintf("%c", 'a');				"a"
    xprintf("%12f", 10.0);			"   10.000000"	<XF_USE_FP>
    xprintf("%.4E", 123.45678);		"1.2346E+02"	<XF_USE_FP>
*/

static void xvfprintf (
	void(*func)(int),	/* Pointer to the output function */
	const char*	fmt,	/* Pointer to the format string */
	va_list arp			/* Pointer to arguments */
)
{
	unsigned int r, i, j, w, f;
	int n, prec;
	char str[SZB_OUTPUT], c, d, *p, pad;
#if XF_USE_LLI
	long long v;
	unsigned long long uv;
#else
	long v;
	unsigned long uv;
#endif

	for (;;) {
		c = *fmt++;					/* Get a format character */
		if (!c) break;				/* End of format? */
		if (c != '%') {				/* Pass it through if not a % sequense */
			xfputc(func, c); continue;
		}
		f = w = 0;			 		/* Clear parms */
		pad = ' '; prec = -1;
		c = *fmt++;					/* Get first char of the sequense */
		if (c == '0') {				/* Flag: left '0' padded */
			pad = '0'; c = *fmt++;
		} else {
			if (c == '-') {			/* Flag: left justified */
				f = 2; c = *fmt++;
			}
		}
		if (c == '*') {				/* Minimum width from an argument */
			n = va_arg(arp, int);
			if (n < 0) {			/* Flag: left justified */
				n = 0 - n; f = 2;
			}
			w = n; c = *fmt++;
		} else {
			while (c >= '0' && c <= '9') {	/* Minimum width */
				w = w * 10 + c - '0';
				c = *fmt++;
			}
		}
		if (c == '.') {				/* Precision */
			c = *fmt++;
			if (c == '*') {				/* Precision from an argument */
				prec = va_arg(arp, int);
				c = *fmt++;
			} else {
				prec = 0;
				while (c >= '0' && c <= '9') {
					prec = prec * 10 + c - '0';
					c = *fmt++;
				}
			}
		}
		if (c == 'l') {		/* Prefix: Size is long */
			f |= 4; c = *fmt++;
#if XF_USE_LLI
			if (c == 'l') {	/* Prefix: Size is long long */
				f |= 8; c = *fmt++;
			}
#endif
		}
		if (!c) break;				/* End of format? */
		switch (c) {				/* Type is... */
		case 'b':					/* Unsigned binary */
			r = 2; break;
		case 'o':					/* Unsigned octal */
			r = 8; break;
		case 'd':					/* Signed decimal */
		case 'u':					/* Unsigned decimal */
			r = 10; break;
		case 'x':					/* Hexdecimal (lower case) */
		case 'X':					/* Hexdecimal (upper case) */
			r = 16; break;
		case 'c':					/* A character */
			xfputc(func, (char)va_arg(arp, int)); continue;
		case 's':					/* String */
			p = va_arg(arp, char*);		/* Get a pointer argument */
			if (!p) p = "";				/* Null ptr generates a null string */
			j = strlen(p);
			if (prec >= 0 && j > (unsigned int)prec) j = prec;	/* Limited length of string body */
			for ( ; !(f & 2) && j < w; j++) xfputc(func, pad);	/* Left pads */
			while (*p && prec--) xfputc(func, *p++);/* String body */
			while (j++ < w) xfputc(func, ' ');		/* Right pads */
			continue;
#if XF_USE_FP
		case 'f':					/* Float (decimal) */
		case 'e':					/* Float (e) */
		case 'E':					/* Float (E) */
			ftoa(p = str, va_arg(arp, double), prec, c);	/* Make fp string */
			for (j = strlen(p); !(f & 2) && j < w; j++) xfputc(func, pad);	/* Left pads */
			while (*p) xfputc(func, *p++);		/* Value */
			while (j++ < w) xfputc(func, ' ');	/* Right pads */
			continue;
#endif
		default:					/* Unknown type (passthrough) */
			xfputc(func, c); continue;
		}

		/* Get an integer argument and put it in numeral */
#if XF_USE_LLI
		if (f & 8) {	/* long long argument? */
			v = (long long)va_arg(arp, long long);
		} else {
			if (f & 4) {	/* long argument? */
				v = (c == 'd') ? (long long)va_arg(arp, long) : (long long)va_arg(arp, unsigned long);
			} else {		/* int/short/char argument */
				v = (c == 'd') ? (long long)va_arg(arp, int) : (long long)va_arg(arp, unsigned int);
			}
		}
#else
		if (f & 4) {	/* long argument? */
			v = (long)va_arg(arp, long);
		} else {		/* int/short/char argument */
			v = (c == 'd') ? (long)va_arg(arp, int) : (long)va_arg(arp, unsigned int);
		}
#endif
		if (c == 'd' && v < 0) {	/* Negative value? */
			v = 0 - v; f |= 1;
		}
		i = 0; uv = v;
		do {	/* Make an integer number string */
			d = (char)(uv % r); uv /= r;
			if (d > 9) d += (c == 'x') ? 0x27 : 0x07;
			str[i++] = d + '0';
		} while (uv != 0 && i < sizeof str);
		if (f & 1) str[i++] = '-';					/* Sign */
		for (j = i; !(f & 2) && j < w; j++) xfputc(func, pad);	/* Left pads */
		do xfputc(func, str[--i]); while (i != 0);	/* Value */
		while (j++ < w) xfputc(func, ' ');			/* Right pads */
	}
}


void xprintf (			/* Put a formatted string to the default device */
	const char*	fmt,	/* Pointer to the format string */
	...					/* Optional arguments */
)
{
	va_list arp;


	va_start(arp, fmt);
	xvfprintf(xfunc_output, fmt, arp);
	va_end(arp);
}


void xfprintf (			/* Put a formatted string to the specified device */
	void(*func)(int),	/* Pointer to the output function */
	const char*	fmt,	/* Pointer to the format string */
	...					/* Optional arguments */
)
{
	va_list arp;


	va_start(arp, fmt);
	xvfprintf(func, fmt, arp);
	va_end(arp);
}


void xsprintf (			/* Put a formatted string to the memory */
	char* buff,			/* Pointer to the output buffer */
	const char*	fmt,	/* Pointer to the format string */
	...					/* Optional arguments */
)
{
	va_list arp;


	strptr = buff;		/* Enable destination for memory */
	va_start(arp, fmt);
	xvfprintf(0, fmt, arp);
	va_end(arp);
	*strptr = 0;		/* Terminate output string */
	strptr = 0;			/* Disable destination for memory */
}



#if XF_USE_DUMP
/*----------------------------------------------*/
/* Dump a line of binary dump                   */
/*----------------------------------------------*/

void put_dump (
	const void* buff,		/* Pointer to the array to be dumped */
	unsigned long addr,		/* Heading address value */
	int len,				/* Number of items to be dumped */
	size_t width			/* Size of buff[0] (1, 2 or 4) */
)
{
	int i;
	const unsigned char *bp;
	const unsigned short *sp;
	const unsigned long *lp;


	xprintf("%08lX ", addr);		/* address */

	switch (width) {
	case sizeof (char):
		bp = buff;
		for (i = 0; i < len; i++) {		/* Hexdecimal dump in (char) */
			xprintf(" %02X", bp[i]);
		}
		xputs("  ");
		for (i = 0; i < len; i++) {		/* ASCII dump */
			xputc((unsigned char)((bp[i] >= ' ' && bp[i] <= '~') ? bp[i] : '.'));
		}
		break;
	case sizeof (short):
		sp = buff;
		do {							/* Hexdecimal dump in (short) */
			xprintf(" %04X", *sp++);
		} while (--len);
		break;
	case sizeof (long):
		lp = buff;
		do {							/* Hexdecimal dump in (short) */
			xprintf(" %08lX", *lp++);
		} while (--len);
		break;
	}

	xputc('\n');
}
#endif	/* XF_USE_DUMP */

#endif	/* XF_USE_OUTPUT */



#if XF_USE_INPUT
int (*xfunc_input)(void);	/* Pointer to the default input stream */

/*----------------------------------------------*/
/* Get a line from the input                    */
/*----------------------------------------------*/


int xgets (			/* 0:End of stream, 1:A line arrived */
	char* buff,		/* Pointer to the buffer */
	int len			/* Buffer length */
)
{
	int c, i;


	if (!xfunc_input) return 0;	/* No input function is specified */

	i = 0;
	for (;;) {
		c = xfunc_input();			/* Get a char from the incoming stream */
		if (c < 0 || c == '\r') break;	/* End of stream or CR? */
		if (c == '\b' && i) {		/* BS? */
			i--;
			if (XF_INPUT_ECHO) xputc(c);
			continue;
		}
		if (c >= ' ' && i < len - 1) {	/* Visible chars? */
			buff[i++] = c;
			if (XF_INPUT_ECHO) xputc(c);
		}
	}
	if (XF_INPUT_ECHO) {
		xputc('\r');
		xputc('\n');
	}
	buff[i] = 0;	/* Terminate with a \0 */
	return (int)(c == '\r');
}


/*----------------------------------------------*/
/* Get a value of integer string                */
/*----------------------------------------------*/
/*	"123 -5   0x3ff 0b1111 0377  w "
	    ^                           1st call returns 123 and next ptr
	       ^                        2nd call returns -5 and next ptr
                   ^                3rd call returns 1023 and next ptr
                          ^         4th call returns 15 and next ptr
                               ^    5th call returns 255 and next ptr
                                  ^ 6th call fails and returns 0
*/

int xatoi (			/* 0:Failed, 1:Successful */
	char **str,		/* Pointer to pointer to the string */
	long *res		/* Pointer to the valiable to store the value */
)
{
	unsigned long val;
	unsigned char c, r, s = 0;


	*res = 0;

	while ((c = **str) == ' ') (*str)++;	/* Skip leading spaces */

	if (c == '-') {		/* negative? */
		s = 1;
		c = *(++(*str));
	}

	if (c == '0') {
		c = *(++(*str));
		switch (c) {
		case 'x':		/* hexdecimal */
			r = 16; c = *(++(*str));
			break;
		case 'b':		/* binary */
			r = 2; c = *(++(*str));
			break;
		default:
			if (c <= ' ') return 1;	/* single zero */
			if (c < '0' || c > '9') return 0;	/* invalid char */
			r = 8;		/* octal */
		}
	} else {
		if (c < '0' || c > '9') return 0;	/* EOL or invalid char */
		r = 10;			/* decimal */
	}

	val = 0;
	while (c > ' ') {
		if (c >= 'a') c -= 0x20;
		c -= '0';
		if (c >= 17) {
			c -= 7;
			if (c <= 9) return 0;	/* invalid char */
		}
		if (c >= r) return 0;		/* invalid char for current radix */
		val = val * r + c;
		c = *(++(*str));
	}
	if (s) val = 0 - val;			/* apply sign if needed */

	*res = val;
	return 1;
}


#if XF_USE_FP
/*----------------------------------------------*/
/* Get a value of the real number string        */
/*----------------------------------------------*/
/* Float version of xatoi
*/

int xatof (			/* 0:Failed, 1:Successful */
	char **str,		/* Pointer to pointer to the string */
	double *res		/* Pointer to the valiable to store the value */
)
{
	double val;
	int s, f, e;
	unsigned char c;


	*res = 0;
	s = f = 0;

	while ((c = **str) == ' ') (*str)++;	/* Skip leading spaces */
	if (c == '-') {			/* Negative? */
		c = *(++(*str)); s = 1; 
	} else if (c == '+') {	/* Positive? */
		c = *(++(*str));
	}
	if (c == XF_DPC) {		/* Leading dp? */
		f = -1; 			/* Start at fractional part */
		c = *(++(*str));
	}
	if (c <= ' ') return 0;	/* Wrong termination? */
	val = 0;
	while (c > ' ') {		/* Get a value of decimal */
		if (c == XF_DPC) {	/* Embedded dp? */
			if (f < 0) return 0;	/* Wrong dp? */
			f = -1;			/* Enter fractional part */
		} else {
			if (c < '0' || c > '9') break;	/* End of decimal? */
			c -= '0';
			if (f == 0) {	/* In integer part */
				val = val * 10 + c;
			} else {		/* In fractional part */
				val += i10x(f--) * c;
			}
		}
		c = *(++(*str));
	}
	if (c > ' ') {	/* It may be an exponent */
		if (c != 'e' && c != 'E') return 0;	/* Wrong character? */
		c = *(++(*str));
		if (c == '-') {
			c = *(++(*str)); s |= 2;	/* Negative exponent */
		} else if (c == '+') {
			c = *(++(*str));			/* Positive exponent */
		}
		if (c <= ' ') return 0;	/* Wrong termination? */
		e = 0;
		while (c > ' ') {		/* Get value of exponent */
			c -= '0';
			if (c > 9) return 0;	/* Not a numeral? */
			e = e * 10 + c;
			c = *(++(*str));
		}
		val *= i10x((s & 2) ? -e : e);	/* Apply exponent */
	}

	if (s & 1) val = -val;	/* Negate sign if needed */

	*res = val;
	return 1;
}
#endif /* XF_USE_FP */

#endif /* XF_USE_INPUT */

Xprintf.h如下

/*------------------------------------------------------------------------*/
/* Universal string handler for user console interface  (C)ChaN, 2021     */
/*------------------------------------------------------------------------*/

#ifndef XPRINTF_DEF
#define XPRINTF_DEF
#include <string.h>

#ifdef __cplusplus
extern "C" {
#endif

#define XF_USE_OUTPUT	1	/* 1: Enable output functions */
#define	XF_CRLF			1	/* 1: Convert \n ==> \r\n in the output char */
#define	XF_USE_DUMP		1	/* 1: Enable put_dump function */
#define	XF_USE_LLI		1	/* 1: Enable long long integer in size prefix ll */
#define	XF_USE_FP		1	/* 1: Enable support for floating point in type e and f */
#define XF_DPC			'.'	/* Decimal separator for floating point */
#define XF_USE_INPUT	1	/* 1: Enable input functions */
#define	XF_INPUT_ECHO	0	/* 1: Echo back input chars in xgets function */

#if defined(__GNUC__) && __GNUC__ >= 10
#pragma GCC diagnostic ignored "-Wcast-function-type"
#endif

#if XF_USE_OUTPUT
#define xdev_out(func) xfunc_output = (void(*)(int))(func)
extern void (*xfunc_output)(int);
void xputc (int chr);
void xfputc (void (*func)(int), int chr);
void xputs (const char* str);
void xfputs (void (*func)(int), const char* str);
void xprintf (const char* fmt, ...);
void xsprintf (char* buff, const char* fmt, ...);
void xfprintf (void (*func)(int), const char* fmt, ...);
void put_dump (const void* buff, unsigned long addr, int len, size_t width);
#endif

#if XF_USE_INPUT
#define xdev_in(func) xfunc_input = (int(*)(void))(func)
extern int (*xfunc_input)(void);
int xgets (char* buff, int len);
int xatoi (char** str, long* res);
int xatof (char** str, double* res);
#endif

#ifdef __cplusplus
}
#endif

#endif

blinky_thread_entry.c中实现接口


static void xprintf_out_port(int ch)
{
    uint8_t val = ch;
    uart_send(&val,1);
}

static int xprintf_in_port(void)
{
    uint32_t len;
    uint8_t val;
    do
    {
        len = uart_read(&val,1);
    }while(len == 0);
    return val;
}

 

设置接口,blinky_thread_entry中初始化

    xdev_out(xprintf_out_port);

    xdev_in(xprintf_in_port);

 

测试代码如下

#include "xprintf.h"

/* Blinky Thread entry function */
void blinky_thread_entry (void * pvParameters)
{
    uart_init();
    xdev_out(xprintf_out_port);
    xdev_in(xprintf_in_port);

    while(1)
    {
        //static uint8_t rx_buffer[64];
        //uint32_t rlen = uart_read(rx_buffer,sizeof(rx_buffer));
        //if(rlen > 0)
        //{
        //    uart_send(rx_buffer,rlen);
        //}
            xprintf("%d\n", 1234);             /* "1234" */
            xprintf("%6d,%3d%%\n", -200, 5);   /* "  -200,  5%" */
            xprintf("%-6u\n", 100);            /* "100   " */
            xprintf("%ld\n", 12345678);        /* "12345678" */
            xprintf("%llu\n", 0x100000000);    /* "4294967296"   <XF_USE_LLI> */
            xprintf("%lld\n", -1LL);           /* "-1"           <XF_USE_LLI> */
            xprintf("%04x\n", 0xA3);           /* "00a3" */
            xprintf("%08lX\n", 0x123ABC);      /* "00123ABC" */
            xprintf("%016b\n", 0x550F);        /* "0101010100001111" */
            xprintf("%*d\n", 6, 100);          /* "   100" */
            xprintf("%s\n", "abcdefg");        /* "abcdefg" */
            xprintf("%5s\n", "abc");           /* "  abc" */
            xprintf("%-5s\n", "abc");          /* "abc  " */
            xprintf("%.5s\n", "abcdefg");      /* "abcde" */
            xprintf("%-5.2s\n", "abcdefg");    /* "ab   " */
            xprintf("%c\n", 'a');              /* "a" */
            xprintf("%12f\n", 10.0);           /* "   10.000000" <XF_USE_FP> */
            xprintf("%.4E\n", 123.45678);      /* "1.2346E+02"   <XF_USE_FP> */

            while(1)
            {
                    char input_buffer[32];
                    char* str = input_buffer;
                    xprintf("please input two int\r\n");
                    xgets(input_buffer, sizeof(input_buffer));
                    long a;
                    xatoi(&str,&a);
                    long b;
                    xatoi(&str,&b);
                    xprintf("%d+%d=%d\r\n",a,b,a+b);
            }
    }

 

 

测试效果如下

打印正常,输入正常

 

最新回复

这个xprintf库挺好用的,他相比RTT的shell有什么特长吗?   详情 回复 发表于 2024-7-25 08:25
点赞 关注

回复
举报

7063

帖子

11

TA的资源

版主

沙发
 

这个xprintf库挺好用的,他相比RTT的shell有什么特长吗?

 
 

回复
您需要登录后才可以回帖 登录 | 注册

查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/6 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表