Example use of printf() with I/O destination chioce(s) made in one function. Teensy 3

Status
Not open for further replies.

stevech

Well-known member
scroll through this code, and copy/paste if you wish.
Code:
/*
 Teensy3.x program to demonstrate use of printf() and redirection of its output to user-chosen I/O devices/files.
 As in ordinary c/c++, one can use printf() to format output text. Where and how the text goes to 1 or more destinations,
 is transparent to the user's program, and altered in one place. That place is _write() as discussed below. This is more common
 than Teensy's current Serial.printf() or Serial1.printf, or use of sprintf() then passing the result to some function.
 
 Compile and upload to the Teensy 3.x this program as-is.
 Open the serial monitor (icon in top right of Arduino IDE screen. This is the virtual serial port in the Teensy board. 
 You should see formatted text once a second, on the COMn port that is created by the Teensy-USB link.
 Now, connect the Teensy 3.x pin 1 (TX1) and GND to a 3.3V to RS232 or USB adapter connected to a PC. 
 You should see the same text coming out of the UART port of the Teensy 3.x, at 115200 baud.
 So at this point, you'll see that the printf() statement in the demo program is directed to two output places. 
 This is done in the function _write() which is below.
 
 
 Next, edit the code below to comment-out one of the "define PRINTF_xxxx" statements. This will disable the
 output for one or the other or both of the outputs.
 
 To change the way the redirects work, e.g., different UART or an LCD display or some such, alter 
 _write() to use some method, e.g., call a function to send the byte(s) to a function for an LCD display, or
 to a wireless link, or a telnet UDP port, etc. One could send the bytes to a file-write function too. 
 
 To use this in your program, copy all the code below then alter setup() and loop() as needed. Your program is
 responsible to create the destination device/file.
 
 TODO: a clever person could code in using a function pointer so the redirection can change at run time by changing
 the pointer, or setting it to NULL to mean that output stream is disabled.
 
 Thanks to Paul for the tip on overriding _write() in Print.cpp.
 
 cheers
 user: stevech on forum.pjrc.com
 
 
*/
#if !(defined(__MK20DX256__) || defined(__MK20DX128__))
  #error "USE TEENSY3.x FOR THIS DEMO OF printf()"
#endif

// One or more of these can receive output from _write() which follows...
#define PRINTF_SERIAL  // comment-out to disable
#define PRINTF_SERIAL1


#ifdef __cplusplus
  extern "C" {
    //__attribute__((weak)) omit this as used in _write() in Print.cpp
  
    // this function overrides the one of the same name in Print.cpp
    int _write(int file, char *ptr, int len)
    {
        // send chars to zero or more outputs
        for (int i = 0; i < len; i++)  {
          #ifdef PRINTF_SERIAL  // see #define at top of file
            Serial.print(ptr[i]);
          #endif
          #ifdef PRINTF_SERIAL1  // see #define at top of file
            Serial1.print(ptr[i]);
          #endif
        }
        return 0;
    }
  } // end extern "C" section
#endif


void setup() {
  #ifdef PRINTF_SERIAL
    Serial.begin(115200);
  #endif
  #ifdef PRINTF_SERIAL1
    Serial1.begin(115200);
  #endif
}

void loop() {
  int n = 0;
  float fp = 0.0;
  char buf[80];
  
  delay(5000);
  //Serial.println("here"); // print without using printf()
  while (1)  {
    delay(1000);
    fp += 0.99999;
    n = millis();
    //Serial.println();
    //Serial.printf("%3d 0x%.*X %5.5f %f %s\n", n, sizeof(int)*2, n, fp, sqrt(n), " Serial.printf");
    //sprintf(buf, "%3d 0x%.*X %5.5f %f %s\n", n, sizeof(int)*2, n, fp, pow(sqrt(n),2), " sprintf then Serial.printf");
    //Serial.printf("%s", buf);   
    
     printf("%3d 0x%.*X %5.5f %f %s\n", n, sizeof(int)*2, n, fp, sqrt(n), " printf per se !!!");
  }

}
 
Last edited:
Status
Not open for further replies.
Back
Top