http://blog.csdn.net/jdh99,环境:
主机:WIN10
开发环境:MDK5.12
MCU:STM32F407
说明:
为单片机设计了一套简单的日志系统,通过日志系统提供的接口可以查看设备状态,并进行一些基本的调试。
日志系统通过串口输出,所以单片机需要准备一个串口供日志系统使用。注意串口发送不能用DMA发送(避免在在中断中打印日志造成的中断竞争),接收可以用DMA接收。
功能:
- 打开/关闭各个模块的调试输出
- 输入动作指令,让设备进行一些动作
- 打印系统运行日志
指令:
- H:帮助
- O:调试输出全开
- O1:打开1号模块,打开其他模块指令类似
- F:调试输出全关
- F1:关闭1号模块
- I:输出系统日志
- C:清除系统日志
- A1:执行1号动作,执行其他动作指令类似
源代码:
log.h:
log.c:
- /**
- * Copyright (c), 2015-2025
- * @file log.c
- * @brief 日志模块主文件
- * @author jdh
- * @email jdh821@163.com
- * @date 2015/5/7
- * @update 2015/6/19
- * @update 2015/6/30
- * @update 2015/7/8
- * @update 2015/7/13
- * @update 2015/7/15
- * @update 2015/8/12
- * @update 2015/8/13
- * @update 2015/11/11
- * @update 2016/5/17
- * @update 2016/6/30
- * @update 2016/7/22
- * @update 2016/8/11
- * @update 2016/8/18
- * @update 2016/8/22
- * @update 2016/8/24
- * @update 2016/9/2
- * @update 2016/9/5
- * @update 2016/9/7
- * @update 2016/9/9
- * @update 2016/9/12
- */
-
- /*********************************************************************
- * 头文件
- **********************************************************************/
-
- #include "log.h"
- #include "protocol_bus.h"
- #include "protocol_uwb.h"
- #include "para_manage.h"
-
- /*********************************************************************
- * 静态变量
- **********************************************************************/
-
- /**
- * @brief 运行日志
- */
-
- static struct _Log Log __attribute__((section("NO_INIT"),zero_init));
-
- /**
- * @brief 日志过滤标志数组,0:未过滤,1:过滤
- */
-
- static uint8_t Filter[NUM_LOG] = {1, 1, 1, 1, 1};
-
- /**
- * @brief 暂停输出标志,0:未暂停输出,1:暂停输出
- */
-
- static uint8_t Flag_Pause = 0;
-
- /*********************************************************************
- * 静态函数
- **********************************************************************/
-
- /**
- * @brief 帮助界面
- */
-
- static void help(void);
-
- /**
- * @brief 输出本地日志
- */
-
- static void print_log(void);
-
- /**
- * @brief 处理动作
- * @param index:动作编号
- */
-
- static void deal_action(uint8_t index);
-
- /*********************************************************************
- * 函数
- **********************************************************************/
-
- /**
- * @brief 模块加载
- */
-
- void log_load(void)
- {
- //检查是否上电
- if (RCC_GetFlagStatus(RCC_FLAG_PORRST) == SET)
- {
- //清除标志位
- RCC_ClearFlag();
- //清除日志
- memset(&Log, 0, sizeof(Log));
- }
- else
- {
- //日志:复位次数
- Log.num_reset++;
- }
- }
-
- /**
- * @brief 清除日志
- */
-
- void log_clear(void)
- {
- memset(&Log, 0, sizeof(Log));
- }
-
- /**
- * @brief 读取日志
- * @retval 日志
- */
-
- struct _Log log_read(void)
- {
- return Log;
- }
-
- /**
- * @brief 收到移动点数据次数
- */
-
- void log_write_num_rf_rx(void)
- {
- Log.num_rf_rx++;
- }
-
- /**
- * @brief 发送超时被删除点数
- */
-
- void log_write_num_time_out_delete(void)
- {
- Log.num_time_out_delete++;
- }
-
- /**
- * @brief RF发送次数
- */
-
- void log_write_num_rf_tx(void)
- {
- Log.num_rf_tx++;
- }
-
- /**
- * @brief RF校时或分配事件次数
- */
-
- void log_write_num_rf_time(void)
- {
- Log.num_rf_time++;
- }
-
- /**
- * @brief RF随机信道发送次数
- */
-
- void log_write_num_rf_random_tx(void)
- {
- Log.num_rf_random_tx++;
- }
-
- /**
- * @brief 复位次数
- */
-
- void log_write_num_reset(void)
- {
- Log.num_reset++;
- }
-
- /**
- * @brief 运行时间
- * @param add_time:增加的时间.单位:0.5s
- */
-
- void log_write_time_run(uint32_t add_time)
- {
- Log.time_run += add_time;
- }
-
- /**
- * @brief 收到同步脉冲计数
- */
-
- void log_write_num_sync_pulse(void)
- {
- Log.num_sync_pulse++;
- }
-
- /**
- * @brief 收到422轮询/事件帧次数
- */
-
- void log_write_num_bus_poll(void)
- {
- Log.num_bus_poll++;
- }
-
- /**
- * @brief 收到422事务命令次数
- */
-
- void log_write_num_bus_down_cmd(void)
- {
- Log.num_bus_down_cmd++;
- }
-
- /**
- * @brief 收到422事务命令中事件个数
- */
-
- void log_write_num_bus_down_cmd_dot(void)
- {
- Log.num_bus_down_cmd_dot++;
- }
-
- /**
- * @brief 收到有效的422帧次数
- */
-
- void log_write_num_valid_bus(void)
- {
- Log.num_valid_bus++;
- }
-
- /**
- * @brief 收到无效的422帧次数
- */
-
- void log_write_num_invalid_bus(void)
- {
- Log.num_invalid_bus++;
- }
-
- /**
- * @brief 收到时间错误
- */
-
- void log_write_num_time_error(void)
- {
- Log.num_time_error++;
- }
-
- /**
- * @brief dw1000芯片错误次数
- * @param index:模块序号,从0开始
- */
-
- void log_write_num_dw1000_error(uint8_t index)
- {
- Log.num_dw1000_error[index]++;
- }
-
- /**
- * @brief dw1000芯片接收时间错误次数
- * @param index:模块序号,从0开始
- */
-
- void log_write_num_dw1000_time_error(uint8_t index)
- {
- Log.num_dw1000_time_error[index]++;
- }
-
- /**
- * @brief 轮询超时被删除点数
- */
-
- void log_write_num_poll_time_out_delete(void)
- {
- Log.num_poll_time_out_delete++;
- }
-
- /**
- * @brief dw1000芯片接收超时复位次数
- * @param index:模块序号,从0开始
- */
-
- void log_write_num_dw1000_time_out_reset(uint8_t index)
- {
- Log.num_dw1000_time_out_reset[index]++;
- }
-
- /**
- * @brief dw1000芯片状态错误次数
- * @param index:模块序号,从0开始
- */
-
- void log_write_num_dw1000_status_error(uint8_t index)
- {
- Log.num_dw1000_status_error[index]++;
- }
-
- /**
- * @brief 控制台打印
- * @param index:模块编号
- * @param info:打印的信息
- */
-
- void log_print(uint8_t index,char *info)
- {
- T_Time time;
- char log_out[256] = {0};
-
- //判断是否是暂停输出
- if (Flag_Pause)
- {
- return;
- }
-
- //判断是否被过滤输出
- if (Filter[index])
- {
- return;
- }
-
- time = get_time();
- sprintf(log_out,"%05d:%03d:%03d %s\r\n",time.s,time.ms,time.us,info);
- console_tx((uint8_t *)log_out,strlen(log_out));
- }
-
- /**
- * @brief 控制台强制打印
- * @param info:打印的信息
- */
-
- void log_print_force(char *info)
- {
- T_Time time;
- char log_out[256] = {0};
-
- time = get_time();
- sprintf(log_out,"%05d:%03d:%03d %s\r\n",time.s,time.ms,time.us,info);
- console_tx((uint8_t *)log_out,strlen(log_out));
- }
-
- /**
- * @brief 接收处理
- * @param rx:接收数据
- */
-
- void log_deal_rx(struct _Console_Rx rx)
- {
- uint8_t i = 0;
- int num = 0;
- char str_temp[5] = {0};
-
- //判断是否是输出本地日志
- if (rx.len == 1 && rx.buf[0] == 'I')
- {
- print_log();
- return;
- }
-
- //判断是否是输出本地日志
- if (rx.len == 1 && rx.buf[0] == 'C')
- {
- log_clear();
- return;
- }
-
- //判断是否是暂停输出
- if (rx.len == 1 && rx.buf[0] == 'P')
- {
- Flag_Pause = 1;
- return;
- }
-
- //判断是否是打开输出
- if (rx.len == 1 && rx.buf[0] == 'S')
- {
- Flag_Pause = 0;
- return;
- }
-
- //判断是否是帮助
- if (rx.len == 1 && rx.buf[0] == 'H')
- {
- help();
- return;
- }
-
- //判断是否是过滤规则
- if (rx.len <= 3 && rx.buf[0] == 'F')
- {
- if (rx.len == 1)
- {
- //全部过滤
- for (i = 0;i < NUM_LOG;i++)
- {
- Filter[i] = 1;
- }
- return;
- }
-
- memset(str_temp,sizeof(str_temp),0);
- memcpy(str_temp,rx.buf,rx.len);
- sscanf(str_temp,"F%d",&num);
- Filter[num] = 1;
- return;
- }
-
- //判断是否是打开模块
- if (rx.len <= 3 && rx.buf[0] == 'O')
- {
- if (rx.len == 1)
- {
- //清除过滤规则
- for (i = 0;i < NUM_LOG;i++)
- {
- Filter[i] = 0;
- }
- return;
- }
-
- memset(str_temp,sizeof(str_temp),0);
- memcpy(str_temp,rx.buf,rx.len);
- sscanf(str_temp,"O%d",&num);
- Filter[num] = 0;
- return;
- }
-
- //判断是否是打开模块
- if (rx.len > 1 && rx.len <= 3 && rx.buf[0] == 'A')
- {
- memset(str_temp,sizeof(str_temp),0);
- memcpy(str_temp,rx.buf,rx.len);
- sscanf(str_temp,"A%d",&num);
- deal_action(num);
- return;
- }
- }
-
- /**
- * @brief 帮助界面
- */
-
- static void help(void)
- {
- char log_out[100] = {0};
-
- strcpy(log_out,"*******************************************\r\n");
- console_tx((uint8_t *)log_out,strlen(log_out));
- strcpy(log_out," UWB基站日志帮助界面 \r\n");
- console_tx((uint8_t *)log_out,strlen(log_out));
- sprintf(log_out,"硬件版本:%d 软件版本:%d\r\n",VERSION_HARD,VERSION_SOFT);
- console_tx((uint8_t *)log_out,strlen(log_out));
- sprintf(log_out,"总线通信协议版本:%s\r\n",VERSION_NAME_BUS);
- console_tx((uint8_t *)log_out,strlen(log_out));
- sprintf(log_out,"空口通信协议版本:%s\r\n",VERSION_NAME_UWB);
- console_tx((uint8_t *)log_out,strlen(log_out));
- sprintf(log_out,"CSSN:0x%06x ID:0x%04x\r\n",para_manage_read_cssn(), para_manage_read_id());
- console_tx((uint8_t *)log_out,strlen(log_out));
- strcpy(log_out,"快捷键I(INFO)输出本地日志\r\n");
- console_tx((uint8_t *)log_out,strlen(log_out));
- strcpy(log_out,"快捷键C(CLEAR)清除本地日志\r\n");
- console_tx((uint8_t *)log_out,strlen(log_out));
- strcpy(log_out,"快捷键P(PAUSE)暂停输出\r\n");
- console_tx((uint8_t *)log_out,strlen(log_out));
- strcpy(log_out,"快捷键S(START)开始输出\r\n");
- console_tx((uint8_t *)log_out,strlen(log_out));
- strcpy(log_out,"快捷键A(ACTION)动作\r\n");
- console_tx((uint8_t *)log_out,strlen(log_out));
- strcpy(log_out,"A1:读取1号dw1000状态寄存器\r\n");
- console_tx((uint8_t *)log_out,strlen(log_out));
- strcpy(log_out,"A2:清除1号dw1000状态寄存器\r\n");
- console_tx((uint8_t *)log_out,strlen(log_out));
- strcpy(log_out,"A3:打开1号dw1000接收\r\n");
- console_tx((uint8_t *)log_out,strlen(log_out));
- strcpy(log_out,"快捷键H(HELP)打开帮助\r\n");
- console_tx((uint8_t *)log_out,strlen(log_out));
- strcpy(log_out,"快捷键F(FILTER)过滤输出\r\n");
- console_tx((uint8_t *)log_out,strlen(log_out));
- strcpy(log_out,"例:过滤1号模块:F1\r\n");
- console_tx((uint8_t *)log_out,strlen(log_out));
- strcpy(log_out,"例:全部过滤:F\r\n");
- console_tx((uint8_t *)log_out,strlen(log_out));
- strcpy(log_out,"快捷键O(OPEN)打开模块\r\n");
- console_tx((uint8_t *)log_out,strlen(log_out));
- strcpy(log_out,"例:打开1号模块:O1\r\n");
- console_tx((uint8_t *)log_out,strlen(log_out));
- strcpy(log_out,"例:全部打开:O\r\n");
- console_tx((uint8_t *)log_out,strlen(log_out));
- strcpy(log_out,"包含的模块:\r\n");
- console_tx((uint8_t *)log_out,strlen(log_out));
- sprintf(log_out,"TEST:%d 过滤:%d \r\n",LOG_TEST,Filter[LOG_TEST]);
- console_tx((uint8_t *)log_out,strlen(log_out));
- sprintf(log_out,"CLOCK:%d 过滤:%d \r\n",LOG_CLOCK,Filter[LOG_CLOCK]);
- console_tx((uint8_t *)log_out,strlen(log_out));
- sprintf(log_out,"DW1000:%d 过滤:%d \r\n",LOG_DW1000,Filter[LOG_DW1000]);
- console_tx((uint8_t *)log_out,strlen(log_out));
- sprintf(log_out,"DW1000_STATUS:%d 过滤:%d \r\n",LOG_DW1000_STATUS,Filter[LOG_DW1000_STATUS]);
- console_tx((uint8_t *)log_out,strlen(log_out));
- sprintf(log_out,"DW1000_DEAL_BUS:%d 过滤:%d \r\n",LOG_DEAL_BUS,Filter[LOG_DEAL_BUS]);
- console_tx((uint8_t *)log_out,strlen(log_out));
- strcpy(log_out,"*******************************************\r\n");
- console_tx((uint8_t *)log_out,strlen(log_out));
- }
-
- /**
- * @brief 输出本地日志
- */
-
- static void print_log(void)
- {
- char log_out[100] = {0};
- uint8_t i = 0;
-
- strcpy(log_out,"本地日志输出:\r\n");
- console_tx((uint8_t *)log_out,strlen(log_out));
- sprintf(log_out,"收到移动点数据次数:%d\r\n", Log.num_rf_rx);
- console_tx((uint8_t *)log_out,strlen(log_out));
- sprintf(log_out,"发送超时被删除点数:%d\r\n", Log.num_time_out_delete);
- console_tx((uint8_t *)log_out,strlen(log_out));
- sprintf(log_out,"RF发送次数:%d\r\n", Log.num_rf_tx);
- console_tx((uint8_t *)log_out,strlen(log_out));
- sprintf(log_out,"RF校时或分配事件次数:%d\r\n", Log.num_rf_time);
- console_tx((uint8_t *)log_out,strlen(log_out));
- sprintf(log_out,"RF随机信道发送次数:%d\r\n", Log.num_rf_random_tx);
- console_tx((uint8_t *)log_out,strlen(log_out));
- sprintf(log_out,"复位次数:%d\r\n", Log.num_reset);
- console_tx((uint8_t *)log_out,strlen(log_out));
- sprintf(log_out,"运行时间:%d\r\n", Log.time_run);
- console_tx((uint8_t *)log_out,strlen(log_out));
- sprintf(log_out,"收到同步脉冲计数:%d\r\n", Log.num_sync_pulse);
- console_tx((uint8_t *)log_out,strlen(log_out));
- sprintf(log_out,"收到422轮询/事件帧次数:%d\r\n", Log.num_bus_poll);
- console_tx((uint8_t *)log_out,strlen(log_out));
- sprintf(log_out,"收到422事务命令次数:%d\r\n", Log.num_bus_down_cmd);
- console_tx((uint8_t *)log_out,strlen(log_out));
- sprintf(log_out,"收到422事务命令中事件个数:%d\r\n", Log.num_bus_down_cmd_dot);
- console_tx((uint8_t *)log_out,strlen(log_out));
- sprintf(log_out,"收到有效的422帧次数:%d\r\n", Log.num_valid_bus);
- console_tx((uint8_t *)log_out,strlen(log_out));
- sprintf(log_out,"收到无效的422帧次数:%d\r\n", Log.num_invalid_bus);
- console_tx((uint8_t *)log_out,strlen(log_out));
- sprintf(log_out,"校时时间错误次数:%d\r\n", Log.num_time_error);
- console_tx((uint8_t *)log_out,strlen(log_out));
- for (i = 0; i < NUM_DW1000; i++)
- {
- sprintf(log_out,"%d号dw1000模块错误次数:%d\r\n", i, Log.num_dw1000_error[i]);
- console_tx((uint8_t *)log_out,strlen(log_out));
- }
- for (i = 0; i < NUM_DW1000; i++)
- {
- sprintf(log_out,"%d号dw1000模块时间错误次数:%d\r\n", i, Log.num_dw1000_time_error[i]);
- console_tx((uint8_t *)log_out,strlen(log_out));
- }
- sprintf(log_out,"轮询超时被删除点数:%d\r\n", Log.num_poll_time_out_delete);
- console_tx((uint8_t *)log_out,strlen(log_out));
- for (i = 0; i < NUM_DW1000; i++)
- {
- sprintf(log_out,"%d号dw1000模块接收时间超时复位次数:%d\r\n", i, Log.num_dw1000_time_out_reset[i]);
- console_tx((uint8_t *)log_out,strlen(log_out));
- }
- for (i = 0; i < NUM_DW1000; i++)
- {
- sprintf(log_out,"%d号dw1000模块状态错误次数:%d\r\n", i, Log.num_dw1000_status_error[i]);
- console_tx((uint8_t *)log_out,strlen(log_out));
- }
- }
-
- /**
- * @brief 处理动作
- * @param index:动作编号
- */
-
- static void deal_action(uint8_t index)
- {
- uint32_t status = 0;
- char log_out[100] = {0};
-
- switch (index)
- {
- //读取1号dw1000状态寄存器
- case 1:
- {
- status = dwt_read32bitreg(0, SYS_STATUS_ID);
- sprintf(log_out,"1号dw1000状态:0x%08x\r\n", status);
- console_tx((uint8_t *)log_out,strlen(log_out));
- break;
- }
- //清除1号dw1000状态寄存器
- case 2:
- {
- status = dwt_read32bitreg(0, SYS_STATUS_ID);
- dwt_write32bitreg(0, SYS_STATUS_ID, status);
- break;
- }
- //打开1号dw1000接收
- case 3:
- {
- dwt_rxenable(0, 0);
- break;
- }
- }
- }