STM32CUBEMX_日志系统_RTT和串口(重映射浮点数打印)
前言:
嵌入式系统开发过程中日志的打印至关重要,他在系统架构搭建和开发过程中包括后期调试定位问题都非常重要,所以在此记录两种日志打印的方式。第一种是移植J-link中自带的RTT(SWD或GADG接口打印日志),这种方式优点非常明显,不用额外占用一个串口资源(优先推荐使用),第二种就是使用一个串口当做日志的打印,优点是常见,不用依托于J-ink使用。
注意:移植RTT过程我已经写了一片文章,详见https://blog.csdn.net/weixin_50183638/article/details/124633472
①在裸机系统中使用没有什么注意的,直接调用SEGGER_RTT_printf(0,“SEGGER RTT Terminal\r\n”);
②需要打印不同的颜色,直接调用SEGGER_RTT_printf(0,RTT_CTRL_TEXT_GREEN"SEGGER RTT Terminal\r\n");
③需要打印到RTT_Viewer的不同的串口,先设置一下输出接口就好了,SEGGER_RTT_SetTerminal(0);
④在FREERTOS系统中,两个任务中不能同时调用SEGGER_RTT_printf(0,“SEGGER RTT Terminal\r\n”);会使系统卡死
⑤使用printf重映射后,不管是串口方式还是RTT方式都可以在不同的线程中打印日志
⑥注意包含头文件,使用printf时注意包含头文件#include “stdio.h”
/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "SEGGER_RTT.h"
#include "stdio.h"
#include "usart.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/**********************************************自定义的日志打印函数*********************************************************/
#define USER_MAIN_DEBUG 1 //日志打印功能使能开关
#ifdef USER_MAIN_DEBUG
#define user_main_printf(format, ...) printf(RTT_CTRL_TEXT_WHITE format "\r\n", ##__VA_ARGS__)
#define user_main_info(format, ...) printf(RTT_CTRL_TEXT_GREEN"[main]info:" format "\r\n", ##__VA_ARGS__)
#define user_main_debug(format, ...) printf(RTT_CTRL_TEXT_WHITE"[main]debug:" format "\r\n", ##__VA_ARGS__)
#define user_main_warning(format, ...) printf(RTT_CTRL_TEXT_YELLOW"[main]debug:" format "\r\n", ##__VA_ARGS__)
#define user_main_error(format, ...) printf(RTT_CTRL_TEXT_RED"[tmain]error:" format "\r\n",##__VA_ARGS__)
#else
#define user_main_printf(format, ...)
#define user_main_info(format, ...)
#define user_main_debug(format, ...)
#define user_main_error(format, ...)
#endif
/**********************************************自定义的日志打印函数*********************************************************/
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */
/* USER CODE END Variables */
osThreadId_t defaultTaskHandle;
osThreadId_t myTask02Handle;
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */
/* USER CODE END FunctionPrototypes */
void StartDefaultTask(void *argument);
void StartTask02(void *argument);
void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */
/**
* @brief FreeRTOS initialization
* @param None
* @retval None
*/
void MX_FREERTOS_Init(void) {
/* USER CODE BEGIN Init */
/* USER CODE END Init */
osKernelInitialize();
/* USER CODE BEGIN RTOS_MUTEX */
/* add mutexes, ... */
/* USER CODE END RTOS_MUTEX */
/* USER CODE BEGIN RTOS_SEMAPHORES */
/* add semaphores, ... */
/* USER CODE END RTOS_SEMAPHORES */
/* USER CODE BEGIN RTOS_TIMERS */
/* start timers, add new ones, ... */
/* USER CODE END RTOS_TIMERS */
/* USER CODE BEGIN RTOS_QUEUES */
/* add queues, ... */
/* USER CODE END RTOS_QUEUES */
/* Create the thread(s) */
/* definition and creation of defaultTask */
const osThreadAttr_t defaultTask_attributes = {
.name = "defaultTask",
.priority = (osPriority_t) osPriorityNormal,
.stack_size = 512
};
defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);
/* definition and creation of myTask02 */
const osThreadAttr_t myTask02_attributes = {
.name = "myTask02",
.priority = (osPriority_t) osPriorityLow,
.stack_size = 512
};
myTask02Handle = osThreadNew(StartTask02, NULL, &myTask02_attributes);
/* USER CODE BEGIN RTOS_THREADS */
/* add threads, ... */
/* USER CODE END RTOS_THREADS */
}
/* USER CODE BEGIN Header_StartDefaultTask */
/**
* @brief Function implementing the defaultTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void *argument)
{
/* USER CODE BEGIN StartDefaultTask */
char GetKey;
/* Infinite loop */
for(;;)
{
/*********************************************接收RTT_Virwer发送字符*********************************************************/
if (SEGGER_RTT_HasKey()) /*判断接受缓冲区中是否有数据*/
{
GetKey = SEGGER_RTT_GetKey(); /*从接收缓冲区中取出一个字符*/
SEGGER_RTT_SetTerminal(0);
SEGGER_RTT_printf(0, "GetKey = %c\r\n", GetKey);
}
/*********************************************接收RTT_Virwer发送字符*********************************************************/
HAL_GPIO_WritePin(GPIOF, GPIO_PIN_9, GPIO_PIN_RESET);
osDelay(500);
HAL_GPIO_WritePin(GPIOF, GPIO_PIN_9, GPIO_PIN_SET);
osDelay(500);
printf(RTT_CTRL_TEXT_GREEN"StartDefaultTask:%f,%f,%f\r\n",234.153,564.1386,2.1350); //重映射RTT打印浮点数
// printf("StartTask02:%.1f,%.1f,%.1f\r\n",45.45,46.46,47.789); //重映射串口打印浮点数
/**********************************************测试自定义的日志打印函数*********************************************************/
SEGGER_RTT_SetTerminal(0);
user_main_printf("StartDefaultTask:%f",1.153); //打印在窗口0,颜色显示:白色
user_main_info("StartDefaultTask:%f",2.153); //打印在窗口0,颜色显示:绿色
user_main_debug("StartDefaultTask:%f",3.153); //打印在窗口0,颜色显示:白色
user_main_warning("StartDefaultTask:%f",4.153); //打印在窗口0,颜色显示:黄色
user_main_error("StartDefaultTask:%f",5.153); //打印在窗口0,颜色显示:红色
/**********************************************测试自定义的日志打印函数*********************************************************/
}
/* USER CODE END StartDefaultTask */
}
/* USER CODE BEGIN Header_StartTask02 */
/**
* @brief Function implementing the myTask02 thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartTask02 */
void StartTask02(void *argument)
{
/* USER CODE BEGIN StartTask02 */
/* Infinite loop */
for(;;)
{
osDelay(1000);
/**********************************************测试自定义的日志打印函数*********************************************************/
SEGGER_RTT_SetTerminal(1); //打印在串口1
user_main_printf("StartDefaultTask:%f",1.153);
user_main_info("StartDefaultTask:%f",2.153);
user_main_debug("StartDefaultTask:%f",3.153);
user_main_warning("StartDefaultTask:%f",4.153);
user_main_error("StartDefaultTask:%f",5.153);
/**********************************************测试自定义的日志打印函数*********************************************************/
printf(RTT_CTRL_TEXT_YELLOW"StartTask02:%d,%d,%d\r\n",45,46,47); //打印黄色日志
// printf("StartTask02:%d,%d\r\n",156,586641); //重映射串口打印整数
}
/* USER CODE END StartTask02 */
}
/* Private application code --------------------------------------------------*/
/********************************************重映射函数*********************************************************/
/* USER CODE BEGIN Application */
//int __io_putchar(int ch)
//{
// HAL_UART_Transmit(&huart1, (uint8_t*)&ch, 1, HAL_MAX_DELAY);
// return ch;
//}
//int fputc(int ch, FILE *f){
// HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
// return ch;
//}
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
// HAL_UART_Transmit(&huart1, (uint8_t*) &ch, 1, 0xffff); //重映射串口1
// return ch;
SEGGER_RTT_PutChar(0, ch); //重映射RTT
return ch;
}
/********************************************重映射函数*********************************************************/
/* USER CODE END Application */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/