目标:在stm32F103c6器件上,实现UART1的232通信,并将printf函数重新定向到UART1,进行调试debug等。
printf函数是底层函数,含于stdio.h头文件。因为在C语言中printf函数已经定义为默认输出到显示器的,若要想在串口上显示,那就需要重定向printf。例如将printf函数重定向到USART1上,这样就可以利用printf函数将单片机的数据打印到PC上的超级终端或者串口调试助手。为了调试方便,有很多在硬件板卡已经设计好的情况下,需要更改调试串口的就会用到这个重定向功能。
step1. 配置串口和中断等
/**
* @brief USART1 GPIO 配置,工作模式配置。9600 8-N-1
* @param PA9/PA10
* @retval 无
*/
void USART1_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
//|RCC_APB2Periph_AFIO
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//PA9-PA10
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//
// 将USART Rx的GPIO配置为浮空输入模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 将USART Tx的GPIO配置为推挽复用模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA9
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 配置串口的工作参数
// 配置波特率
USART_InitStructure.USART_BaudRate = 9600;//
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//
USART_InitStructure.USART_StopBits = USART_StopBits_1;//
USART_InitStructure.USART_Parity = USART_Parity_No;///
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//
// 配置工作模式,收发一起
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//
USART_Init(USART1, &USART_InitStructure); ; //
// 串口中断优先级配置
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 0-3;
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; //
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //
NVIC_Init(&NVIC_InitStructure); //
// 使能串口接收中断
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
// 使能串口
USART_Cmd(USART1, ENABLE);
}
step2. 编写中断函数,加入到文件stm32f10x_it.c中即可
/*******************************************************************************
* Function Name : USART1_IRQHandler
* Description : This function handles USART1 global interrupt request.
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void USART1_IRQHandler(void)
{
if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{
uint8_t data = USART_ReceiveData(USART1);
//queue_push(data);
}
}
step3. 编写printf重定向函数,加入头文件#include <stdio.h>和#include <stdlib.h>
//重定向c库函数printf到串口,重定向后可使用printf函数
int fputc(int ch, FILE *f)
{
/* 发送一个字节数据到串口 */
USART_SendData(USART1, (uint8_t) ch);
/* 等待发送完毕 */
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
return (ch);
}
///重定向c库函数scanf到串口,重写向后可使用scanf、getchar等函数
int fgetc(FILE *f)
{
/* 等待串口输入数据 */
while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);
return (int)USART_ReceiveData(USART1);
}