问题:
源码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