在 RT-Thread 中,有一个打印函数 rt_kprintf() 供用户使用,方便在调试的时候输出各种信息。如果 要想使用 rt_kprintf(),则必须将控制台重映射到 rt_kprintf(),这个控制台可以是串口、CAN、USB、 以太网等输出设备,用的最多的就是串口,接下来我们讲解下如何将串口重定向到 rt_kprintf()。[参考野火F103]
添加bsp_usart.c, bsp_usart.h
bsp_usart.c
#include "bsp_usart.h"
/**
* @brief 配置嵌套向量中断控制器NVIC
* @param 无
* @retval 无
*/
static void NVIC_Configuration(void)
{
;
NVIC_InitTypeDef NVIC_InitStructure
/* 嵌套向量中断控制器组选择 */
(NVIC_PriorityGroup_2);
NVIC_PriorityGroupConfig
/* 配置USART为中断源 */
.NVIC_IRQChannel = DEBUG_USART_IRQ;
NVIC_InitStructure/* 抢断优先级*/
.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure/* 子优先级 */
.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure/* 使能中断 */
.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure/* 初始化配置NVIC */
(&NVIC_InitStructure);
NVIC_Init}
/**
* @brief USART GPIO 配置,工作参数配置
* @param 无
* @retval 无
*/
void USART_Config(void)
{
;
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure
// 打开串口GPIO的时钟
(DEBUG_USART_GPIO_CLK, ENABLE);
DEBUG_USART_GPIO_APBxClkCmd
// 打开串口外设的时钟
(DEBUG_USART_CLK, ENABLE);
DEBUG_USART_APBxClkCmd
// 将USART Tx的GPIO配置为推挽复用模式
.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);
GPIO_Init
// 将USART Rx的GPIO配置为浮空输入模式
.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);
GPIO_Init
// 配置串口的工作参数
// 配置波特率
.USART_BaudRate = DEBUG_USART_BAUDRATE;
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_InitStructure// 完成串口的初始化配置
(DEBUG_USARTx, &USART_InitStructure);
USART_Init
// 串口中断优先级配置
();
NVIC_Configuration
// 使能串口接收中断
(DEBUG_USARTx, USART_IT_RXNE, ENABLE);
USART_ITConfig
// 使能串口
(DEBUG_USARTx, ENABLE);
USART_Cmd}
/***************** 发送一个字节 **********************/
void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch)
{
/* 发送一个字节数据到USART */
(pUSARTx,ch);
USART_SendData
/* 等待发送数据寄存器为空 */
while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
}
/****************** 发送8位的数组 ************************/
void Usart_SendArray( USART_TypeDef * pUSARTx, uint8_t *array, uint16_t num)
{
uint8_t i;
for(i=0; i<num; i++)
{
/* 发送一个字节数据到USART */
(pUSARTx,array[i]);
Usart_SendByte
}
/* 等待发送完成 */
while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET);
}
/***************** 发送字符串 **********************/
void Usart_SendString( USART_TypeDef * pUSARTx, char *str)
{
unsigned int k=0;
do
{
( pUSARTx, *(str + k) );
Usart_SendByte++;
k} while(*(str + k)!='\0');
/* 等待发送完成 */
while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET)
{}
}
/***************** 发送一个16位数 **********************/
void Usart_SendHalfWord( USART_TypeDef * pUSARTx, uint16_t ch)
{
uint8_t temp_h, temp_l;
/* 取出高八位 */
= (ch&0XFF00)>>8;
temp_h /* 取出低八位 */
= ch&0XFF;
temp_l
/* 发送高八位 */
(pUSARTx,temp_h);
USART_SendDatawhile (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
/* 发送低八位 */
(pUSARTx,temp_l);
USART_SendDatawhile (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
}
///重定向c库函数printf到串口,重定向后可使用printf函数
int fputc(int ch, FILE *f)
{
/* 发送一个字节数据到串口 */
(DEBUG_USARTx, (uint8_t) ch);
USART_SendData
/* 等待发送完毕 */
while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET);
return (ch);
}
///重定向c库函数scanf到串口,重写向后可使用scanf、getchar等函数
int fgetc(FILE *f)
{
/* 等待串口输入数据 */
while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_RXNE) == RESET);
return (int)USART_ReceiveData(DEBUG_USARTx);
}
bsp_usart.h
#ifndef __USART_H
#define __USART_H
#include "stm32f10x.h"
#include <stdio.h>
/**
* 串口宏定义,不同的串口挂载的总线和IO不一样,移植时需要修改这几个宏
* 1-修改总线时钟的宏,uart1挂载到apb2总线,其他uart挂载到apb1总线
* 2-修改GPIO的宏
*/
// 串口1-USART1
#define DEBUG_USARTx USART1
#define DEBUG_USART_CLK RCC_APB2Periph_USART1
#define DEBUG_USART_APBxClkCmd RCC_APB2PeriphClockCmd
#define DEBUG_USART_BAUDRATE 115200
// USART GPIO 引脚宏定义
#define DEBUG_USART_GPIO_CLK (RCC_APB2Periph_GPIOA)
#define DEBUG_USART_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd
#define DEBUG_USART_TX_GPIO_PORT GPIOA
#define DEBUG_USART_TX_GPIO_PIN GPIO_Pin_9
#define DEBUG_USART_RX_GPIO_PORT GPIOA
#define DEBUG_USART_RX_GPIO_PIN GPIO_Pin_10
#define DEBUG_USART_IRQ USART1_IRQn
#define DEBUG_USART_IRQHandler USART1_IRQHandler
// 串口2-USART2
//#define DEBUG_USARTx USART2
//#define DEBUG_USART_CLK RCC_APB1Periph_USART2
//#define DEBUG_USART_APBxClkCmd RCC_APB1PeriphClockCmd
//#define DEBUG_USART_BAUDRATE 115200
//// USART GPIO 引脚宏定义
//#define DEBUG_USART_GPIO_CLK (RCC_APB2Periph_GPIOA)
//#define DEBUG_USART_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd
//
//#define DEBUG_USART_TX_GPIO_PORT GPIOA
//#define DEBUG_USART_TX_GPIO_PIN GPIO_Pin_2
//#define DEBUG_USART_RX_GPIO_PORT GPIOA
//#define DEBUG_USART_RX_GPIO_PIN GPIO_Pin_3
//#define DEBUG_USART_IRQ USART2_IRQn
//#define DEBUG_USART_IRQHandler USART2_IRQHandler
// 串口3-USART3
//#define DEBUG_USARTx USART3
//#define DEBUG_USART_CLK RCC_APB1Periph_USART3
//#define DEBUG_USART_APBxClkCmd RCC_APB1PeriphClockCmd
//#define DEBUG_USART_BAUDRATE 115200
//// USART GPIO 引脚宏定义
//#define DEBUG_USART_GPIO_CLK (RCC_APB2Periph_GPIOB)
//#define DEBUG_USART_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd
//
//#define DEBUG_USART_TX_GPIO_PORT GPIOB
//#define DEBUG_USART_TX_GPIO_PIN GPIO_Pin_10
//#define DEBUG_USART_RX_GPIO_PORT GPIOB
//#define DEBUG_USART_RX_GPIO_PIN GPIO_Pin_11
//#define DEBUG_USART_IRQ USART3_IRQn
//#define DEBUG_USART_IRQHandler USART3_IRQHandler
// 串口4-UART4
//#define DEBUG_USARTx UART4
//#define DEBUG_USART_CLK RCC_APB1Periph_UART4
//#define DEBUG_USART_APBxClkCmd RCC_APB1PeriphClockCmd
//#define DEBUG_USART_BAUDRATE 115200
//// USART GPIO 引脚宏定义
//#define DEBUG_USART_GPIO_CLK (RCC_APB2Periph_GPIOC)
//#define DEBUG_USART_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd
//
//#define DEBUG_USART_TX_GPIO_PORT GPIOC
//#define DEBUG_USART_TX_GPIO_PIN GPIO_Pin_10
//#define DEBUG_USART_RX_GPIO_PORT GPIOC
//#define DEBUG_USART_RX_GPIO_PIN GPIO_Pin_11
//#define DEBUG_USART_IRQ UART4_IRQn
//#define DEBUG_USART_IRQHandler UART4_IRQHandler
// 串口5-UART5
//#define DEBUG_USARTx UART5
//#define DEBUG_USART_CLK RCC_APB1Periph_UART5
//#define DEBUG_USART_APBxClkCmd RCC_APB1PeriphClockCmd
//#define DEBUG_USART_BAUDRATE 115200
//// USART GPIO 引脚宏定义
//#define DEBUG_USART_GPIO_CLK (RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD)
//#define DEBUG_USART_GPIO_APBxClkCmd RCC_APB2PeriphClockCmd
//
//#define DEBUG_USART_TX_GPIO_PORT GPIOC
//#define DEBUG_USART_TX_GPIO_PIN GPIO_Pin_12
//#define DEBUG_USART_RX_GPIO_PORT GPIOD
//#define DEBUG_USART_RX_GPIO_PIN GPIO_Pin_2
//#define DEBUG_USART_IRQ UART5_IRQn
//#define DEBUG_USART_IRQHandler UART5_IRQHandler
void USART_Config(void);
void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch);
void Usart_SendString( USART_TypeDef * pUSARTx, char *str);
void Usart_SendHalfWord( USART_TypeDef * pUSARTx, uint16_t ch);
#endif /* __USART_H */
重构void rt_hw_console_output(const char *str)函数
board.c
/*
* File : board.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2017-07-24 Tanek the first version
*/
#include "board.h"
#include <rthw.h>
#include <rtthread.h>
#if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
#define RT_HEAP_SIZE 1024
static uint32_t rt_heap[RT_HEAP_SIZE]; // heap default size: 4K(1024 * 4)
void *rt_heap_begin_get(void)
RT_WEAK {
return rt_heap;
}
void *rt_heap_end_get(void)
RT_WEAK {
return rt_heap + RT_HEAP_SIZE;
}
#endif
/**
* This function will initial your board.
*/
void rt_hw_board_init()
{
/* 初始化 SysTick */
(SystemCoreClock / RT_TICK_PER_SECOND);
SysTick_Config/* 初始化开发板的 LED */
();
LED_GPIO_Config// 初始化串口
();
USART_Config/* 初始化测试部分, 测试完把代码删除*/
// LED2_ON;
// while (1)
// {
// /* code */
// }
/* Call components board initial (use INIT_BOARD_EXPORT()) */
#ifdef RT_USING_COMPONENTS_INIT
();
rt_components_board_init#endif
#if defined(RT_USING_CONSOLE) && defined(RT_USING_DEVICE)
(RT_CONSOLE_DEVICE_NAME);
rt_console_set_device#endif
#if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
(rt_heap_begin_get(), rt_heap_end_get());
rt_system_heap_init#endif
}
void SysTick_Handler(void)
{
/* enter interrupt */
();
rt_interrupt_enter
();
rt_tick_increase
/* leave interrupt */
();
rt_interrupt_leave}
/**************************重写rtthread控制台输出, 通过串口发送*************************************/
void rt_hw_console_output(const char *str)
{
/*进入临界区*/
();
rt_enter_critical
/* 直到将字符串发送完 */
while (*str != '\0')
{
/* 换行 */
if (*str == '\n')
{
(DEBUG_USARTx, '\r');
USART_SendDatawhile (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET);
}
(DEBUG_USARTx, *str++);
USART_SendDatawhile (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET);
}
/* 退出临界区 */
();
rt_exit_critical}
初始化串口配置
board.c
(); USART_Config
调用
mian.c
/**
*********************************************************************
* @file main.c
* @author fire
* @version V1.0
* @date 2018-xx-xx
* @brief RT-Thread 3.0 + STM32 工程模版
*********************************************************************
* @attention
*
* 实验平台:野火 F103-指南者 STM32 开发板
* 论坛 :http://www.firebbs.cn
* 淘宝 :https://fire-stm32.taobao.com
*
**********************************************************************
*/
/*
*************************************************************************
* 包含的头文件
*************************************************************************
*/
#include "board.h"
#include "rtthread.h"
/*
*************************************************************************
* 变量
*************************************************************************
*/
/* 定义线程控制块 */
//static struct rt_thread led1_thread;
static rt_thread_t led1_thread = RT_NULL;
static rt_thread_t led2_thread = RT_NULL;
/******************************static memory*******************************/
/* 定义线程控制块 */
// static struct rt_thread led1_thread;
/* 定义线程控栈时要求 RT_ALIGN_SIZE 个字节对齐 */
// ALIGN(RT_ALIGN_SIZE)
/* 定义线程栈 */
// static rt_uint8_t rt_led1_thread_stack[1024];
/****************************static memory end*****************************/
/*
*************************************************************************
* 函数声明
*************************************************************************
*/
static void led1_thread_entry(void *parameter);
static void led2_thread_entry(void *parameter);
/*
*************************************************************************
* main 函数
*************************************************************************
*/
/**
* @brief 主函数
* @param 无
* @retval 无
*/
int main(void)
{
/* 暂时没有在main线程里面创建任务应用线程 */
// thread 1
= rt_thread_create("led1",led1_thread_entry,RT_NULL,512, 3,20);
led1_thread
/* 线程启动,进行调度 */
if (led1_thread != RT_NULL)
(led1_thread);
rt_thread_startupelse
return -1;
// thread 2
= rt_thread_create("led2", led2_thread_entry, RT_NULL, 512, 3, 20);
led2_thread
if (led2_thread != RT_NULL)
(led2_thread);
rt_thread_startupelse
return -1;
/**********************************static memory demo ***************************************/
// rt_thread_init(&led1_thread, /* 线程控制块 */
// "led1", /* 线程名字 */
// led1_thread_entry, /* 线程入口函数 */
// RT_NULL, /* 线程入口函数参数 */
// &rt_led1_thread_stack[0], /* 线程栈起始地址 */
// sizeof(rt_led1_thread_stack), /* 线程栈大小 */
// 3, /* 线程的优先级 */
// 20); /* 线程时间片 */
// rt_thread_startup(&led1_thread); /* 启动线程,开启调度 */
/******************************static memory demo end*************************************/
}
/*
*************************************************************************
* 线程定义
*************************************************************************
*/
static void led1_thread_entry(void *parameter){
while (1)
{
;
LED1_ON(1500); /* 延时 500 个 tick */
rt_thread_delay;
LED1_OFF(1500); /* 延时 500 个 tick */
rt_thread_delay("thread --[1], Red\r\n");
rt_kprintf}
}
static void led2_thread_entry(void *parameter)
{
while (1)
{
;
LED2_ON(500); /* 延时 500 个 tick */
rt_thread_delay;
LED2_OFF(500); /* 延时 500 个 tick */
rt_thread_delay("thread --[2], Green\r\n");
rt_kprintf}
}