使用JLink SEGGER_RTT_printf()函数实现打印浮点数

问题:
源码SEGGER_RTT_printf()函数无法打印浮点数。

思路:
修改SEGGER_RTT_printf()函数来达到打印浮点数。

参考文章:https://blog.csdn.net/qq_36075612/article/details/123432025

对参考文章的做法进行优化:
参考文章部分,目前只能打印浮点数小数点后3位,如果打印小数点后6位,会出现显示有点怪怪的。

修改源码:
下面为修改后的函数

static unsigned char __GetNumber(int _tempInt)
{
	unsigned char tempCount = 0;
	
	while(_tempInt != 0)
    {
        _tempInt /= 10;
        ++tempCount;
    }
	
	return tempCount;
}

/*********************************************************************
*
*       Public code
*
**********************************************************************
*/
/*********************************************************************
*
*       SEGGER_RTT_vprintf
*
*  Function description
*    Stores a formatted string in SEGGER RTT control block.
*    This data is read by the host.
*
*  Parameters
*    BufferIndex  Index of "Up"-buffer to be used. (e.g. 0 for "Terminal")
*    sFormat      Pointer to format string
*    pParamList   Pointer to the list of arguments for the format string
*
*  Return values
*    >= 0:  Number of bytes which have been stored in the "Up"-buffer.
*     < 0:  Error
*/
int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList) 
{
	char c;
	SEGGER_RTT_PRINTF_DESC BufferDesc;
	int v;
	unsigned char numberCount;
	int powN;
	unsigned NumDigits;
	unsigned FormatFlags;
	unsigned FieldWidth;
	char acBuffer[SEGGER_RTT_PRINTF_BUFFER_SIZE];

	BufferDesc.pBuffer        = acBuffer;
	BufferDesc.BufferSize     = SEGGER_RTT_PRINTF_BUFFER_SIZE;
	BufferDesc.Cnt            = 0u;
	BufferDesc.RTTBufferIndex = BufferIndex;
	BufferDesc.ReturnValue    = 0;

	numberCount = 0;

	do 
	{
		c = *sFormat;
		sFormat++;
		if (c == 0u) 
		{
			break;
		}
		if (c == '%') 
		{
			//
			// Filter out flags
			//
			FormatFlags = 0u;
			v = 1;
			do 
			{
				c = *sFormat;
				switch (c) 
				{
					case '-': FormatFlags |= FORMAT_FLAG_LEFT_JUSTIFY; sFormat++; break;
					case '0': FormatFlags |= FORMAT_FLAG_PAD_ZERO;     sFormat++; break;
					case '+': FormatFlags |= FORMAT_FLAG_PRINT_SIGN;   sFormat++; break;
					case '#': FormatFlags |= FORMAT_FLAG_ALTERNATE;    sFormat++; break;
					default:  v = 0; break;
				}
			} while (v);
			//
			// filter out field with
			//
			FieldWidth = 0u;
			do 
			{
				c = *sFormat;
				if ((c < '0') || (c > '9')) 
				{
					break;
				}
				sFormat++;
				FieldWidth = (FieldWidth * 10u) + ((unsigned)c - '0');
			} while (1);

			//
			// Filter out precision (number of digits to display)
			//
			NumDigits = 0u;
			c = *sFormat;
			if (c == '.') 
			{
				sFormat++;
				do 
				{
					c = *sFormat;
					if ((c < '0') || (c > '9')) 
					{
						break;
					}
					sFormat++;
					NumDigits = NumDigits * 10u + ((unsigned)c - '0');
				} while (1);
			}
			//
			// Filter out length modifier
			//
			c = *sFormat;
			do 
			{
				if ((c == 'l') || (c == 'h')) 
				{
					sFormat++;
					c = *sFormat;
				} 
				else 
				{
					break;
				}
			} while (1);
			//
			// Handle specifiers
			//
			switch (c) 
			{
				case 'c': 
				{
					char c0;
					v = va_arg(*pParamList, int);
					c0 = (char)v;
					_StoreChar(&BufferDesc, c0);
					break;
				}
				case 'd':
					v = va_arg(*pParamList, int);
					_PrintInt(&BufferDesc, v, 10u, NumDigits, FieldWidth, FormatFlags);
					break;
				case 'u':
					v = va_arg(*pParamList, int);
					_PrintUnsigned(&BufferDesc, (unsigned)v, 10u, NumDigits, FieldWidth, FormatFlags);
					break;
				case 'x':
				case 'X':
					v = va_arg(*pParamList, int);
					_PrintUnsigned(&BufferDesc, (unsigned)v, 16u, NumDigits, FieldWidth, FormatFlags);
					break;
				case 's':
				{
					const char * s = va_arg(*pParamList, const char *);
					do 
					{
						c = *s;
						s++;
						if (c == '\0') 
						{
							break;
						}
						_StoreChar(&BufferDesc, c);
					} while (BufferDesc.ReturnValue >= 0);
				}
					break;
				case 'p':
					v = va_arg(*pParamList, int);
					_PrintUnsigned(&BufferDesc, (unsigned)v, 16u, 8u, 8u, 0u);
					break;
				case '%':
					_StoreChar(&BufferDesc, '%');
					break;
				// Add the ability to output floating point numbers. It has two decimal places by default.
				#if 0
				case 'f':
				case 'F':
				{
					char ch[10]={0};
					const char * s=ch;
					double a = va_arg(*pParamList, double);
					sprintf(ch,"%4.6f",a);
					do
					{
						c = *s;
						s++;
						if (c == '\0') break;
						_StoreChar(&BufferDesc, c);
					}while(BufferDesc.ReturnValue >= 0);
				}
					break;
				#else
				case 'f':
				case 'F': 
				{
					float fv = (float)va_arg(*pParamList, double);    // Retrieves the input floating point value
					if(fv < 0) 
					{
						_StoreChar(&BufferDesc, '-');          // Judge the sign
						fv *= -1;
					}
					v = abs((int)fv);                                 // Take the positive integer part
					numberCount = __GetNumber(v);					// 获取正数部分的位数
					_PrintInt(&BufferDesc, v, 10u, numberCount, FieldWidth, FormatFlags);  // According to an integer
					_StoreChar(&BufferDesc, '.');   		  // Display decimal point
					if(NumDigits > 9) NumDigits = 9;
					powN = pow(10,NumDigits);
					fv = fv - v;
					v = abs((int)(fv * powN));    

					v = v % powN;

					_PrintInt(&BufferDesc, v, 10u, NumDigits, FieldWidth, FormatFlags);          // Display three decimal places
				}
					break;
				#endif
				default:
					break;
			}
			sFormat++;
		} 
		else 
		{
			_StoreChar(&BufferDesc, c);
		}
	} while (BufferDesc.ReturnValue >= 0);

	if (BufferDesc.ReturnValue > 0) 
	{
		//
		// Write remaining data, if any
		//
		if (BufferDesc.Cnt != 0u) 
		{
			SEGGER_RTT_Write(BufferIndex, acBuffer, BufferDesc.Cnt);
		}
		BufferDesc.ReturnValue += (int)BufferDesc.Cnt;
	}
	return BufferDesc.ReturnValue;
}

主要修改部分:

// Add the ability to output floating point numbers. It has two decimal places by default.
				#if 0
				case 'f':
				case 'F':
				{
					char ch[10]={0};
					const char * s=ch;
					double a = va_arg(*pParamList, double);
					sprintf(ch,"%4.6f",a);
					do
					{
						c = *s;
						s++;
						if (c == '\0') break;
						_StoreChar(&BufferDesc, c);
					}while(BufferDesc.ReturnValue >= 0);
				}
					break;
				#else
				case 'f':
				case 'F': 
				{
					float fv = (float)va_arg(*pParamList, double);    // Retrieves the input floating point value
					if(fv < 0) 
					{
						_StoreChar(&BufferDesc, '-');          // Judge the sign
						fv *= -1;
					}
					v = abs((int)fv);                                 // Take the positive integer part
					numberCount = __GetNumber(v);					// 获取正数部分的位数
					_PrintInt(&BufferDesc, v, 10u, numberCount, FieldWidth, FormatFlags);  // According to an integer
					_StoreChar(&BufferDesc, '.');   		  // Display decimal point
					if(NumDigits > 9) NumDigits = 9;
					powN = pow(10,NumDigits);
					fv = fv - v;
					v = abs((int)(fv * powN));    

					v = v % powN;

					_PrintInt(&BufferDesc, v, 10u, NumDigits, FieldWidth, FormatFlags);          // Display three decimal places
				}
					break;
				#endif

测试修改后的函数:

float Float1 = 11.012021568F;
void __TestRTT_Print(void)
{
//	float Float1 = 11.012021568F;
	int8_t Int_8 = -2;
	uint8_t uInt_8 = 100;
	uint16_t uInt16 = 1000;
	uint32_t uInt32 = 10000;
	int16_t  Int16 = -1000;
	int32_t  Int32 = -10000;
	
	SEGGER_RTT_printf(0,"Float1 = %0.10F\r\n",Float1);// 打印浮点数正数
	SEGGER_RTT_printf(0,"-Float1 = %.10f\r\n",-Float1);//打印浮点数负数
	SEGGER_RTT_printf(0,"Int_8 = %d\r\n",Int_8);//打印signe char负数
	SEGGER_RTT_printf(0,"uInt_8 = %d\r\n",uInt_8);//打印unsigne char正数
	SEGGER_RTT_printf(0,"uInt16 = %d\r\n",uInt16);
	SEGGER_RTT_printf(0,"uInt32 = %d\r\n",uInt32);
	SEGGER_RTT_printf(0,"Int16 = %d\r\n",Int16);
	SEGGER_RTT_printf(0,"Int32 = %d\r\n",Int32);
	
	delay_ms(100);
}

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

结果说明:
这里出现的小数点后6位之后对不上问题。
比如打印结果是:11.012022018,在 Debug 测试时的变量值:11.012022

在这里插入图片描述

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值