This is the 22nd day of my participation in Gwen Challenge

Printf function is often used to print debugging information when debugging programs. In STM103 microcontroller, printf function can only be used in serial port 1 by default. Sometimes serial port 1 is occupied, and it is troublesome to output debugging information. Now I’ll summarize how to use the printf function on other serial ports. Here we use the routines for positive atoms to illustrate. The default initialization code for serial port 1 is as follows:

#if 1 #pragma import(__use_no_semihosting) }; FILE __stdout; // define _sys_exit() to avoid using semi-host mode _sys_exit(int x) {x = x; } // define fputc function int fputc(int ch, FILE *f) {while((USART1->SR & 0X40) == 0); USART1->DR = (u8) ch; return ch; } #endif void uart_init(u32 bound) {GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE); // Enable USART1, GPIOA clock //USART1_TX gpioa. 9 gPIo_initstructure. GPIO_Pin = GPIO_Pin_9; //PA.9 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // reuse push-pull output GPIO_Init(GPIOA, &GPIO_InitStructure); //USART1_RX gpioa. 10 Initializes gpio_initstructure. GPIO_Pin = GPIO_Pin_10; //PA10 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // Float GPIO_Init(GPIOA, &GPIO_InitStructure); NVIC_IRQChannel = USART1_IRQn; nvic_initStructure.nvic_irqChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3 ; // Preempt priority 3 nvic_initstructure. NVIC_IRQChannelSubPriority = 3; // Subpriority 3 nvic_initstructure. NVIC_IRQChannelCmd = ENABLE; // enable NVIC_Init(&NVIC_InitStructure) for IRQ channels; //USART initializes usart_initstructure. USART_BaudRate = bound; // Serial port baud rate usart_initstructure. USART_WordLength = USART_WordLength_8b; // 8-bit data format usARt_initstructure. USART_StopBits = USART_StopBits_1; // a stop bit usart_initstructure. USART_Parity = USART_Parity_No; // None parity bit usart_initstructure. USART_HardwareFlowControl = USART_HardwareFlowControl_None; . / / there is no hardware flow control USART_InitStructure USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // USART_Init(USART1, &USART_InitStructure); // Initialize serial port 1 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); USART_Cmd(USART1, ENABLE); // Enable serial port 1}Copy the code

The above section of the initialization function uart_init () is the setup for the printf function, which by default outputs data through serial port 1. If we now want to redefine the printf function to serial port 3, we can cut some of the code above uart_init () to the front of the serial port 3 initialization function, and change serial port 1 in the fputc () function to serial port 3. The modified code is as follows: Serial port 1 initialization code

Void uart_init(u32 bound) {//GPIO port set GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE); // Enable USART1, GPIOA clock //USART1_TX gpioa. 9 gPIo_initstructure. GPIO_Pin = GPIO_Pin_9; //PA.9 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // reuse push-pull output GPIO_Init(GPIOA, &GPIO_InitStructure); //USART1_RX gpioa. 10 Initializes gpio_initstructure. GPIO_Pin = GPIO_Pin_10; //PA10 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // Float GPIO_Init(GPIOA, &GPIO_InitStructure); NVIC_IRQChannel = USART1_IRQn; nvic_initStructure.nvic_irqChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3 ; // Preempt priority 3 nvic_initstructure. NVIC_IRQChannelSubPriority = 3; // Subpriority 3 nvic_initstructure. NVIC_IRQChannelCmd = ENABLE; // enable NVIC_Init(&NVIC_InitStructure) for IRQ channels; //USART initializes usart_initstructure. USART_BaudRate = bound; // Serial port baud rate usart_initstructure. USART_WordLength = USART_WordLength_8b; // 8-bit data format usARt_initstructure. USART_StopBits = USART_StopBits_1; // a stop bit usart_initstructure. USART_Parity = USART_Parity_No; // None parity bit usart_initstructure. USART_HardwareFlowControl = USART_HardwareFlowControl_None; . / / there is no hardware flow control USART_InitStructure USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // USART_Init(USART1, &USART_InitStructure); // Initialize serial port 1 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); USART_Cmd(USART1, ENABLE); // Enable serial port 1}Copy the code

Serial port 3 initialization code

#if 1 #pragma import(__use_no_semihosting) }; FILE __stdout; // define _sys_exit() to avoid using semi-host mode _sys_exit(int x) {x = x; } // define fputc function int fputc(int ch, FILE *f) {while((USART3->SR & 0X40) == 0); USART3->DR = (u8) ch; return ch; } #endif void uart3_init(u16 baud) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); USART_InitStructure.USART_BaudRate = baud; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_Init(USART3, &USART_InitStructure); USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); USART_Cmd(USART3, ENABLE); }Copy the code

When you modify the printf function, you can print it through serial port 3. The core code for setting the printf function is as follows:

Struct __FILE {int handle; struct __FILE {int handle; }; FILE __stdout; // define _sys_exit() to avoid using semi-host mode _sys_exit(int x) {x = x; } // define fputc function int fputc(int ch, FILE *f) {while((USART3->SR & 0X40) == 0); USART3->DR = (u8) ch; return ch; }Copy the code

As you can see from the above functions, to redefine the output serial port of the printf function, you only need to modify the definition of the serial port in the fputc() function.