using printf for two uart - Page 1
Forum section: electronics / general

author: tariq
author_rank: Contributor
timestamp: July 18, 2020, 02:31:35 pm
content: himy printf function is in attachment. in this function printf only sends data by usart1.i want to send data by printf with choosing my uart channelfor exampleprintf(&huart2,"HELLO WORLD"%d,variable);can any one help me?Thank you.

author: ebclr
author_rank: Super Contributor
timestamp: July 18, 2020, 03:48:41 pm
content: Most compilers relay on the Putchar to send print, take a look at your put char function and change that one , according to the com needed

author: tariq
author_rank: Contributor
timestamp: July 18, 2020, 04:23:04 pm
content: can you give me an example please?

author: Nominal Animal
author_rank: Super Contributor
timestamp: July 18, 2020, 04:51:09 pm
content: If you useCode:#ifdef __GNUC__#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)#else#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)#endif /* __GNUC__ */static UART_HandleTypeDef *printf_uart = &huart1;void printf_to(UART_HandleTypeDef *uart){printf_uart = uart;}PUTCHAR_PROTOTYPE{HAL_UART_Transmit(printf_uart, (uint8_t *)&ch, 1, HAL_MAX_DELAY);return ch;}Then you can useprintf_to(&huart1);or similar to change which UART is used for futureprintf()s.

author: phil from seattle
author_rank: Super Contributor
timestamp: July 18, 2020, 04:53:57 pm
content: In the past, sprintf has been the go to way of using printf formatting for arbitrary outputs. You do somethinglike:Code:char buffer, * bp;sprintf(buffer, /* normal printf stuff */);bp = buffer;while (*bp != 0) putchar(streamhw, *bp++);you supply putchar, what ever library you are using supplies sprintf.Teensyduino has added printf to the stream class so I can do:Code:Serial2.begin(115400);Serial2.printf(...)Which is way better than Arduino's clunky-assed print and println.

author: newbrain
author_rank: Super Contributor
timestamp: July 18, 2020, 09:37:35 pm
content: Which library are you using?Many libraries that try to be C standard compliant (eg: newlib-nano) provide a vprintf function, which takes ava_listargument, instead of being variadic as printf.In fact, printf is often implemented using vprintf.vprintf() can easily be used to build your own special printf(), exactly as the one you prototyped in the OP - well, apart from the syntax error...Code:/* Global variable to hold the UART in use */extern UART_HandleTypeDef *currentUart;int printfUart(UART_HandleTypeDef *uart, const char *format, ...){/* Assign the passed UARAT handle to a global variable, to be used in printchar */currentUart = uart;va_list va;va_start(va, format);const int returnValue = vprintf(format, va);va_end(va);return returnValue;}ThecurrentUartvariable (of type UART_HandleTypeDef *) should be visible and used by yourputchar()to send the character to the right UART.Code:[...]UART_HandleTypeDef *currentUart;PUTCHAR_PROTOTYPE{HAL_UART_Transmit(currentUart, (uint8_t *)&ch, 1, HAL_MAX_DELAY);return ch;}Reentrancy is not supported by the simple implementation above (important if you have a degree of parallelism, or if you want to call the function from an ISR - you shouldn't in any case, though).If you do not have a vprintf, I often usethis very small implementation of the printf family.Note: code not tested. I take no liability if your toothbrush catches fire or your cat becomes green.

author: westfw
author_rank: Super Contributor
timestamp: July 19, 2020, 04:54:36 am
content: Quotethat would usually be "fprintf(file, format, ...);"How you associate a particular "file" with a particular UART (or "whatever") depends on the environment you're using.Which you failed to mention.

author: abyrvalg
author_rank: Frequent Contributor
timestamp: July 19, 2020, 06:57:34 am
content: If the hardware supports using pointers to peripherals the “file” param can be a just a pointer to uart cast to FILE * (and back in fputc).

author: westfw
author_rank: Super Contributor
timestamp: July 20, 2020, 07:55:53 am
content: QuoteIt looks like in current microcontrollers with newlib or newlib nano, you would use "funopen" or "fopencookie", depending on the exact "featrues" enabled. (I wrote something for Energia some years ago using fopencookie(), and it doesn't work any more (hmm. maybe it was MPIDE that worked.) However, funopen() works, now, on ARM-based Arduinos...Code:int myWrite(void *cookie, const char *buf, int n){Stream *s = (Stream *)cookie;// Serial.println("myWrite");return s->write((uint8_t*)buf, n);}FILE *myOut;void setup() {pinMode(LED, OUTPUT);Serial.begin(115200);while (!Serial);myOut = funopen((void *)(&Serial), NULL, myWrite, NULL, NULL);setlinebuf(myOut);fprintf(myOut, "This is a test of funopen() based printf\n");}