Ich schreibe Code für einen PIC18F46K22 mit dem C18-Compiler. Ich möchte den Wert einer Ganzzahl schreiben in ASCII über den USART zu meinem PC.
Für , es ist einfach:
Write1USART(n + 0x30); // 0x30 = '0'
Das würde funktionieren :
Write1USART((n/10) + 0x30);
Write1USART((n%10) + 0x30);
Aber das ist wahrscheinlich nicht der schnellste Weg.
Gibt es irgendwo da draußen eine eingebaute Funktion oder eine Funktion, die ich einfach verwenden könnte, anstatt meine eigene zu rollen ?
Der C18-Compiler unterstützt die Number-to-ASCII-Familie von Standard-C-Funktionen in stdlib.h : itoa()
, ltoa()
, ultoa()
et cetera.
Je nachdem, welchen Compiler / stdlib.h Sie haben, wäre der relevante Funktionsprototyp:
extern char * itoa(char * buf, int val, int base); // signed int
extern char * utoa(char * buf, unsigned val, int base); // unsigned int
oder
extern char * itoa(char * buf, int val); // signed int
extern char * utoa(char * buf, unsigned val); // unsigned int
Wenn Sie nach einem relativ robusten, eingebauten " Standard "-C-Weg suchen, um Ihre Zahlen in ASCII-Strings umzuwandeln, sollten Sie diese xtoa()
Funktionen verwenden.
Wenn Sie andererseits gezwungen sind, ein paar zusätzliche Zyklen oder Bytes an Speicher aus dem endgültigen Code herauszuholen, sind einige der anderen Antworten auf Ihre Frage der richtige Weg.
itoa
Vielleicht stammt es aus dem alten Borland C, aber es hat es nie in ISO C geschafft. wenn sie da sind, benutze sie.Sie könnten eine Funktion ausprobieren, die die Brute-Force-Methode zum Konvertieren in eine Zeichenfolge verwendet. Die folgende Funktion verwendet weder den Modulo-Operator noch die Multiplikation. Es gibt eine Zeichenfolge zurück.
/*
* Create a function that will return a string.
* It accepts 'inputValue' that is up to 255, but you can make it an int or longint...
* ...after you make some edits in the function.
* inputValue: 5 7 6
* Digits: 1st 2nd 3rd
*/
unsigned char* returnString(unsigned char inputValue)
{
static unsigned char processedString[4]; // Return a string of 3 digits.
unsigned char firstDigitCounter = 0; // Brute-force counter for first digit.
unsigned char secondDigitCounter = 0; // Brute-force counter for second digit.
if (inputValue > 99) // If we have a 3 digit number,
{
while (inputValue > 99) // Until our number is 3 digits, i.e. bigger than 99,
{
inputValue -= 100; // Subtract 100 and..
firstDigitCounter++; //.. increment first digit.
}
while (inputValue > 9) // Until our number is 3 digits, i.e. bigger than 9,
{
inputValue -= 10; // Subtract 10 and..
secondDigitCounter++; //.. increment second digit.
}
// Now, we have left the 'inputValue' as a single digit.
processedString[0] = firstDigitCounter + 0x30; // First digit
processedString[1] = secondDigitCounter + 0x30; // Second digit
processedString[2] = inputValue + 0x30; // Third digit
processedString[3] = '\0'; // String terminator.
}
else // If we have a 2 digit number,
{
while (inputValue > 9) // Until our number is 3 digits, i.e. bigger than 99,
{
inputValue -= 10; // Subtract 10 and..
secondDigitCounter++; //.. increment second digit.
}
processedString[0] = secondDigitCounter + 0x30; // Second digit
processedString[1] = inputValue + 0x30; // Third digit
processedString[2] = '\0'; // String terminator.
}
return processedString; // Return the processed string.
}
Pastebin des obigen Codes.
Ich habe sprintf();
vorher verwendet. Abgesehen davon, dass es mit der Formatierung bequem ist, bin ich mir nicht ganz sicher, ob es schnell ist und einen geringen Platzbedarf hat. Es kommt mit .
#include <stdio.h>
const uint8_t stringLength = 16;
char string[ stringLength ] = { 0 };
volatile uint32_t measurement = 12345;
sprintf( string , "Measured: %lu milliseconds\n" , measurement );
uint8_t charCounter = 0;
while ( ( charCounter < stringLength ) and ( string[ charCounter ] != 0x00 ) ) {
serialByteOut( string[ charCounter ] ); // Send a single character
charCounter++;
}
Wo measurement
wird eine 32-Bit-Ganzzahl in einer ISR aktualisiert, die ich drucken möchte, und string
ist der Ausgabepuffer. %lu
gibt an, dass eine lange vorzeichenlose Ganzzahl gedruckt werden soll, und \n ist ein Zeilenumbruch.
Die Verwendung ist weitgehend die gleiche wie die printf();
Dokumentation ist umfangreich und kann leicht im Internet auf verschiedenen Websites gefunden werden: http://linux.die.net/man/3/sprintf
Ich habe selbst eine Funktion erstellt:
void writeInteger(unsigned long input) {
unsigned long start = 1;
unsigned long counter;
while (start*10 <= input)
start *= 10;
for (counter = start; counter >= 1; counter /= 10)
Write1USART(((input / counter) % 10) + 0x30);
}
Sie könnten dies versuchen:
void writeInteger(unsigned i)
{
if (i > 9)
writeInteger(i/10);
write1USART(i % 10 + '0');
}
Kortuk
Benutzer17592
unsigned long
.Peter Becker
n + 0x30
mit einem Kommentar . Sowohl C als auch C++ erfordern, dass die Ziffern - benachbarte ansteigende Werte haben, also immer funktionieren und klarer sind.0x30 = '0'
n + '0'
0
9
n + '0'