增加了屏幕显示的封装驱动,日志输出,电机挡位控制

This commit is contained in:
2026-02-05 13:06:01 +08:00
parent 22380b09a1
commit f275a5aad9
194 changed files with 65750 additions and 45 deletions

View File

@@ -44,7 +44,7 @@ void MX_ADC1_Init(void)
*/
hadc1.Instance = ADC1;
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.ContinuousConvMode = ENABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
@@ -58,7 +58,7 @@ void MX_ADC1_Init(void)
*/
sConfig.Channel = ADC_CHANNEL_0;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();

View File

@@ -0,0 +1,272 @@
//
// Created by wangb on 25-6-4.
//
#ifndef ELOG_H
#define ELOG_H
#include "elog_cfg.h"
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/* output log's level */
#define ELOG_LVL_ASSERT 0
#define ELOG_LVL_ERROR 1
#define ELOG_LVL_WARN 2
#define ELOG_LVL_INFO 3
#define ELOG_LVL_DEBUG 4
#define ELOG_LVL_VERBOSE 5
/* the output silent level and all level for filter setting */
#define ELOG_FILTER_LVL_SILENT ELOG_LVL_ASSERT
#define ELOG_FILTER_LVL_ALL ELOG_LVL_VERBOSE
/* output log's level total number */
#define ELOG_LVL_TOTAL_NUM 6
/* EasyLogger software version number */
#define ELOG_SW_VERSION "2.2.99"
/* EasyLogger assert for developer. */
#ifdef ELOG_ASSERT_ENABLE
#define ELOG_ASSERT(EXPR) \
if (!(EXPR)) \
{ \
if (elog_assert_hook == NULL) { \
elog_a("elog", "(%s) has assert failed at %s:%ld.", #EXPR, __FUNCTION__, __LINE__); \
while (1); \
} else { \
elog_assert_hook(#EXPR, __FUNCTION__, __LINE__); \
} \
}
#else
#define ELOG_ASSERT(EXPR) ((void)0);
#endif
#ifndef ELOG_OUTPUT_ENABLE
#define elog_raw(...)
#define elog_assert(tag, ...)
#define elog_error(tag, ...)
#define elog_warn(tag, ...)
#define elog_info(tag, ...)
#define elog_debug(tag, ...)
#define elog_verbose(tag, ...)
#else /* ELOG_OUTPUT_ENABLE */
#ifdef ELOG_FMT_USING_FUNC
#define ELOG_OUTPUT_FUNC __FUNCTION__
#else
#define ELOG_OUTPUT_FUNC NULL
#endif
#ifdef ELOG_FMT_USING_DIR
#define ELOG_OUTPUT_DIR __FILE__
#else
#define ELOG_OUTPUT_DIR NULL
#endif
#ifdef ELOG_FMT_USING_LINE
#define ELOG_OUTPUT_LINE __LINE__
#else
#define ELOG_OUTPUT_LINE 0
#endif
#define elog_raw(...) elog_raw_output(__VA_ARGS__)
#if ELOG_OUTPUT_LVL >= ELOG_LVL_ASSERT
#define elog_assert(tag, ...) \
elog_output(ELOG_LVL_ASSERT, tag, ELOG_OUTPUT_DIR, ELOG_OUTPUT_FUNC, ELOG_OUTPUT_LINE, __VA_ARGS__)
#else
#define elog_assert(tag, ...)
#endif /* ELOG_OUTPUT_LVL >= ELOG_LVL_ASSERT */
#if ELOG_OUTPUT_LVL >= ELOG_LVL_ERROR
#define elog_error(tag, ...) \
elog_output(ELOG_LVL_ERROR, tag, ELOG_OUTPUT_DIR, ELOG_OUTPUT_FUNC, ELOG_OUTPUT_LINE, __VA_ARGS__)
#else
#define elog_error(tag, ...)
#endif /* ELOG_OUTPUT_LVL >= ELOG_LVL_ERROR */
#if ELOG_OUTPUT_LVL >= ELOG_LVL_WARN
#define elog_warn(tag, ...) \
elog_output(ELOG_LVL_WARN, tag, ELOG_OUTPUT_DIR, ELOG_OUTPUT_FUNC, ELOG_OUTPUT_LINE, __VA_ARGS__)
#else
#define elog_warn(tag, ...)
#endif /* ELOG_OUTPUT_LVL >= ELOG_LVL_WARN */
#if ELOG_OUTPUT_LVL >= ELOG_LVL_INFO
#define elog_info(tag, ...) \
elog_output(ELOG_LVL_INFO, tag, ELOG_OUTPUT_DIR, ELOG_OUTPUT_FUNC, ELOG_OUTPUT_LINE, __VA_ARGS__)
#else
#define elog_info(tag, ...)
#endif /* ELOG_OUTPUT_LVL >= ELOG_LVL_INFO */
#if ELOG_OUTPUT_LVL >= ELOG_LVL_DEBUG
#define elog_debug(tag, ...) \
elog_output(ELOG_LVL_DEBUG, tag, ELOG_OUTPUT_DIR, ELOG_OUTPUT_FUNC, ELOG_OUTPUT_LINE, __VA_ARGS__)
#else
#define elog_debug(tag, ...)
#endif /* ELOG_OUTPUT_LVL >= ELOG_LVL_DEBUG */
#if ELOG_OUTPUT_LVL == ELOG_LVL_VERBOSE
#define elog_verbose(tag, ...) \
elog_output(ELOG_LVL_VERBOSE, tag, ELOG_OUTPUT_DIR, ELOG_OUTPUT_FUNC, ELOG_OUTPUT_LINE, __VA_ARGS__)
#else
#define elog_verbose(tag, ...)
#endif /* ELOG_OUTPUT_LVL == ELOG_LVL_VERBOSE */
#endif /* ELOG_OUTPUT_ENABLE */
/* all formats index */
typedef enum {
ELOG_FMT_LVL = 1 << 0, /**< level */
ELOG_FMT_TAG = 1 << 1, /**< tag */
ELOG_FMT_TIME = 1 << 2, /**< current time */
ELOG_FMT_P_INFO = 1 << 3, /**< process info */
ELOG_FMT_T_INFO = 1 << 4, /**< thread info */
ELOG_FMT_DIR = 1 << 5, /**< file directory and name */
ELOG_FMT_FUNC = 1 << 6, /**< function name */
ELOG_FMT_LINE = 1 << 7, /**< line number */
} ElogFmtIndex;
/* macro definition for all formats */
#define ELOG_FMT_ALL (ELOG_FMT_LVL|ELOG_FMT_TAG|ELOG_FMT_TIME|ELOG_FMT_P_INFO|ELOG_FMT_T_INFO| \
ELOG_FMT_DIR|ELOG_FMT_FUNC|ELOG_FMT_LINE)
/* output log's tag filter */
typedef struct {
uint8_t level;
char tag[ELOG_FILTER_TAG_MAX_LEN + 1];
bool tag_use_flag; /**< false : tag is no used true: tag is used */
} ElogTagLvlFilter, *ElogTagLvlFilter_t;
/* output log's filter */
typedef struct {
uint8_t level;
char tag[ELOG_FILTER_TAG_MAX_LEN + 1];
char keyword[ELOG_FILTER_KW_MAX_LEN + 1];
ElogTagLvlFilter tag_lvl[ELOG_FILTER_TAG_LVL_MAX_NUM];
} ElogFilter, *ElogFilter_t;
/* easy logger */
typedef struct {
ElogFilter filter;
size_t enabled_fmt_set[ELOG_LVL_TOTAL_NUM];
bool init_ok;
bool output_enabled;
bool output_lock_enabled;
bool output_is_locked_before_enable;
bool output_is_locked_before_disable;
#ifdef ELOG_COLOR_ENABLE
bool text_color_enabled;
#endif
}EasyLogger, *EasyLogger_t;
/* EasyLogger error code */
typedef enum {
ELOG_NO_ERR,
} ElogErrCode;
/* elog.c */
ElogErrCode elog_init(void);
void elog_deinit(void);
void elog_start(void);
void elog_stop(void);
void elog_set_output_enabled(bool enabled);
bool elog_get_output_enabled(void);
void elog_set_text_color_enabled(bool enabled);
bool elog_get_text_color_enabled(void);
void elog_set_fmt(uint8_t level, size_t set);
void elog_set_filter(uint8_t level, const char *tag, const char *keyword);
void elog_set_filter_lvl(uint8_t level);
void elog_set_filter_tag(const char *tag);
void elog_set_filter_kw(const char *keyword);
void elog_set_filter_tag_lvl(const char *tag, uint8_t level);
uint8_t elog_get_filter_tag_lvl(const char *tag);
void elog_raw_output(const char *format, ...);
void elog_output(uint8_t level, const char *tag, const char *file, const char *func,
const long line, const char *format, ...);
void elog_output_lock_enabled(bool enabled);
extern void (*elog_assert_hook)(const char* expr, const char* func, size_t line);
void elog_assert_set_hook(void (*hook)(const char* expr, const char* func, size_t line));
int8_t elog_find_lvl(const char *log);
const char *elog_find_tag(const char *log, uint8_t lvl, size_t *tag_len);
void elog_hexdump(const char *name, uint8_t width, const void *buf, uint16_t size);
#define elog_a(tag, ...) elog_assert(tag, __VA_ARGS__)
#define elog_e(tag, ...) elog_error(tag, __VA_ARGS__)
#define elog_w(tag, ...) elog_warn(tag, __VA_ARGS__)
#define elog_i(tag, ...) elog_info(tag, __VA_ARGS__)
#define elog_d(tag, ...) elog_debug(tag, __VA_ARGS__)
#define elog_v(tag, ...) elog_verbose(tag, __VA_ARGS__)
/**
* log API short definition
* NOTE: The `LOG_TAG` and `LOG_LVL` must defined before including the <elog.h> when you want to use log_x API.
*/
#if !defined(LOG_TAG)
#define LOG_TAG "NO_TAG"
#endif
#if !defined(LOG_LVL)
#define LOG_LVL ELOG_LVL_VERBOSE
#endif
#if LOG_LVL >= ELOG_LVL_ASSERT
#define log_a(...) elog_a(LOG_TAG, __VA_ARGS__)
#else
#define log_a(...) ((void)0);
#endif
#if LOG_LVL >= ELOG_LVL_ERROR
#define log_e(...) elog_e(LOG_TAG, __VA_ARGS__)
#else
#define log_e(...) ((void)0);
#endif
#if LOG_LVL >= ELOG_LVL_WARN
#define log_w(...) elog_w(LOG_TAG, __VA_ARGS__)
#else
#define log_w(...) ((void)0);
#endif
#if LOG_LVL >= ELOG_LVL_INFO
#define log_i(...) elog_i(LOG_TAG, __VA_ARGS__)
#else
#define log_i(...) ((void)0);
#endif
#if LOG_LVL >= ELOG_LVL_DEBUG
#define log_d(...) elog_d(LOG_TAG, __VA_ARGS__)
#else
#define log_d(...) ((void)0);
#endif
#if LOG_LVL >= ELOG_LVL_VERBOSE
#define log_v(...) elog_v(LOG_TAG, __VA_ARGS__)
#else
#define log_v(...) ((void)0);
#endif
/* assert API short definition */
#if !defined(assert)
#define assert ELOG_ASSERT
#endif
/* elog_buf.c */
void elog_buf_enabled(bool enabled);
void elog_flush(void);
/* elog_async.c */
void elog_async_enabled(bool enabled);
size_t elog_async_get_log(char *log, size_t size);
size_t elog_async_get_line_log(char *log, size_t size);
/* elog_utils.c */
size_t elog_strcpy(size_t cur_len, char *dst, const char *src);
size_t elog_cpyln(char *line, const char *log, size_t len);
void *elog_memcpy(void *dst, const void *src, size_t count);
void easylogger_init(void);
#ifdef __cplusplus
}
#endif
#endif //ELOG_H

View File

@@ -0,0 +1,59 @@
//
// Created by wangb on 25-6-4.
//
#ifndef _ELOG_CFG_H_
#define _ELOG_CFG_H_
/*---------------------------------------------------------------------------*/
/* enable log output. */
#define ELOG_OUTPUT_ENABLE
/* setting static output log level. range: from ELOG_LVL_ASSERT to ELOG_LVL_VERBOSE */
#define ELOG_OUTPUT_LVL ELOG_LVL_VERBOSE
/* enable assert check */
#define ELOG_ASSERT_ENABLE
/* buffer size for every line's log */
#define ELOG_LINE_BUF_SIZE 1024
/* output line number max length */
#define ELOG_LINE_NUM_MAX_LEN 5
/* output filter's tag max length */
#define ELOG_FILTER_TAG_MAX_LEN 30
/* output filter's keyword max length */
#define ELOG_FILTER_KW_MAX_LEN 16
/* output filter's tag level max num */
#define ELOG_FILTER_TAG_LVL_MAX_NUM 5
/* output newline sign */
#define ELOG_NEWLINE_SIGN "\r\n" //换行
/*---------------------------------------------------------------------------*/
/* enable log color */
#define ELOG_COLOR_ENABLE
/* change the some level logs to not default color if you want */
#define ELOG_COLOR_ASSERT (F_MAGENTA B_NULL S_NORMAL)
#define ELOG_COLOR_ERROR (F_RED B_NULL S_NORMAL)
#define ELOG_COLOR_WARN (F_YELLOW B_NULL S_NORMAL)
#define ELOG_COLOR_INFO (F_CYAN B_NULL S_NORMAL)
#define ELOG_COLOR_DEBUG (F_GREEN B_NULL S_NORMAL)
#define ELOG_COLOR_VERBOSE (F_BLUE B_NULL S_NORMAL)
/*---------------------------------------------------------------------------*/
/* enable log fmt */
/* comment it if you don't want to output them at all */
#define ELOG_FMT_USING_FUNC
#define ELOG_FMT_USING_DIR
#define ELOG_FMT_USING_LINE
/*---------------------------------------------------------------------------*/
/* enable asynchronous output mode */
//#define ELOG_ASYNC_OUTPUT_ENABLE
/* the highest output level for async mode, other level will sync output */
#define ELOG_ASYNC_OUTPUT_LVL ELOG_LVL_ASSERT
/* buffer size for asynchronous output mode */
#define ELOG_ASYNC_OUTPUT_BUF_SIZE (ELOG_LINE_BUF_SIZE * 10)
/* each asynchronous output's log which must end with newline sign */
#define ELOG_ASYNC_LINE_OUTPUT
/* asynchronous output mode using POSIX pthread implementation */
#define ELOG_ASYNC_OUTPUT_USING_PTHREAD
/*---------------------------------------------------------------------------*/
/* enable buffered output mode */
//#define ELOG_BUF_OUTPUT_ENABLE
/* buffer size for buffered output mode */
#define ELOG_BUF_OUTPUT_BUF_SIZE (ELOG_LINE_BUF_SIZE * 10)
#endif /* _ELOG_CFG_H_ */

View File

@@ -0,0 +1,114 @@
//
// Created by wangb on 25-6-4.
//
#include "elog.h"
#include <stdio.h>
#include "main.h"
/**
* EasyLogger port initialize
*
* @return result
*/
ElogErrCode elog_port_init(void) {
ElogErrCode result = ELOG_NO_ERR;
/* add your code here */
return result;
}
/**
* EasyLogger port deinitialize
*
*/
void elog_port_deinit(void) {
/* add your code here */
}
/**
* output log port interface
*
* @param log output of log
* @param size log size
*/
void elog_port_output(const char *log, size_t size) {
/* add your code here */
printf("%.*s", size, log); //elog 的输出
}
/**
* output lock
*/
void elog_port_output_lock(void) {
/* add your code here */
__disable_irq(); //关闭全局中断
}
/**
* output unlock
*/
void elog_port_output_unlock(void) {
/* add your code here */
__enable_irq(); //开启全局中断
}
#include <stdio.h>
/**
* get current time interface
*
* @return current time
*/
const char *elog_port_get_time(void) {
return "";
}
/**
* get current process name interface
*
* @return current process name
*/
const char *elog_port_get_p_info(void) {
/* add your code here */
return "";
}
/**
* get current thread name interface
*
* @return current thread name
*/
const char *elog_port_get_t_info(void) {
/* add your code here */
//获取STM32 的线程接口
return "";
}
void easylogger_init(void) {
/* init Easylogger */
elog_init();
/* set EasyLogger log format */
elog_set_fmt(ELOG_LVL_ASSERT, ELOG_FMT_ALL & ~ELOG_FMT_P_INFO);
elog_set_fmt(ELOG_LVL_ERROR, ELOG_FMT_LVL | ELOG_FMT_TAG | ELOG_FMT_TIME);
elog_set_fmt(ELOG_LVL_WARN, ELOG_FMT_LVL | ELOG_FMT_TAG | ELOG_FMT_TIME);
elog_set_fmt(ELOG_LVL_INFO, ELOG_FMT_LVL | ELOG_FMT_TAG | ELOG_FMT_TIME);
elog_set_fmt(ELOG_LVL_DEBUG, ELOG_FMT_ALL & ~(ELOG_FMT_FUNC | ELOG_FMT_P_INFO));
elog_set_fmt(ELOG_LVL_VERBOSE, ELOG_FMT_ALL & ~(ELOG_FMT_FUNC | ELOG_FMT_P_INFO));
/* start EasyLogger */
elog_start();
}

View File

@@ -0,0 +1,912 @@
//
// Created by wangb on 25-6-4.
//
#define LOG_TAG "elog"
#include "elog.h"
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#if !defined(ELOG_OUTPUT_LVL)
#error "Please configure static output log level (in elog_cfg.h)"
#endif
#if !defined(ELOG_LINE_NUM_MAX_LEN)
#error "Please configure output line number max length (in elog_cfg.h)"
#endif
#if !defined(ELOG_LINE_BUF_SIZE)
#error "Please configure buffer size for every line's log (in elog_cfg.h)"
#endif
#if !defined(ELOG_FILTER_TAG_MAX_LEN)
#error "Please configure output filter's tag max length (in elog_cfg.h)"
#endif
#if !defined(ELOG_FILTER_KW_MAX_LEN)
#error "Please configure output filter's keyword max length (in elog_cfg.h)"
#endif
#if !defined(ELOG_NEWLINE_SIGN)
#error "Please configure output newline sign (in elog_cfg.h)"
#endif
/* output filter's tag level max num */
#ifndef ELOG_FILTER_TAG_LVL_MAX_NUM
#define ELOG_FILTER_TAG_LVL_MAX_NUM 4
#endif
#ifdef ELOG_COLOR_ENABLE
/**
* CSI(Control Sequence Introducer/Initiator) sign
* more information on https://en.wikipedia.org/wiki/ANSI_escape_code
*/
#define CSI_START "\033["
#define CSI_END "\033[0m"
/* output log front color */
#define F_BLACK "30;"
#define F_RED "31;"
#define F_GREEN "32;"
#define F_YELLOW "33;"
#define F_BLUE "34;"
#define F_MAGENTA "35;"
#define F_CYAN "36;"
#define F_WHITE "37;"
/* output log background color */
#define B_NULL
#define B_BLACK "40;"
#define B_RED "41;"
#define B_GREEN "42;"
#define B_YELLOW "43;"
#define B_BLUE "44;"
#define B_MAGENTA "45;"
#define B_CYAN "46;"
#define B_WHITE "47;"
/* output log fonts style */
#define S_BOLD "1m"
#define S_UNDERLINE "4m"
#define S_BLINK "5m"
#define S_NORMAL "22m"
/* output log default color definition: [front color] + [background color] + [show style] */
#ifndef ELOG_COLOR_ASSERT
#define ELOG_COLOR_ASSERT (F_MAGENTA B_NULL S_NORMAL)
#endif
#ifndef ELOG_COLOR_ERROR
#define ELOG_COLOR_ERROR (F_RED B_NULL S_NORMAL)
#endif
#ifndef ELOG_COLOR_WARN
#define ELOG_COLOR_WARN (F_YELLOW B_NULL S_NORMAL)
#endif
#ifndef ELOG_COLOR_INFO
#define ELOG_COLOR_INFO (F_CYAN B_NULL S_NORMAL)
#endif
#ifndef ELOG_COLOR_DEBUG
#define ELOG_COLOR_DEBUG (F_GREEN B_NULL S_NORMAL)
#endif
#ifndef ELOG_COLOR_VERBOSE
#define ELOG_COLOR_VERBOSE (F_BLUE B_NULL S_NORMAL)
#endif
#endif /* ELOG_COLOR_ENABLE */
/* EasyLogger object */
static EasyLogger elog;
/* every line log's buffer */
static char log_buf[ELOG_LINE_BUF_SIZE] = { 0 };
/* level output info */
static const char *level_output_info[] = {
[ELOG_LVL_ASSERT] = "ASSERT/",
[ELOG_LVL_ERROR] = "ERROR/",
[ELOG_LVL_WARN] = "WARN/",
[ELOG_LVL_INFO] = "INFO/",
[ELOG_LVL_DEBUG] = "DEBUG/",
[ELOG_LVL_VERBOSE] = "VERBOS/",
};
#ifdef ELOG_COLOR_ENABLE
/* color output info */
static const char *color_output_info[] = {
[ELOG_LVL_ASSERT] = ELOG_COLOR_ASSERT,
[ELOG_LVL_ERROR] = ELOG_COLOR_ERROR,
[ELOG_LVL_WARN] = ELOG_COLOR_WARN,
[ELOG_LVL_INFO] = ELOG_COLOR_INFO,
[ELOG_LVL_DEBUG] = ELOG_COLOR_DEBUG,
[ELOG_LVL_VERBOSE] = ELOG_COLOR_VERBOSE,
};
#endif /* ELOG_COLOR_ENABLE */
static bool get_fmt_enabled(uint8_t level, size_t set);
static bool get_fmt_used_and_enabled_u32(uint8_t level, size_t set, uint32_t arg);
static bool get_fmt_used_and_enabled_ptr(uint8_t level, size_t set, const char* arg);
static void elog_set_filter_tag_lvl_default(void);
/* EasyLogger assert hook */
void (*elog_assert_hook)(const char* expr, const char* func, size_t line);
extern void elog_port_output(const char *log, size_t size);
extern void elog_port_output_lock(void);
extern void elog_port_output_unlock(void);
/**
* EasyLogger initialize.
*
* @return result
*/
ElogErrCode elog_init(void) {
extern ElogErrCode elog_port_init(void);
extern ElogErrCode elog_async_init(void);
ElogErrCode result = ELOG_NO_ERR;
if (elog.init_ok == true) {
return result;
}
/* port initialize */
result = elog_port_init();
if (result != ELOG_NO_ERR) {
return result;
}
#ifdef ELOG_ASYNC_OUTPUT_ENABLE
result = elog_async_init();
if (result != ELOG_NO_ERR) {
return result;
}
#endif
/* enable the output lock */
elog_output_lock_enabled(true);
/* output locked status initialize */
elog.output_is_locked_before_enable = false;
elog.output_is_locked_before_disable = false;
#ifdef ELOG_COLOR_ENABLE
/* enable text color by default */
elog_set_text_color_enabled(true);
#endif
/* set level is ELOG_LVL_VERBOSE */
elog_set_filter_lvl(ELOG_LVL_VERBOSE);
/* set tag_level to default val */
elog_set_filter_tag_lvl_default();
elog.init_ok = true;
return result;
}
/**
* EasyLogger deinitialize.
*
*/
void elog_deinit(void) {
extern ElogErrCode elog_port_deinit(void);
extern ElogErrCode elog_async_deinit(void);
if (!elog.init_ok) {
return ;
}
#ifdef ELOG_ASYNC_OUTPUT_ENABLE
elog_async_deinit();
#endif
/* port deinitialize */
elog_port_deinit();
elog.init_ok = false;
}
/**
* EasyLogger start after initialize.
*/
void elog_start(void) {
if (!elog.init_ok) {
return ;
}
/* enable output */
elog_set_output_enabled(true);
#if defined(ELOG_ASYNC_OUTPUT_ENABLE)
elog_async_enabled(true);
#elif defined(ELOG_BUF_OUTPUT_ENABLE)
elog_buf_enabled(true);
#endif
}
/**
* EasyLogger stop after initialize.
*/
void elog_stop(void) {
if (!elog.init_ok) {
return ;
}
/* disable output */
elog_set_output_enabled(false);
#if defined(ELOG_ASYNC_OUTPUT_ENABLE)
elog_async_enabled(false);
#elif defined(ELOG_BUF_OUTPUT_ENABLE)
elog_buf_enabled(false);
#endif
/* show version */
log_i("EasyLogger V%s is deinitialize success.", ELOG_SW_VERSION);
}
/**
* set output enable or disable
*
* @param enabled TRUE: enable FALSE: disable
*/
void elog_set_output_enabled(bool enabled) {
ELOG_ASSERT((enabled == false) || (enabled == true));
elog.output_enabled = enabled;
}
#ifdef ELOG_COLOR_ENABLE
/**
* set log text color enable or disable
*
* @param enabled TRUE: enable FALSE:disable
*/
void elog_set_text_color_enabled(bool enabled) {
ELOG_ASSERT((enabled == false) || (enabled == true));
elog.text_color_enabled = enabled;
}
/**
* get log text color enable status
*
* @return enable or disable
*/
bool elog_get_text_color_enabled(void) {
return elog.text_color_enabled;
}
#endif /* ELOG_COLOR_ENABLE */
/**
* get output is enable or disable
*
* @return enable or disable
*/
bool elog_get_output_enabled(void) {
return elog.output_enabled;
}
/**
* set log output format. only enable or disable
*
* @param level level
* @param set format set
*/
void elog_set_fmt(uint8_t level, size_t set) {
ELOG_ASSERT(level <= ELOG_LVL_VERBOSE);
elog.enabled_fmt_set[level] = set;
}
/**
* set log filter all parameter
*
* @param level level
* @param tag tag
* @param keyword keyword
*/
void elog_set_filter(uint8_t level, const char *tag, const char *keyword) {
ELOG_ASSERT(level <= ELOG_LVL_VERBOSE);
elog_set_filter_lvl(level);
elog_set_filter_tag(tag);
elog_set_filter_kw(keyword);
}
/**
* set log filter's level
*
* @param level level
*/
void elog_set_filter_lvl(uint8_t level) {
ELOG_ASSERT(level <= ELOG_LVL_VERBOSE);
elog.filter.level = level;
}
/**
* set log filter's tag
*
* @param tag tag
*/
void elog_set_filter_tag(const char *tag) {
strncpy(elog.filter.tag, tag, ELOG_FILTER_TAG_MAX_LEN);
}
/**
* set log filter's keyword
*
* @param keyword keyword
*/
void elog_set_filter_kw(const char *keyword) {
strncpy(elog.filter.keyword, keyword, ELOG_FILTER_KW_MAX_LEN);
}
/**
* lock output
*/
void elog_output_lock(void) {
if (elog.output_lock_enabled) {
elog_port_output_lock();
elog.output_is_locked_before_disable = true;
} else {
elog.output_is_locked_before_enable = true;
}
}
/**
* unlock output
*/
void elog_output_unlock(void) {
if (elog.output_lock_enabled) {
elog_port_output_unlock();
elog.output_is_locked_before_disable = false;
} else {
elog.output_is_locked_before_enable = false;
}
}
/**
* set log filter's tag level val to default
*/
static void elog_set_filter_tag_lvl_default(void)
{
uint8_t i = 0;
for (i =0; i< ELOG_FILTER_TAG_LVL_MAX_NUM; i++){
memset(elog.filter.tag_lvl[i].tag, '\0', ELOG_FILTER_TAG_MAX_LEN + 1);
elog.filter.tag_lvl[i].level = ELOG_FILTER_LVL_SILENT;
elog.filter.tag_lvl[i].tag_use_flag = false;
}
}
/**
* Set the filter's level by different tag.
* The log on this tag which level is less than it will stop output.
*
* example:
* // the example tag log enter silent mode
* elog_set_filter_tag_lvl("example", ELOG_FILTER_LVL_SILENT);
* // the example tag log which level is less than INFO level will stop output
* elog_set_filter_tag_lvl("example", ELOG_LVL_INFO);
* // remove example tag's level filter, all level log will resume output
* elog_set_filter_tag_lvl("example", ELOG_FILTER_LVL_ALL);
*
* @param tag log tag
* @param level The filter level. When the level is ELOG_FILTER_LVL_SILENT, the log enter silent mode.
* When the level is ELOG_FILTER_LVL_ALL, it will remove this tag's level filer.
* Then all level log will resume output.
*
*/
void elog_set_filter_tag_lvl(const char *tag, uint8_t level)
{
ELOG_ASSERT(level <= ELOG_LVL_VERBOSE);
ELOG_ASSERT(tag != ((void *)0));
uint8_t i = 0;
if (!elog.init_ok) {
return;
}
elog_output_lock();
/* find the tag in arr */
for (i =0; i< ELOG_FILTER_TAG_LVL_MAX_NUM; i++){
if (elog.filter.tag_lvl[i].tag_use_flag == true &&
!strncmp(tag, elog.filter.tag_lvl[i].tag,ELOG_FILTER_TAG_MAX_LEN)){
break;
}
}
if (i < ELOG_FILTER_TAG_LVL_MAX_NUM){
/* find OK */
if (level == ELOG_FILTER_LVL_ALL){
/* remove current tag's level filter when input level is the lowest level */
elog.filter.tag_lvl[i].tag_use_flag = false;
memset(elog.filter.tag_lvl[i].tag, '\0', ELOG_FILTER_TAG_MAX_LEN + 1);
elog.filter.tag_lvl[i].level = ELOG_FILTER_LVL_SILENT;
} else{
elog.filter.tag_lvl[i].level = level;
}
} else{
/* only add the new tag's level filer when level is not ELOG_FILTER_LVL_ALL */
if (level != ELOG_FILTER_LVL_ALL){
for (i =0; i< ELOG_FILTER_TAG_LVL_MAX_NUM; i++){
if (elog.filter.tag_lvl[i].tag_use_flag == false){
strncpy(elog.filter.tag_lvl[i].tag, tag, ELOG_FILTER_TAG_MAX_LEN);
elog.filter.tag_lvl[i].level = level;
elog.filter.tag_lvl[i].tag_use_flag = true;
break;
}
}
}
}
elog_output_unlock();
}
/**
* get the level on tag's level filer
*
* @param tag tag
*
* @return It will return the lowest level when tag was not found.
* Other level will return when tag was found.
*/
uint8_t elog_get_filter_tag_lvl(const char *tag)
{
ELOG_ASSERT(tag != ((void *)0));
uint8_t i = 0;
uint8_t level = ELOG_FILTER_LVL_ALL;
if (!elog.init_ok) {
return level;
}
elog_output_lock();
/* find the tag in arr */
for (i =0; i< ELOG_FILTER_TAG_LVL_MAX_NUM; i++){
if (elog.filter.tag_lvl[i].tag_use_flag == true &&
!strncmp(tag, elog.filter.tag_lvl[i].tag,ELOG_FILTER_TAG_MAX_LEN)){
level = elog.filter.tag_lvl[i].level;
break;
}
}
elog_output_unlock();
return level;
}
/**
* output RAW format log
*
* @param format output format
* @param ... args
*/
void elog_raw_output(const char *format, ...) {
va_list args;
size_t log_len = 0;
int fmt_result;
/* check output enabled */
if (!elog.output_enabled) {
return;
}
/* args point to the first variable parameter */
va_start(args, format);
/* lock output */
elog_output_lock();
/* package log data to buffer */
fmt_result = vsnprintf(log_buf, ELOG_LINE_BUF_SIZE, format, args);
/* output converted log */
if ((fmt_result > -1) && (fmt_result <= ELOG_LINE_BUF_SIZE)) {
log_len = fmt_result;
} else {
log_len = ELOG_LINE_BUF_SIZE;
}
/* output log */
#if defined(ELOG_ASYNC_OUTPUT_ENABLE)
extern void elog_async_output(uint8_t level, const char *log, size_t size);
/* raw log will using assert level */
elog_async_output(ELOG_LVL_ASSERT, log_buf, log_len);
#elif defined(ELOG_BUF_OUTPUT_ENABLE)
extern void elog_buf_output(const char *log, size_t size);
elog_buf_output(log_buf, log_len);
#else
elog_port_output(log_buf, log_len);
#endif
/* unlock output */
elog_output_unlock();
va_end(args);
}
/**
* output the log
*
* @param level level
* @param tag tag
* @param file file name
* @param func function name
* @param line line number
* @param format output format
* @param ... args
*
*/
void elog_output(uint8_t level, const char *tag, const char *file, const char *func,
const long line, const char *format, ...) {
extern const char *elog_port_get_time(void);
extern const char *elog_port_get_p_info(void);
extern const char *elog_port_get_t_info(void);
size_t tag_len = strlen(tag), log_len = 0, newline_len = strlen(ELOG_NEWLINE_SIGN);
char line_num[ELOG_LINE_NUM_MAX_LEN + 1] = { 0 };
char tag_sapce[ELOG_FILTER_TAG_MAX_LEN / 2 + 1] = { 0 };
va_list args;
int fmt_result;
ELOG_ASSERT(level <= ELOG_LVL_VERBOSE);
/* check output enabled */
if (!elog.output_enabled) {
return;
}
/* level filter */
if (level > elog.filter.level || level > elog_get_filter_tag_lvl(tag)) {
return;
} else if (!strstr(tag, elog.filter.tag)) { /* tag filter */
return;
}
/* args point to the first variable parameter */
va_start(args, format);
/* lock output */
elog_output_lock();
#ifdef ELOG_COLOR_ENABLE
/* add CSI start sign and color info */
if (elog.text_color_enabled) {
log_len += elog_strcpy(log_len, log_buf + log_len, CSI_START);
log_len += elog_strcpy(log_len, log_buf + log_len, color_output_info[level]);
}
#endif
/* package level info */
if (get_fmt_enabled(level, ELOG_FMT_LVL)) {
log_len += elog_strcpy(log_len, log_buf + log_len, level_output_info[level]);
}
/* package tag info */
if (get_fmt_enabled(level, ELOG_FMT_TAG)) {
log_len += elog_strcpy(log_len, log_buf + log_len, tag);
/* if the tag length is less than 50% ELOG_FILTER_TAG_MAX_LEN, then fill space */
if (tag_len <= ELOG_FILTER_TAG_MAX_LEN / 2) {
memset(tag_sapce, ' ', ELOG_FILTER_TAG_MAX_LEN / 2 - tag_len);
log_len += elog_strcpy(log_len, log_buf + log_len, tag_sapce);
}
log_len += elog_strcpy(log_len, log_buf + log_len, " ");
}
/* package time, process and thread info */
if (get_fmt_enabled(level, ELOG_FMT_TIME | ELOG_FMT_P_INFO | ELOG_FMT_T_INFO)) {
log_len += elog_strcpy(log_len, log_buf + log_len, "[");
/* package time info */
if (get_fmt_enabled(level, ELOG_FMT_TIME)) {
log_len += elog_strcpy(log_len, log_buf + log_len, elog_port_get_time());
if (get_fmt_enabled(level, ELOG_FMT_P_INFO | ELOG_FMT_T_INFO)) {
log_len += elog_strcpy(log_len, log_buf + log_len, " ");
}
}
/* package process info */
if (get_fmt_enabled(level, ELOG_FMT_P_INFO)) {
log_len += elog_strcpy(log_len, log_buf + log_len, elog_port_get_p_info());
if (get_fmt_enabled(level, ELOG_FMT_T_INFO)) {
log_len += elog_strcpy(log_len, log_buf + log_len, " ");
}
}
/* package thread info */
if (get_fmt_enabled(level, ELOG_FMT_T_INFO)) {
log_len += elog_strcpy(log_len, log_buf + log_len, elog_port_get_t_info());
}
log_len += elog_strcpy(log_len, log_buf + log_len, "] ");
}
/* package file directory and name, function name and line number info */
if (get_fmt_used_and_enabled_ptr(level, ELOG_FMT_DIR, file) ||
get_fmt_used_and_enabled_ptr(level, ELOG_FMT_FUNC, func) ||
get_fmt_used_and_enabled_u32(level, ELOG_FMT_LINE, line)) {
log_len += elog_strcpy(log_len, log_buf + log_len, "(");
/* package file info */
if (get_fmt_used_and_enabled_ptr(level, ELOG_FMT_DIR, file)) {
log_len += elog_strcpy(log_len, log_buf + log_len, file);
if (get_fmt_used_and_enabled_ptr(level, ELOG_FMT_FUNC, func)) {
log_len += elog_strcpy(log_len, log_buf + log_len, ":");
} else if (get_fmt_used_and_enabled_u32(level, ELOG_FMT_LINE, line)) {
log_len += elog_strcpy(log_len, log_buf + log_len, " ");
}
}
/* package line info */
if (get_fmt_used_and_enabled_u32(level, ELOG_FMT_LINE, line)) {
snprintf(line_num, ELOG_LINE_NUM_MAX_LEN, "%ld", line);
log_len += elog_strcpy(log_len, log_buf + log_len, line_num);
if (get_fmt_used_and_enabled_ptr(level, ELOG_FMT_FUNC, func)) {
log_len += elog_strcpy(log_len, log_buf + log_len, " ");
}
}
/* package func info */
if (get_fmt_used_and_enabled_ptr(level, ELOG_FMT_FUNC, func)) {
log_len += elog_strcpy(log_len, log_buf + log_len, func);
}
log_len += elog_strcpy(log_len, log_buf + log_len, ")");
}
/* package other log data to buffer. '\0' must be added in the end by vsnprintf. */
fmt_result = vsnprintf(log_buf + log_len, ELOG_LINE_BUF_SIZE - log_len, format, args);
va_end(args);
/* calculate log length */
if ((log_len + fmt_result <= ELOG_LINE_BUF_SIZE) && (fmt_result > -1)) {
log_len += fmt_result;
} else {
/* using max length */
log_len = ELOG_LINE_BUF_SIZE;
}
/* overflow check and reserve some space for CSI end sign and newline sign */
#ifdef ELOG_COLOR_ENABLE
if (log_len + (sizeof(CSI_END) - 1) + newline_len > ELOG_LINE_BUF_SIZE) {
/* using max length */
log_len = ELOG_LINE_BUF_SIZE;
/* reserve some space for CSI end sign */
log_len -= (sizeof(CSI_END) - 1);
#else
if (log_len + newline_len > ELOG_LINE_BUF_SIZE) {
/* using max length */
log_len = ELOG_LINE_BUF_SIZE;
#endif /* ELOG_COLOR_ENABLE */
/* reserve some space for newline sign */
log_len -= newline_len;
}
/* keyword filter */
if (elog.filter.keyword[0] != '\0') {
/* add string end sign */
log_buf[log_len] = '\0';
/* find the keyword */
if (!strstr(log_buf, elog.filter.keyword)) {
/* unlock output */
elog_output_unlock();
return;
}
}
#ifdef ELOG_COLOR_ENABLE
/* add CSI end sign */
if (elog.text_color_enabled) {
log_len += elog_strcpy(log_len, log_buf + log_len, CSI_END);
}
#endif
/* package newline sign */
log_len += elog_strcpy(log_len, log_buf + log_len, ELOG_NEWLINE_SIGN);
/* output log */
#if defined(ELOG_ASYNC_OUTPUT_ENABLE)
extern void elog_async_output(uint8_t level, const char *log, size_t size);
elog_async_output(level, log_buf, log_len);
#elif defined(ELOG_BUF_OUTPUT_ENABLE)
extern void elog_buf_output(const char *log, size_t size);
elog_buf_output(log_buf, log_len);
#else
elog_port_output(log_buf, log_len);
#endif
/* unlock output */
elog_output_unlock();
}
/**
* get format enabled
*
* @param level level
* @param set format set
*
* @return enable or disable
*/
static bool get_fmt_enabled(uint8_t level, size_t set) {
ELOG_ASSERT(level <= ELOG_LVL_VERBOSE);
if (elog.enabled_fmt_set[level] & set) {
return true;
} else {
return false;
}
}
static bool get_fmt_used_and_enabled_u32(uint8_t level, size_t set, uint32_t arg) {
return arg && get_fmt_enabled(level, set);
}
static bool get_fmt_used_and_enabled_ptr(uint8_t level, size_t set, const char* arg) {
return arg && get_fmt_enabled(level, set);
}
/**
* enable or disable logger output lock
* @note disable this lock is not recommended except you want output system exception log
*
* @param enabled true: enable false: disable
*/
void elog_output_lock_enabled(bool enabled) {
elog.output_lock_enabled = enabled;
/* it will re-lock or re-unlock before output lock enable */
if (elog.output_lock_enabled) {
if (!elog.output_is_locked_before_disable && elog.output_is_locked_before_enable) {
/* the output lock is unlocked before disable, and the lock will unlocking after enable */
elog_port_output_lock();
} else if (elog.output_is_locked_before_disable && !elog.output_is_locked_before_enable) {
/* the output lock is locked before disable, and the lock will locking after enable */
elog_port_output_unlock();
}
}
}
/**
* Set a hook function to EasyLogger assert. It will run when the expression is false.
*
* @param hook the hook function
*/
void elog_assert_set_hook(void (*hook)(const char* expr, const char* func, size_t line)) {
elog_assert_hook = hook;
}
/**
* find the log level
* @note make sure the log level is output on each format
*
* @param log log buffer
*
* @return log level, found failed will return -1
*/
int8_t elog_find_lvl(const char *log) {
ELOG_ASSERT(log);
/* make sure the log level is output on each format */
ELOG_ASSERT(elog.enabled_fmt_set[ELOG_LVL_ASSERT] & ELOG_FMT_LVL);
ELOG_ASSERT(elog.enabled_fmt_set[ELOG_LVL_ERROR] & ELOG_FMT_LVL);
ELOG_ASSERT(elog.enabled_fmt_set[ELOG_LVL_WARN] & ELOG_FMT_LVL);
ELOG_ASSERT(elog.enabled_fmt_set[ELOG_LVL_INFO] & ELOG_FMT_LVL);
ELOG_ASSERT(elog.enabled_fmt_set[ELOG_LVL_DEBUG] & ELOG_FMT_LVL);
ELOG_ASSERT(elog.enabled_fmt_set[ELOG_LVL_VERBOSE] & ELOG_FMT_LVL);
#ifdef ELOG_COLOR_ENABLE
uint8_t i;
size_t csi_start_len = strlen(CSI_START);
for(i = 0; i < ELOG_LVL_TOTAL_NUM; i ++) {
if (!strncmp(color_output_info[i], log + csi_start_len, strlen(color_output_info[i]))) {
return i;
}
}
/* found failed */
return -1;
#else
switch (log[0]) {
case 'A': return ELOG_LVL_ASSERT;
case 'E': return ELOG_LVL_ERROR;
case 'W': return ELOG_LVL_WARN;
case 'I': return ELOG_LVL_INFO;
case 'D': return ELOG_LVL_DEBUG;
case 'V': return ELOG_LVL_VERBOSE;
default: return -1;
}
#endif
}
/**
* find the log tag
* @note make sure the log tag is output on each format
* @note the tag don't have space in it
*
* @param log log buffer
* @param lvl log level, you can get it by @see elog_find_lvl
* @param tag_len found tag length
*
* @return log tag, found failed will return NULL
*/
const char *elog_find_tag(const char *log, uint8_t lvl, size_t *tag_len) {
const char *tag = NULL, *tag_end = NULL;
ELOG_ASSERT(log);
ELOG_ASSERT(tag_len);
ELOG_ASSERT(lvl < ELOG_LVL_TOTAL_NUM);
/* make sure the log tag is output on each format */
ELOG_ASSERT(elog.enabled_fmt_set[lvl] & ELOG_FMT_TAG);
#ifdef ELOG_COLOR_ENABLE
tag = log + strlen(CSI_START) + strlen(color_output_info[lvl]) + strlen(level_output_info[lvl]);
#else
tag = log + strlen(level_output_info[lvl]);
#endif
/* find the first space after tag */
if ((tag_end = memchr(tag, ' ', ELOG_FILTER_TAG_MAX_LEN)) != NULL) {
*tag_len = tag_end - tag;
} else {
tag = NULL;
}
return tag;
}
/**
* dump the hex format data to log
*
* @param name name for hex object, it will show on log header
* @param width hex number for every line, such as: 16, 32
* @param buf hex buffer
* @param size buffer size
*/
void elog_hexdump(const char *name, uint8_t width, const void *buf, uint16_t size)
{
#define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
uint16_t i, j;
uint16_t log_len = 0;
const uint8_t *buf_p = buf;
char dump_string[8] = {0};
int fmt_result;
if (!elog.output_enabled) {
return;
}
/* level filter */
if (ELOG_LVL_DEBUG > elog.filter.level) {
return;
} else if (!strstr(name, elog.filter.tag)) { /* tag filter */
return;
}
/* lock output */
elog_output_lock();
for (i = 0; i < size; i += width) {
/* package header */
fmt_result = snprintf(log_buf, ELOG_LINE_BUF_SIZE, "D/HEX %s: %04X-%04X: ", name, i, i + width - 1);
/* calculate log length */
if ((fmt_result > -1) && (fmt_result <= ELOG_LINE_BUF_SIZE)) {
log_len = fmt_result;
} else {
log_len = ELOG_LINE_BUF_SIZE;
}
/* dump hex */
for (j = 0; j < width; j++) {
if (i + j < size) {
snprintf(dump_string, sizeof(dump_string), "%02X ", buf_p[i + j]);
} else {
strncpy(dump_string, " ", sizeof(dump_string));
}
log_len += elog_strcpy(log_len, log_buf + log_len, dump_string);
if ((j + 1) % 8 == 0) {
log_len += elog_strcpy(log_len, log_buf + log_len, " ");
}
}
log_len += elog_strcpy(log_len, log_buf + log_len, " ");
/* dump char for hex */
for (j = 0; j < width; j++) {
if (i + j < size) {
snprintf(dump_string, sizeof(dump_string), "%c", __is_print(buf_p[i + j]) ? buf_p[i + j] : '.');
log_len += elog_strcpy(log_len, log_buf + log_len, dump_string);
}
}
/* overflow check and reserve some space for newline sign */
if (log_len + strlen(ELOG_NEWLINE_SIGN) > ELOG_LINE_BUF_SIZE) {
log_len = ELOG_LINE_BUF_SIZE - strlen(ELOG_NEWLINE_SIGN);
}
/* package newline sign */
log_len += elog_strcpy(log_len, log_buf + log_len, ELOG_NEWLINE_SIGN);
/* do log output */
#if defined(ELOG_ASYNC_OUTPUT_ENABLE)
extern void elog_async_output(uint8_t level, const char *log, size_t size);
elog_async_output(ELOG_LVL_DEBUG, log_buf, log_len);
#elif defined(ELOG_BUF_OUTPUT_ENABLE)
extern void elog_buf_output(const char *log, size_t size);
elog_buf_output(log_buf, log_len);
#else
elog_port_output(log_buf, log_len);
#endif
}
/* unlock output */
elog_output_unlock();
}

View File

@@ -0,0 +1,79 @@
//
// Created by wangb on 25-6-4.
//
#include "elog.h"
#include <string.h>
/**
* another copy string function
*
* @param cur_len current copied log length, max size is ELOG_LINE_BUF_SIZE
* @param dst destination
* @param src source
*
* @return copied length
*/
size_t elog_strcpy(size_t cur_len, char *dst, const char *src) {
const char *src_old = src;
assert(dst);
assert(src);
while (*src != 0) {
/* make sure destination has enough space */
if (cur_len++ < ELOG_LINE_BUF_SIZE) {
*dst++ = *src++;
} else {
break;
}
}
return src - src_old;
}
/**
* Copy line log split by newline sign. It will copy all log when the newline sign isn't find.
*
* @param line line log buffer
* @param log origin log buffer
* @param len origin log buffer length
*
* @return copy size
*/
size_t elog_cpyln(char *line, const char *log, size_t len) {
size_t newline_len = strlen(ELOG_NEWLINE_SIGN), copy_size = 0;
assert(line);
assert(log);
while (len--) {
*line++ = *log++;
copy_size++;
if (copy_size >= newline_len && !strncmp(log - newline_len, ELOG_NEWLINE_SIGN, newline_len)) {
break;
}
}
return copy_size;
}
/**
* This function will copy memory content from source address to destination
* address.
*
* @param dst the address of destination memory
* @param src the address of source memory
* @param count the copied length
*
* @return the address of destination memory
*/
void *elog_memcpy(void *dst, const void *src, size_t count) {
char *tmp = (char *) dst, *s = (char *) src;
assert(dst);
assert(src);
while (count--)
*tmp++ = *s++;
return dst;
}

View File

@@ -25,6 +25,16 @@
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "usart.h"
#include "adc.h"
#include "tim.h"
#include "motor_driver.h"
#include "elog.h"
#include <stdint.h>
#include <stdio.h>
#include "screen.h"
#include <string.h>
#include <sys/_intsup.h>
/* USER CODE END Includes */
@@ -40,12 +50,29 @@
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
#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(&huart5, (uint8_t *) &ch, 1, HAL_MAX_DELAY);
return ch;
}
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */
/* 按键状态位: bit0..bit3 分别对应 M__KEY, M__KEYC7, HOT_KEY, TIME_KEY, 为1表示按下 */
volatile uint8_t key_state = 0;
volatile uint8_t key_state_prev = 0; /* 上一次的按键状态,用于检测按键变化 */
/* 设备状态标志0表示关闭1表示打开 */
static uint8_t hot_state = 0; /* HOT 设备状态 */
static uint8_t time_state = 0; /* TIME_KEY 时间状态 */
/* USER CODE END Variables */
/* Definitions for defaultTask */
osThreadId_t defaultTaskHandle;
@@ -54,6 +81,41 @@ const osThreadAttr_t defaultTask_attributes = {
.stack_size = 128 * 4,
.priority = (osPriority_t) osPriorityNormal,
};
/* Definitions for KeyTask */
osThreadId_t KeyTaskHandle;
const osThreadAttr_t KeyTask_attributes = {
.name = "KeyTask",
.stack_size = 512 * 4,
.priority = (osPriority_t) osPriorityRealtime,
};
/* Definitions for Sensor_Task */
osThreadId_t Sensor_TaskHandle;
const osThreadAttr_t Sensor_Task_attributes = {
.name = "Sensor_Task",
.stack_size = 512 * 4,
.priority = (osPriority_t) osPriorityHigh7,
};
/* Definitions for Temp_Task */
osThreadId_t Temp_TaskHandle;
const osThreadAttr_t Temp_Task_attributes = {
.name = "Temp_Task",
.stack_size = 256 * 4,
.priority = (osPriority_t) osPriorityNormal,
};
/* Definitions for Motor_Task */
osThreadId_t Motor_TaskHandle;
const osThreadAttr_t Motor_Task_attributes = {
.name = "Motor_Task",
.stack_size = 512 * 4,
.priority = (osPriority_t) osPriorityNormal1,
};
/* Definitions for Screen_Tsak */
osThreadId_t Screen_TsakHandle;
const osThreadAttr_t Screen_Tsak_attributes = {
.name = "Screen_Tsak",
.stack_size = 1024 * 4,
.priority = (osPriority_t) osPriorityNormal,
};
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */
@@ -61,6 +123,11 @@ const osThreadAttr_t defaultTask_attributes = {
/* USER CODE END FunctionPrototypes */
void StartDefaultTask(void *argument);
void Key(void *argument);
void Sensor(void *argument);
void Temp(void *argument);
void Motor(void *argument);
void Screen(void *argument);
void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */
@@ -71,7 +138,9 @@ void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */
*/
void MX_FREERTOS_Init(void) {
/* USER CODE BEGIN Init */
easylogger_init(); /* 初始化 EasyLogger */
__enable_irq(); //开启全局中断
elog_i("task_init", "任务初始!");
/* USER CODE END Init */
/* USER CODE BEGIN RTOS_MUTEX */
@@ -94,6 +163,21 @@ void MX_FREERTOS_Init(void) {
/* creation of defaultTask */
defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);
/* creation of KeyTask */
KeyTaskHandle = osThreadNew(Key, NULL, &KeyTask_attributes);
/* creation of Sensor_Task */
Sensor_TaskHandle = osThreadNew(Sensor, NULL, &Sensor_Task_attributes);
/* creation of Temp_Task */
Temp_TaskHandle = osThreadNew(Temp, NULL, &Temp_Task_attributes);
/* creation of Motor_Task */
Motor_TaskHandle = osThreadNew(Motor, NULL, &Motor_Task_attributes);
/* creation of Screen_Tsak */
Screen_TsakHandle = osThreadNew(Screen, NULL, &Screen_Tsak_attributes);
/* USER CODE BEGIN RTOS_THREADS */
/* add threads, ... */
/* USER CODE END RTOS_THREADS */
@@ -114,14 +198,312 @@ void MX_FREERTOS_Init(void) {
void StartDefaultTask(void *argument)
{
/* USER CODE BEGIN StartDefaultTask */
// 初始化命令
uint8_t init_cmd1[] = {0x7E, 0xFF, 0x06, 0x06, 0x00, 0x00, 0x1E, 0xFE, 0xD7, 0xEF}; // 开启声音
uint8_t init_cmd2[] = {0x7E, 0xFF, 0x06, 0x09, 0x00, 0x00, 0x02, 0xFE, 0xF0, 0xEF}; // 指定播放设备为TF卡
// 定义测试指令数据
uint8_t test_cmd[] = {0x7E, 0xFF, 0x06, 0x12, 0x00, 0x00, 0x01, 0xFE, 0xE8, 0xEF};
// 先让模块稳定
osDelay(2000);
// 初始化:先发送开启声音指令,再发送指定播放设备指令
HAL_UART_Transmit(&huart3, init_cmd1, sizeof(init_cmd1), 1000);
osDelay(1500); // 重要:等待模块响应
HAL_UART_Transmit(&huart3, init_cmd2, sizeof(init_cmd2), 1000);
osDelay(1500); // 重要:等待初始化完成
/* Infinite loop */
for(;;)
{
osDelay(1);
// 直接整包发送测试指令
HAL_UART_Transmit(&huart3, test_cmd, sizeof(test_cmd), 1000);
// 把发送的数据打印出来
//elog_d("mp3_cmd","发送测试指令: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", test_cmd[0], test_cmd[1], test_cmd[2], test_cmd[3], test_cmd[4], test_cmd[5], test_cmd[6], test_cmd[7], test_cmd[8], test_cmd[9]);
// 可选:等待发送完成
// while(__HAL_UART_GET_FLAG(&huart3, UART_FLAG_TC) == RESET);
HAL_GPIO_TogglePin(RUN_LED_GPIO_Port, RUN_LED_Pin);
osDelay(1000); // 延时1秒
}
/* USER CODE END StartDefaultTask */
}
/* USER CODE BEGIN Header_Key */
/**
* @brief Function implementing the KeyTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_Key */
void Key(void *argument)
{
/* USER CODE BEGIN Key */
/* 防抖轮询实现四个低电平有效按键检测 */
GPIO_TypeDef* key_ports[4] = {M__KEY_GPIO_Port, M__KEYC7_GPIO_Port, HOT_KEY_GPIO_Port, TIME_KEY_GPIO_Port};
const uint16_t key_pins[4] = {M__KEY_Pin, M__KEYC7_Pin, HOT_KEY_Pin, TIME_KEY_Pin};
uint8_t press_count[4] = {0};
uint8_t release_count[4] = {0};
uint8_t pressed[4] = {0};
const uint8_t THRESH = 3; /* 3 * 10ms = 30ms 防抖 */
for(;;)
{
for (int i = 0; i < 4; i++) {
GPIO_PinState level = HAL_GPIO_ReadPin(key_ports[i], key_pins[i]);
if (level == GPIO_PIN_RESET) { /* 低电平有效 */
press_count[i]++;
release_count[i] = 0;
if (!pressed[i] && press_count[i] >= THRESH) {
pressed[i] = 1;
key_state |= (1 << i); /* bit0..3 分别对应四个按键按下状态 */
}
} else {
release_count[i]++;
press_count[i] = 0;
if (pressed[i] && release_count[i] >= THRESH) {
pressed[i] = 0;
key_state &= ~(1 << i);
}
}
}
osDelay(10); /* 10ms 轮询间隔 */
}
/* USER CODE END Key */
}
/* USER CODE BEGIN Header_Sensor */
/**
* @brief Function implementing the Sensor_Task thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_Sensor */
void Sensor(void *argument)
{
/* USER CODE BEGIN Sensor */
/* 按键处理任务 - 按键状态切换控制 */
/* Infinite loop */
for(;;)
{
/* 检测新按下的按键 */
uint8_t key_pressed = key_state & ~key_state_prev;
key_state_prev = key_state;
/* ===== M__KEY (bit0) 控制 ===== */
if (key_pressed & (1 << 0)) {
/* M__KEY 按下:加档(提高转速) */
elog_i("Key", "M__KEY按下 - 加档");
if (Motor_GetGear() == 0) {
Motor_StartupBoost();
} else {
Motor_GearUp();
}
}
/* ===== M__KEYC7 (bit1) 控制 ===== */
if (key_pressed & (1 << 1)) {
/* M__KEYC7 按下:降档(降低转速) */
elog_i("Key", "M__KEYC7按下 - 降档");
Motor_GearDown();
}
/* ===== HOT_KEY (bit2) 控制 ===== */
if (key_pressed & (1 << 2)) {
/* HOT_KEY 按下:切换热功能 */
hot_state = !hot_state;
HAL_GPIO_WritePin(HOT_GPIO_Port, HOT_Pin, hot_state ? GPIO_PIN_SET : GPIO_PIN_RESET);
}
/* ===== TIME_KEY (bit3) 控制 ===== */
if (key_pressed & (1 << 3)) {
/* TIME_KEY 按下:切换定时 */
time_state = !time_state;
if (time_state) {
// TODO: 添加定时启动逻辑
} else {
// TODO: 添加定时关闭逻辑
}
}
osDelay(20); /* 20ms 检查一次按键状态 */
}
/* USER CODE END Sensor */
}
/* USER CODE BEGIN Header_Temp */
/**
* @brief Function implementing the Temp_Task thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_Temp */
void Temp(void *argument)
{
/* USER CODE BEGIN Temp */
#ifdef ENABLE_TEMP_SENSOR
/* ADC采集参数 */
uint32_t adc_raw = 0; /* ADC原始值 */
uint32_t adc_sum = 0; /* 累加和(用于平均) */
uint16_t sample_count = 32; /* 采样次数 */
float voltage = 0.0f; /* 转换后的电压 */
float temperature = 0.0f; /* 转换后的温度 */
/* 电路参数 */
const float VREF = 3.3f; /* 参考电压 */
/* 一阶低通滤波器 */
float adc_filtered = 0.0f; /* 滤波后的ADC值 */
const float FILTER_ALPHA = 0.1f; /* 滤波系数 */
/* NTC 10K 3950参数 */
const float NTC_B_VALUE = 3950.0f; /* NTC B值 */
const float NTC_R0 = 10000.0f; /* 25°C时电阻10K */
const float NTC_T0 = 298.15f; /* 25°C对应的绝对温度(K) */
const float R_FIXED = 10000.0f; /* 分压电阻10K */
/* ADC校准 */
HAL_ADCEx_Calibration_Start(&hadc1);
/* 预热先采集几次丢弃稳定ADC */
for (uint16_t i = 0; i < 10; i++) {
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, 100);
HAL_ADC_GetValue(&hadc1);
HAL_ADC_Stop(&hadc1);
osDelay(10);
}
/* Infinite loop */
for(;;)
{
/* 采集多次求平均,提高精度 */
adc_sum = 0;
for (uint16_t i = 0; i < sample_count; i++) {
HAL_ADC_Start(&hadc1);
if (HAL_ADC_PollForConversion(&hadc1, 100) == HAL_OK) {
adc_sum += HAL_ADC_GetValue(&hadc1);
}
HAL_ADC_Stop(&hadc1);
osDelay(20);
}
/* 计算平均值 */
adc_raw = adc_sum / sample_count;
/* 一阶低通滤波 */
if (adc_filtered == 0.0f) {
adc_filtered = (float)adc_raw;
} else {
adc_filtered = FILTER_ALPHA * (float)adc_raw + (1.0f - FILTER_ALPHA) * adc_filtered;
}
adc_raw = (uint32_t)(adc_filtered + 0.5f);
/* 转换为电压 */
voltage = ((float)adc_raw / 4095.0f) * VREF;
/* ==================== NTC 10K 3950 温度计算 ====================
* 电路3.3V ──[10K固定电阻]──┬── PA0 (ADC)
* │
* [NTC 10K]
* │
* GND
*
* Steinhart-Hart简化方程
* 1/T = 1/T0 + (1/B) * ln(R/R0)
*/
{
/* 计算NTC电阻值 */
float ntc_resistance = R_FIXED * voltage / (VREF - voltage);
/* Steinhart-Hart方程计算温度(K) */
float steinhart = logf(ntc_resistance / NTC_R0) / NTC_B_VALUE + 1.0f / NTC_T0;
temperature = 1.0f / steinhart - 273.15f; /* 转换为摄氏度 */
elog_i("Temp", "ADC:%lu 电压:%.3fV NTC:%.1fΩ 温度:%.1f°C",
adc_raw, voltage, ntc_resistance, temperature);
}
osDelay(1000);
}
#else
/* 温度传感器未启用,任务空转 */
elog_i("Temp", "温度传感器未启用等待NTC改装...");
for(;;)
{
osDelay(5000);
elog_i("Temp", "温度传感器未启用等待NTC改装...");
}
#endif /* ENABLE_TEMP_SENSOR */
/* USER CODE END Temp */
}
/* USER CODE BEGIN Header_Motor */
/**
* @brief Function implementing the Motor_Task thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_Motor */
void Motor(void *argument)
{
/* USER CODE BEGIN Motor */
/* 电机驱动初始化 */
Motor_Init();
/* Infinite loop */
for(;;)
{
/* 电机任务主要功能:
* - 监控电机状态(超温保护、过流保护等)
* - 定期打印状态信息
* - 响应紧急停止信号
*/
/* 每1秒打印一次电机状态 */
uint8_t current_gear = Motor_GetGear();
elog_i("Motor", "当前档位: %u (0=停止,1=低,2=中,3=高)", current_gear);
osDelay(1000);
}
/* USER CODE END Motor */
}
/* USER CODE BEGIN Header_Screen */
/**
* @brief Function implementing the Screen_Tsak thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_Screen */
void Screen(void *argument)
{
/* USER CODE BEGIN Screen */
char buf[100];
sprintf(buf, "CLR(1);\r\n");
//HAL_UART_Transmit(&huart1, (uint8_t *)buf, strlen(buf), HAL_MAX_DELAY);
/* Infinite loop */
for(;;)
{
HAL_UART_Transmit(&huart1, (uint8_t *)buf, strlen(buf), HAL_MAX_DELAY);
osDelay(2000);
}
/* USER CODE END Screen */
}
/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */

View File

@@ -50,9 +50,19 @@ void MX_GPIO_Init(void)
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(HOT_GPIO_Port, HOT_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, RUN_LED_Pin|ERR_LED_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin : HOT_Pin */
GPIO_InitStruct.Pin = HOT_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(HOT_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pins : RUN_LED_Pin ERR_LED_Pin */
GPIO_InitStruct.Pin = RUN_LED_Pin|ERR_LED_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
@@ -63,7 +73,7 @@ void MX_GPIO_Init(void)
/*Configure GPIO pins : M__KEY_Pin M__KEYC7_Pin HOT_KEY_Pin TIME_KEY_Pin */
GPIO_InitStruct.Pin = M__KEY_Pin|M__KEYC7_Pin|HOT_KEY_Pin|TIME_KEY_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
}

128
Core/Src/motor_driver.c Normal file
View File

@@ -0,0 +1,128 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file motor_driver.c
* @brief 电机驱动实现 - 双路AT8236-MS H桥驱动
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "motor_driver.h"
#include "elog.h"
#include "stm32f1xx_hal.h"
#include "stm32f1xx_hal_tim.h"
#include "cmsis_os.h"
#include "tim.h"
/* Private defines -----------------------------------------------------------*/
/* TIM4自动重装载值是99 (100-1)所以PWM值范围是0-99 */
/* Private function prototypes -----------------------------------------------*/
/* PWM parameters */
#define PWM_ARR 99
#define PWM_STEPS (PWM_ARR + 1)
/* 三档占空比(百分比),索引为 0..2 对应 档位 1..3档位0为停止 */
static const uint8_t gears_percent[3] = {75, 80, 85};
/* current_gear: 0 = 停止, 1 = 低, 2 = 中, 3 = 高 */
static uint8_t current_gear = 0; /* 0..3 */
static inline uint32_t percent_to_compare(uint8_t percent) {
return ((uint32_t)percent * PWM_STEPS) / 100U;
}
/* 将两个电机都设置为指定占空比(只使用 TIM4_CH2, TIM4_CH4 输出CH1/CH3 停止以保持单方向) */
static void set_both_motors_percent(uint8_t percent) {
uint32_t cmp = percent_to_compare(percent);
/* 停止并关闭 CH1、使用 CH2 输出 */
HAL_TIM_PWM_Stop(&htim4, TIM_CHANNEL_1);
__HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_2, (uint16_t)cmp);
/* 停止并关闭 CH3、使用 CH4 输出 */
HAL_TIM_PWM_Stop(&htim4, TIM_CHANNEL_3);
__HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_4, (uint16_t)cmp);
}
/* 启动时短暂提升到 90% 并保持 500ms然后降到一档档位1 */
void Motor_StartupBoost(void) {
set_both_motors_percent(90);
osDelay(1500);
current_gear = 1; /* 启动后回到档位1最低速 */
set_both_motors_percent(gears_percent[current_gear - 1]);
}
/* 设置挡位0..30=停止 */
void Motor_SetGear(uint8_t gear) {
if (gear > 3) gear = 3;
current_gear = gear;
if (current_gear == 0) {
set_both_motors_percent(0);
} else {
set_both_motors_percent(gears_percent[current_gear - 1]);
}
}
/* 切换到下一档0->1->2->3->0 循环) */
void Motor_NextGear(void) {
current_gear++;
if (current_gear > 3) current_gear = 0;
if (current_gear == 0) {
set_both_motors_percent(0);
} else {
set_both_motors_percent(gears_percent[current_gear - 1]);
}
}
/* 向上加档(与按键配合使用) */
void Motor_GearUp(void) {
Motor_NextGear();
}
/* 向下减档(循环) */
void Motor_GearDown(void) {
if (current_gear == 0) {
current_gear = 3;
} else {
current_gear--;
}
if (current_gear == 0) {
set_both_motors_percent(0);
} else {
set_both_motors_percent(gears_percent[current_gear - 1]);
}
}
uint8_t Motor_GetGear(void) {
return current_gear;
}
/* Exported functions --------------------------------------------------------*/
/**
* @brief 电机驱动初始化
*/
void Motor_Init(void) {
/* 启动TIM4 PWM输出 */
HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_2);
HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_3);
HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_4);
// 初始完全停止电机
Motor_Stop();
}
void Motor_Stop(void) {
// 所有引脚输出0 - 完全停止
__HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_1, 0);
__HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_2, 0);
__HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_3, 0);
__HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_4, 0);
}

40
Core/Src/motor_driver.h Normal file
View File

@@ -0,0 +1,40 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file motor_driver.h
* @brief 电机驱动头文件 - 双路AT8236-MS H桥驱动
******************************************************************************
* @attention
*
* AT8236-MS 双路H桥电机驱动芯片
* - 芯片1: TIM4_CH1 -> AIN1, TIM4_CH2 -> AIN2
* - 芯片2: TIM4_CH3 -> BIN1, TIM4_CH4 -> BIN2
* - 两路电机同步控制:同时启动、同时停止
******************************************************************************
*/
/* USER CODE END Header */
#ifndef __MOTOR_DRIVER_H__
#define __MOTOR_DRIVER_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
void Motor_Init(void);
void Motor_Stop(void) ;
void Motor_StartupBoost(void);
void Motor_SetGear(uint8_t gear);
void Motor_NextGear(void);
void Motor_GearUp(void);
void Motor_GearDown(void);
uint8_t Motor_GetGear(void);
#ifdef __cplusplus
}
#endif
#endif /* __MOTOR_DRIVER_H__ */

189
Core/Src/screen.c Normal file
View File

@@ -0,0 +1,189 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file screen.c
* @brief 串口屏驱动实现JC系列使用 USART1
******************************************************************************
*/
/* USER CODE END Header */
#include "screen.h"
#include "main.h"
#include "usart.h"
#include "cmsis_os.h"
#include <string.h>
#include <stdio.h>
/* 模块初始化:不要使用 MP3 的二进制初始化指令,改为屏幕清屏作为默认初始化 */
/* 发送缓冲 */
static char txbuf[256];
/**
* @brief 发送字符串到串口屏(阻塞直到发送完成)
* @param cmd: 要发送的C字符串不强制包含结尾CR/LF
* @retval 0=OK, <0=错误
*/
int Screen_SendCmd(const char *cmd) {
if (cmd == NULL) return -1;
size_t len = strlen(cmd);
if (len == 0) return -1;
HAL_StatusTypeDef st = HAL_UART_Transmit(&huart1, (uint8_t *)cmd, (uint16_t)len, HAL_MAX_DELAY);
return (st == HAL_OK) ? 0 : -2;
}
/**
* @brief 发送命令并等待模块返回 "OK\r\n"超时返回非0
*/
int Screen_SendCmdWaitOK(const char *cmd, uint32_t timeout_ms) {
(void)timeout_ms;
/* 保留接口:当前不等待屏幕回包,直接发送后返回发送状态 */
return Screen_SendCmd(cmd);
}
void Screen_Init(void) {
/*
* 屏幕初始化:简单实现为上电等待并清除屏幕
* 若需要按照厂商例程发送更多配置指令,可在此扩展
*/
osDelay(1000);
Screen_Clear(0);
osDelay(200);
}
/* 简单封装接口示例 */
void Screen_Clear(uint8_t layer) {
sprintf(txbuf, "DIR(1);CLR(%u);\r\n", (unsigned)layer);
Screen_SendCmd(txbuf);
}
void Screen_DisplayImage(uint32_t addr) {
sprintf(txbuf, "DIR(1);FSIMG(%lu,0,0,128,128,0);\r\n", (unsigned long)addr);
Screen_SendCmd(txbuf);
}
void Screen_SetBrightness(uint8_t val) {
sprintf(txbuf, "BL(%u);\r\n", (unsigned)val);
Screen_SendCmd(txbuf);
}
void Screen_DrawText16(uint16_t x, uint16_t y, const char *text, uint8_t color) {
sprintf(txbuf, "SBC(%u);DC16(%u,%u,'%s',%u);\r\n", (unsigned)color, (unsigned)x, (unsigned)y, text, (unsigned)color);
Screen_SendCmd(txbuf);
}
/* 额外封装实现 */
/* 以下为屏幕命令封装函数实现,均以字符串形式发送到串口屏 */
/* 函数内部不等待屏幕回包,调用者若需确认执行结果请自行实现回包处理 */
void Screen_SetRotation(uint8_t dir) {
sprintf(txbuf, "DIR(%u);\r\n", dir);
Screen_SendCmd(txbuf);
}
void Screen_SetBaud(uint32_t baud) {
sprintf(txbuf, "BPS(%lu);\r\n", (unsigned long)baud);
Screen_SendCmd(txbuf);
}
void Screen_DisplayImageAtAddr(uint32_t addr, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint8_t mode) {
sprintf(txbuf, "FSIMG(%lu,%u,%u,%u,%u,%u);\r\n", (unsigned long)addr, (unsigned)x, (unsigned)y, (unsigned)w, (unsigned)h, (unsigned)mode);
Screen_SendCmd(txbuf);
}
void Screen_DisplayImageByIndex(uint32_t index, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint8_t mode) {
sprintf(txbuf, "FSIMG(%u,%u,%u,%u,%u,%u);\r\n", (unsigned)index, (unsigned)x, (unsigned)y, (unsigned)w, (unsigned)h, (unsigned)mode);
Screen_SendCmd(txbuf);
}
void Screen_Pixel(uint16_t x, uint16_t y, uint8_t color) {
sprintf(txbuf, "PS(%u,%u,%u);\r\n", (unsigned)x, (unsigned)y, (unsigned)color);
Screen_SendCmd(txbuf);
}
void Screen_Line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint8_t color) {
sprintf(txbuf, "PL(%u,%u,%u,%u,%u);\r\n", (unsigned)x1, (unsigned)y1, (unsigned)x2, (unsigned)y2, (unsigned)color);
Screen_SendCmd(txbuf);
}
void Screen_Box(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint8_t color) {
sprintf(txbuf, "BOX(%u,%u,%u,%u,%u);\r\n", (unsigned)x1, (unsigned)y1, (unsigned)x2, (unsigned)y2, (unsigned)color);
Screen_SendCmd(txbuf);
}
void Screen_BoxFill(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint8_t color) {
sprintf(txbuf, "BOXF(%u,%u,%u,%u,%u);\r\n", (unsigned)x1, (unsigned)y1, (unsigned)x2, (unsigned)y2, (unsigned)color);
Screen_SendCmd(txbuf);
}
void Screen_Circle(uint16_t x, uint16_t y, uint16_t r, uint8_t color) {
sprintf(txbuf, "CIR(%u,%u,%u,%u);\r\n", (unsigned)x, (unsigned)y, (unsigned)r, (unsigned)color);
Screen_SendCmd(txbuf);
}
void Screen_CircleFill(uint16_t x, uint16_t y, uint16_t r, uint8_t color) {
sprintf(txbuf, "CIRF(%u,%u,%u,%u);\r\n", (unsigned)x, (unsigned)y, (unsigned)r, (unsigned)color);
Screen_SendCmd(txbuf);
}
void Screen_SetBGColor(uint8_t color) {
sprintf(txbuf, "SBC(%u);\r\n", (unsigned)color);
Screen_SendCmd(txbuf);
}
void Screen_DrawText16V(uint16_t x, uint16_t y, const char *text, uint8_t color) {
sprintf(txbuf, "DCV16(%u,%u,'%s',%u);\r\n", (unsigned)x, (unsigned)y, text, (unsigned)color);
Screen_SendCmd(txbuf);
}
void Screen_DrawText24(uint16_t x, uint16_t y, const char *text, uint8_t color) {
sprintf(txbuf, "DC24(%u,%u,'%s',%u);\r\n", (unsigned)x, (unsigned)y, text, (unsigned)color);
Screen_SendCmd(txbuf);
}
void Screen_DrawText24V(uint16_t x, uint16_t y, const char *text, uint8_t color) {
sprintf(txbuf, "DCV24(%u,%u,'%s',%u);\r\n", (unsigned)x, (unsigned)y, text, (unsigned)color);
Screen_SendCmd(txbuf);
}
void Screen_DrawText32(uint16_t x, uint16_t y, const char *text, uint8_t color) {
sprintf(txbuf, "DC32(%u,%u,'%s',%u);\r\n", (unsigned)x, (unsigned)y, text, (unsigned)color);
Screen_SendCmd(txbuf);
}
void Screen_DrawText32V(uint16_t x, uint16_t y, const char *text, uint8_t color) {
sprintf(txbuf, "DCV32(%u,%u,'%s',%u);\r\n", (unsigned)x, (unsigned)y, text, (unsigned)color);
Screen_SendCmd(txbuf);
}
void Screen_DrawText48(uint16_t x, uint16_t y, const char *text, uint8_t color, uint8_t transparent) {
sprintf(txbuf, "DC48(%u,%u,'%s',%u,%u);\r\n", (unsigned)x, (unsigned)y, text, (unsigned)color, (unsigned)transparent);
Screen_SendCmd(txbuf);
}
void Screen_Button(uint16_t x, uint16_t y, uint16_t w, uint16_t h, const char *label, uint8_t fontColor, uint8_t bgColor, uint8_t pressFlag, uint8_t style) {
sprintf(txbuf, "BTN(%u,%u,%u,%u,'%s',%u,%u,%u,%u);\r\n", (unsigned)x, (unsigned)y, (unsigned)w, (unsigned)h, label, (unsigned)fontColor, (unsigned)bgColor, (unsigned)pressFlag, (unsigned)style);
Screen_SendCmd(txbuf);
}
void Screen_QRCode(uint16_t x, uint16_t y, const char *url) {
sprintf(txbuf, "QRCODE(%u,%u,%s);\r\n", (unsigned)x, (unsigned)y, url);
Screen_SendCmd(txbuf);
}
void Screen_QRCodeEx(uint16_t x, uint16_t y, const char *url, uint16_t size, uint8_t color) {
sprintf(txbuf, "QRCODE(%u,%u,%s,%u,%u);\r\n", (unsigned)x, (unsigned)y, url, (unsigned)size, (unsigned)color);
Screen_SendCmd(txbuf);
}
void Screen_Ver(void) {
sprintf(txbuf, "VER();\r\n");
Screen_SendCmd(txbuf);
}
/* USER CODE BEGIN AdditionalFunctions */
/* 可以在这里扩展更多绘图/控件函数供应用层调用 */
/* USER CODE END AdditionalFunctions */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -34,6 +34,7 @@ void MX_TIM4_Init(void)
/* USER CODE END TIM4_Init 0 */
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
@@ -41,11 +42,20 @@ void MX_TIM4_Init(void)
/* USER CODE END TIM4_Init 1 */
htim4.Instance = TIM4;
htim4.Init.Prescaler = 0;
htim4.Init.Prescaler = 71;
htim4.Init.CounterMode = TIM_COUNTERMODE_UP;
htim4.Init.Period = 65535;
htim4.Init.Period = 99;
htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
if (HAL_TIM_Base_Init(&htim4) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim4, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_Init(&htim4) != HAL_OK)
{
Error_Handler();
@@ -83,10 +93,10 @@ void MX_TIM4_Init(void)
}
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef* tim_pwmHandle)
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
{
if(tim_pwmHandle->Instance==TIM4)
if(tim_baseHandle->Instance==TIM4)
{
/* USER CODE BEGIN TIM4_MspInit 0 */
@@ -117,7 +127,7 @@ void HAL_TIM_MspPostInit(TIM_HandleTypeDef* timHandle)
*/
GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* USER CODE BEGIN TIM4_MspPostInit 1 */
@@ -127,10 +137,10 @@ void HAL_TIM_MspPostInit(TIM_HandleTypeDef* timHandle)
}
void HAL_TIM_PWM_MspDeInit(TIM_HandleTypeDef* tim_pwmHandle)
void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle)
{
if(tim_pwmHandle->Instance==TIM4)
if(tim_baseHandle->Instance==TIM4)
{
/* USER CODE BEGIN TIM4_MspDeInit 0 */