日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當(dāng)前位置:首頁 > 嵌入式 > 嵌入式云IOT技術(shù)圈
[導(dǎo)讀]嵌入式開源項(xiàng)目精選專欄 本專欄由Mculover666創(chuàng)建,主要內(nèi)容為尋找嵌入式領(lǐng)域內(nèi)的優(yōu)質(zhì)開源項(xiàng)目,一是幫助開發(fā)者使用開源項(xiàng)目實(shí)現(xiàn)更多的功能,二是通過這些開源項(xiàng)目,學(xué)習(xí)大佬的代碼及背后的實(shí)現(xiàn)思想,提升自己的代碼水平,和其它專欄相比,本專欄的優(yōu)勢(shì)在于:


嵌入式開源項(xiàng)目精選專欄

本專欄由Mculover666創(chuàng)建,主要內(nèi)容為尋找嵌入式領(lǐng)域內(nèi)的優(yōu)質(zhì)開源項(xiàng)目,一是幫助開發(fā)者使用開源項(xiàng)目實(shí)現(xiàn)更多的功能,二是通過這些開源項(xiàng)目,學(xué)習(xí)大佬的代碼及背后的實(shí)現(xiàn)思想,提升自己的代碼水平,和其它專欄相比,本專欄的優(yōu)勢(shì)在于:

不會(huì)單純的介紹分享項(xiàng)目,還會(huì)包含作者親自實(shí)踐的過程分享,甚至還會(huì)有對(duì)它背后的設(shè)計(jì)思想解讀。

目前本專欄包含的開源項(xiàng)目有:

  • SFUD | 一個(gè)簡(jiǎn)潔實(shí)用的開源項(xiàng)目,幫你輕松搞定SPI Flash
  • cJSON | 一個(gè)輕量級(jí)C語言JSON解析器
  • paho | 支持10種語言編寫mqtt客戶端,總有一款適合你!
  • MultiButton | 一個(gè)小巧簡(jiǎn)單易用的事件驅(qū)動(dòng)型按鍵驅(qū)動(dòng)模塊
  • letter-shell | 一個(gè)功能強(qiáng)大的嵌入式shell

如果您自己編寫或者發(fā)現(xiàn)的開源項(xiàng)目不錯(cuò),歡迎留言或者私信投稿到本專欄,分享獲得雙倍的快樂!

1. EasyLogger

本期給大家?guī)淼拈_源項(xiàng)目是 EasyLogger,一款輕量級(jí)且高性能的日志庫,作者armink,目前收獲 1.1K 個(gè) star,遵循 MIT 開源許可協(xié)議。

EasyLogger 是一款超輕量級(jí)、高性能的 C/C++ 日志庫,非常適合對(duì)資源敏感的軟件項(xiàng)目,相比之下, EasyLogger 的功能更加簡(jiǎn)單,提供給用戶的接口更少,上手會(huì)更快,更多實(shí)用功能支持以插件形式進(jìn)行動(dòng)態(tài)擴(kuò)展。

目前EasyLogger支持以下功能:

  • 日志輸出方式支持串口、Flash、文件等;
  • 日志內(nèi)容可包含級(jí)別、時(shí)間戳、線程信息、進(jìn)程信息等;
  • 支持多種操作系統(tǒng),支持裸機(jī);
  • 各級(jí)別日志支持不同顏色顯示;

項(xiàng)目地址:https://github.com/armink/EasyLogger

2. 移植EasyLogger

2.1. 移植思路

在移植過程中主要參考兩個(gè)資料:項(xiàng)目的readme文檔和demo工程。

對(duì)于這些開源項(xiàng)目,其實(shí)移植起來也就兩步:

  • ① 添加源碼到裸機(jī)工程中;
  • ② 實(shí)現(xiàn)需要的接口即可;

2.2. 準(zhǔn)備裸機(jī)工程

本文中我使用的是小熊派IoT開發(fā)套件,主控芯片為STM32L431RCT6:移植之前需要準(zhǔn)備一份裸機(jī)工程,我使用STM32CubeMX生成,使用USART1的查詢方式發(fā)送數(shù)據(jù),并將printf重定向到USART1,具體過程請(qǐng)參考:

  • STM32CubeMX_06 | 使用USART發(fā)送和接收數(shù)據(jù)(查詢模式)
  • STM32CubeMX_09 | 重定向printf函數(shù)到串口輸出的多種方法

串口USART1配置如下:生成工程后printf重定向代碼如下:

#include <stdio.h>

int fputc(int ch, FILE *stream)
{
    /* 堵塞判斷串口是否發(fā)送完成 */
    while((USART1->ISR & 0X40) == 0);

    /* 串口發(fā)送完成,將該字符發(fā)送 */
    USART1->TDR = (uint8_t) ch;

    return ch;
}

裸機(jī)工程準(zhǔn)備好之后開始移植easylogger。

2.3. 添加elog到工程中

① 復(fù)制源碼到工程中:② 在keil中添加easylogger組件的源碼文件:

  • port/elog_port.c:elog移植接口文件;
  • src/elog.c:elog核心功能源碼;
  • src/elog_utils.c:elog所用到的一些c庫工具函數(shù)實(shí)現(xiàn);
  • src/elog_buf.c(可選添加):elog緩沖輸出模式源碼;
  • src/elog_async.c(可選添加):elog異步輸出模式源碼;

③ 將easylogger/inc頭文件路徑添加到keil中:

2.4. 實(shí)現(xiàn)elog移植接口

elog的移植接口都已經(jīng)寫好了,在elog_port.c文件中,只需要在函數(shù)體中添加代碼即可。

① elog初始化接口

ElogErrCode elog_port_init(void);

如果涉及到后續(xù)elog使用資源的初始化,比如動(dòng)態(tài)申請(qǐng)分配緩沖區(qū)內(nèi)存,可以放在此接口中,本文中保持默認(rèn)。

② elog日志輸出接口(重點(diǎn))

//開頭添加
#include <stdio.h>

……

//接口實(shí)現(xiàn)
void elog_port_output(const char *logsize_t size) {
 //日志使用printf輸出,printf已經(jīng)重定向到串口USART1
 printf("%.*s", size, log);
}

這兒有個(gè)小知識(shí)點(diǎn),%s表示字符串輸出,.<十進(jìn)制數(shù)>是精度控制格式符,輸出字符時(shí)表示輸出字符的位數(shù),在精度控制時(shí),小數(shù)點(diǎn)后的十進(jìn)制數(shù)可以使用*來占位,在后面提供一個(gè)變量作為精度控制的具體值。

③ 日志輸出上鎖/解鎖接口

該接口可以對(duì)日志輸出接口進(jìn)行上鎖/解鎖,以保證日志在并發(fā)輸出時(shí)的正確性,本文中使用的是裸機(jī)程序,所以在此使用關(guān)閉全局中斷來加鎖,打開全局中斷來解鎖:

//開頭添加
#include <stm32l4xx_hal.h>

……

//接口實(shí)現(xiàn)
void elog_port_output_lock(void) {
    
    //關(guān)閉全局中斷
 __set_PRIMASK(1);
  
}
void elog_port_output_unlock(void) {
    
    //開啟全局中斷
 __set_PRIMASK(0);
    
}

STM32開關(guān)全局中斷的方式很多,本文中直接操作 PRIMASK 寄存器來快速的屏蔽/打開全局中斷,參考文章:

https://blog.csdn.net/working24hours/article/details/88323241

④ 系統(tǒng)信息獲取接口

elog提供了三個(gè)接口用來獲取當(dāng)前時(shí)間、獲取進(jìn)程號(hào)、獲取線程號(hào),因?yàn)楸疚闹幸浦驳铰銠C(jī)工程中,并且沒有提供時(shí)間支持,所以這三個(gè)接口都返回空字符串,如下:

const char *elog_port_get_time(void) {
    
 return "";
    
}
const char *elog_port_get_p_info(void) {

 return "";
    
}
const char *elog_port_get_t_info(void) {

 return "";
    
}

2.5. 配置elog

elog的核心功能開啟宏定義和核心參數(shù)宏定義都在配置文件elog_cfg.h中,在本文中只講述其中重要的宏定義。

日志輸出總開關(guān):

/* enable log output. */
#define ELOG_OUTPUT_ENABLE

換行符宏定義修改如下:

/* output newline sign */
#define ELOG_NEWLINE_SIGN                        "\r\n"

帶有顏色的日志輸出開關(guān):

/* enable log color */
#define ELOG_COLOR_ENABLE

移植時(shí)并沒有添加異步輸出和緩沖區(qū)輸出的源碼,所以將這兩個(gè)功能關(guān)掉:至此,移植配置完成,接下來可以開始愉快的使用啦!

3. 使用easylogger

3.1. 初始化elog

elog使用之前需要初始化,過程有三步:① 初始化elog

ElogErrCode elog_init(void);

② 設(shè)置日志輸出格式

void elog_set_fmt(uint8_t level, size_t set);

其中第一個(gè)參數(shù)表示設(shè)置哪個(gè)日志輸出級(jí)別對(duì)應(yīng)的輸出格式,從以下宏定義中選擇一個(gè):

/* 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

其二個(gè)參數(shù)是日志輸出格式,枚舉給出,可以自由組合搭配:

/* 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)

③ 啟動(dòng)elog

void elog_start(void);

接下來在main函數(shù)中的usart1初始化函數(shù)之后,while(1)之前編寫elog初始化代碼:

/* USER CODE BEGIN 2 */
/* 初始化elog */
elog_init();

/* 設(shè)置每個(gè)級(jí)別的日志輸出格式 */
//輸出所有內(nèi)容
elog_set_fmt(ELOG_LVL_ASSERT, ELOG_FMT_ALL);
//輸出日志級(jí)別信息和日志TAG
elog_set_fmt(ELOG_LVL_ERROR, ELOG_FMT_LVL | ELOG_FMT_TAG);
elog_set_fmt(ELOG_LVL_WARN, ELOG_FMT_LVL | ELOG_FMT_TAG);
elog_set_fmt(ELOG_LVL_INFO, ELOG_FMT_LVL | ELOG_FMT_TAG);
//除了時(shí)間、進(jìn)程信息、線程信息之外,其余全部輸出
elog_set_fmt(ELOG_LVL_DEBUG, ELOG_FMT_ALL & ~(ELOG_FMT_TIME | ELOG_FMT_P_INFO | ELOG_FMT_T_INFO));
//輸出所有內(nèi)容
elog_set_fmt(ELOG_LVL_VERBOSE, ELOG_FMT_ALL);

/* 啟動(dòng)elog */
elog_start();

/* USER CODE END 2 */

3.2. elog日志輸出

elog中每種級(jí)別都有一種完整方式,兩種簡(jiǎn)化方式,使用時(shí)自行選擇:

#define elog_assert(tag, ...) 
#define elog_a(tag, ...) //簡(jiǎn)化方式1,每次需填寫 LOG_TAG
#define log_a(...)       //簡(jiǎn)化方式2,LOG_TAG 在文件頂部定義,使用前無需填寫 LOG_TAG

#define elog_error(tag, ...)
#define elog_e(tag, ...)
#define log_e(...)

#define elog_warn(tag, ...)
#define elog_w(tag, ...)
#define log_w(...)

#define elog_info(tag, ...)
#define elog_i(tag, ...)
#define log_i(...)

#define elog_debug(tag, ...)
#define elog_d(tag, ...)
#define log_d(...)

#define elog_verbose(tag, ...)
#define elog_v(tag, ...)
#define log_v(...)

前兩種在使用的時(shí)候只需要包含<elog.h>頭文件即可,第三種方式除了包含頭文件之外,還需要在文件開始定義TAG宏定義,使用起來和printf相同,所以這里我使用第三種方法演示。

首先在main.c文件開始定義TAG宏,包含頭文件:

/* USER CODE BEGIN Includes */
#define LOG_TAG    "main"

#include <elog.h>

/* USER CODE END Includes */

然后在main函數(shù)中編寫的elog初始化代碼之后,繼續(xù)添加代碼,測(cè)試elog的使用:

log_a("Hello EasyLogger!");
log_e("Hello EasyLogger!");
log_w("Hello EasyLogger!");
log_i("Hello EasyLogger!");
log_d("Hello EasyLogger!");
log_v("Hello EasyLogger!");

編譯,燒寫,使用串口終端(Mobaxterm)查看串口輸出:

3.3. 五彩繽紛的輸出

要想五彩繽紛的日志,僅在elog_cfg.h中使能顏色輸出還不夠,還需要使用API開啟輸出:

void elog_set_text_color_enabled(bool enabled);

在初始化elog的時(shí)候使能文字顏色輸出:再次編譯、下載、查看輸出:每個(gè)級(jí)別日志的前景色、背景色、字體都可以在elog_cfg.h中修改宏定義,宏定義的值在elog.c中給出,可自行查看,比如這里我將ERROR級(jí)別的日志修改為閃爍字體:編譯、下載、查看輸出:

3.4. 移植前后內(nèi)存占用情況

移植前的裸機(jī)工程只具有usart1收發(fā)功能,移植easylogger之后兩者內(nèi)存對(duì)比如下:

3.5. elog的高級(jí)功能

elog除了基本的日志功能之外,還提供了一些高級(jí)功能,比如:

  • 日志輸出過濾功能:可以按級(jí)別、TAG、關(guān)鍵詞過濾日志;
  • 緩沖輸出模式;
  • 異步輸出模式;

這些功能如何使用,在項(xiàng)目的readme文檔中講述的很詳細(xì),本文限于篇幅,這些高級(jí)功能不詳細(xì)講述,如有興趣深入,可以自行研究。

4. 設(shè)計(jì)思想解讀

4.1. 數(shù)據(jù)加工

使用日志打印組件與使用printf最基本的區(qū)別在于:輸出了更多有利于調(diào)試的信息,可以理解為對(duì)輸出數(shù)據(jù)進(jìn)行了一次加工。

打印語句所在文件、函數(shù)名、行號(hào)這些信息是利用了編譯器內(nèi)置宏的功能:

  • __FILE__:文件名
  • __FUNCTION__:函數(shù)名
  • __LINE__:行號(hào)

而在終端中輸出有顏色的字符則是利用了ANSI escape code,即Escape 序列屏幕控制碼,關(guān)于這兩個(gè)知識(shí)點(diǎn)詳細(xì)的解釋和示例請(qǐng)閱讀:

  • 編譯器宏詳解
  • ANSI escape code詳解

在elog中對(duì)輸出內(nèi)容進(jìn)行加工處理的函數(shù)為:

/**
 * 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, ...) ;

4.2. 日志輸出模式

俗話說,師傅領(lǐng)進(jìn)門,修行在個(gè)人,本文所講述的只是日志打印組件的基本功能,使用printf直接實(shí)現(xiàn)日志輸出接口,所以在日志輸出模式上和使用printf輸出沒有區(qū)別,只不過多了些信息。

elog支持異步輸出模式,開啟異步輸出模式后,將會(huì)提升用戶應(yīng)用程序的執(zhí)行效率。應(yīng)用程序在進(jìn)行日志輸出時(shí),無需等待日志徹底輸出完成,即可直接返回。

elog也支持緩沖輸出模式,開啟緩沖輸出模式后,如果緩沖區(qū)不滿,用戶線程在進(jìn)行日志輸出時(shí),無需等待日志徹底輸出完成,即可直接返回。但當(dāng)日志緩沖區(qū)滿以后,將會(huì)占用用戶線程,自動(dòng)將緩沖區(qū)中的日志全部輸出干凈。

這兩種無需等待,直接返回的日志輸出模式,在打印大量日志信息的時(shí)候非常重要,打印日志的代碼對(duì)正常應(yīng)用程序的影響越小越好,本文不再講述,還請(qǐng)讀者自行研究。

5. 項(xiàng)目工程源碼獲取和問題交流

目前我將Easylogger源碼、我移植到小熊派STM32L431RCT6開發(fā)板的工程源碼上傳到了QQ群里(包含好幾份HAL庫,QQ相對(duì)速度快點(diǎn)),可以在QQ群里下載,有問題也可以在群里交流,當(dāng)然也歡迎大家分享出來自己移植的工程到QQ群里

放上QQ群二維碼:

接收更多精彩文章及資源推送,歡迎訂閱我的微信公眾號(hào):『mculover666』。

免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問題,請(qǐng)聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅(qū)動(dòng)電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: 驅(qū)動(dòng)電源

在工業(yè)自動(dòng)化蓬勃發(fā)展的當(dāng)下,工業(yè)電機(jī)作為核心動(dòng)力設(shè)備,其驅(qū)動(dòng)電源的性能直接關(guān)系到整個(gè)系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動(dòng)勢(shì)抑制與過流保護(hù)是驅(qū)動(dòng)電源設(shè)計(jì)中至關(guān)重要的兩個(gè)環(huán)節(jié),集成化方案的設(shè)計(jì)成為提升電機(jī)驅(qū)動(dòng)性能的關(guān)鍵。

關(guān)鍵字: 工業(yè)電機(jī) 驅(qū)動(dòng)電源

LED 驅(qū)動(dòng)電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個(gè)照明設(shè)備的使用壽命。然而,在實(shí)際應(yīng)用中,LED 驅(qū)動(dòng)電源易損壞的問題卻十分常見,不僅增加了維護(hù)成本,還影響了用戶體驗(yàn)。要解決這一問題,需從設(shè)計(jì)、生...

關(guān)鍵字: 驅(qū)動(dòng)電源 照明系統(tǒng) 散熱

根據(jù)LED驅(qū)動(dòng)電源的公式,電感內(nèi)電流波動(dòng)大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關(guān)鍵字: LED 設(shè)計(jì) 驅(qū)動(dòng)電源

電動(dòng)汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產(chǎn)業(yè)的重要發(fā)展方向。電動(dòng)汽車的核心技術(shù)之一是電機(jī)驅(qū)動(dòng)控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機(jī)驅(qū)動(dòng)系統(tǒng)中的關(guān)鍵元件,其性能直接影響到電動(dòng)汽車的動(dòng)力性能和...

關(guān)鍵字: 電動(dòng)汽車 新能源 驅(qū)動(dòng)電源

在現(xiàn)代城市建設(shè)中,街道及停車場(chǎng)照明作為基礎(chǔ)設(shè)施的重要組成部分,其質(zhì)量和效率直接關(guān)系到城市的公共安全、居民生活質(zhì)量和能源利用效率。隨著科技的進(jìn)步,高亮度白光發(fā)光二極管(LED)因其獨(dú)特的優(yōu)勢(shì)逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關(guān)鍵字: 發(fā)光二極管 驅(qū)動(dòng)電源 LED

LED通用照明設(shè)計(jì)工程師會(huì)遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關(guān)鍵字: LED 驅(qū)動(dòng)電源 功率因數(shù)校正

在LED照明技術(shù)日益普及的今天,LED驅(qū)動(dòng)電源的電磁干擾(EMI)問題成為了一個(gè)不可忽視的挑戰(zhàn)。電磁干擾不僅會(huì)影響LED燈具的正常工作,還可能對(duì)周圍電子設(shè)備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關(guān)鍵字: LED照明技術(shù) 電磁干擾 驅(qū)動(dòng)電源

開關(guān)電源具有效率高的特性,而且開關(guān)電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機(jī)重量也有所下降,所以,現(xiàn)在的LED驅(qū)動(dòng)電源

關(guān)鍵字: LED 驅(qū)動(dòng)電源 開關(guān)電源

LED驅(qū)動(dòng)電源是把電源供應(yīng)轉(zhuǎn)換為特定的電壓電流以驅(qū)動(dòng)LED發(fā)光的電壓轉(zhuǎn)換器,通常情況下:LED驅(qū)動(dòng)電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: LED 隧道燈 驅(qū)動(dòng)電源
關(guān)閉