#技術資源# flow_lib
一,介紹:
適用于嵌入式單片機的裸機程式微庫,只占用你的rom 6個位元組,是的,6個位元組。顛覆式的設計思維,讓你寫代碼的時候像flow(流水)一樣絲滑,讓你永遠不用在為delay時cpu空轉而煩惱,附加的超輕便的軟體定時器讓你輕松實作各種定時需求,另還有信號量的配方,讓你任務間的同步像詩一樣寫意,并且能讓你裸機程式效率提升百倍以上。
Gitee開源:https://gitee.com/qq791314247/flow_lib
Github開源:https://github.com/791314247/flow_lib
CSDN博客:https://blog.csdn.net/qq_35333978/article/details/112428159
二,移植說明:
移植特別簡單,flow_def.h有一個全域變數:
extern unsigned long flow_tick;
把這個變數放在你的某個硬體中斷里去,這個硬體中斷一定要是一直運行的,推薦RTC半秒中斷,或者systick中斷都可以。
然后在flow.h里的第一行有個宏
#define FL_HARD_TICK (500) /* 系統硬體中斷一次所需要的時間,單位ms */
把這里的值改成你的硬體中斷一次所需的時間,單位是毫秒,比如你的flow_tick放在了一個500ms中斷一次的rtc里,那么這里的宏FL_HARD_TICK的值就是500,具體中斷設為多少取決于你的系統最短一次的延時的時間。
假如我的最短延時需求是100ms,那么我就得給個100ms中斷一次的硬體中斷源,宏FL_HARD_TICK的值就是100,我就可以這樣使用:
FL_LOCK_DELAY(fl, FL_CLOCK_SEC /10);
來延時100ms。
三,使用說明:
核心檔案時flow.h,看這里的注釋基本就會使用大部分功能。
/*
* Copyright (c) 2006-2018
*
* SPDX-License-Identifier:
*
* Change Logs:
* Date Author Notes
* 2020 wangrui
*/
#ifndef __FLOW_
#define __FLOW_
#include <flow_def.h>
#include <flow_core.h>
#include <flow_sem.h>
#define FL_HARD_TICK (500) /* 系統硬體中斷一次所需要的時間,單位ms */
#define FL_CLOCK_SEC (1000/FL_HARD_TICK) /* 一秒鐘需要的tick,可以除也可以自行添加其它宏 */
/**
* 初始化一個flow行程
*/
#define FL_INIT(fl) FLOW_INIT(fl)
/**
* flow頭,必須放在函式內的最前面
*/
#define FL_HEAD(fl) FLOW_HEAD(fl)
/**
* flow尾,必須放在函式內的最后面
*/
#define FL_TAIL(fl) FLOW_TAIL(fl)
/**
* 給行程加鎖,直到judge為真,加鎖期間一直放開cpu給其他行程使用
*/
#define FL_LOCK_WAIT(fl, judge) FLOW_LOCK_WAIT(fl, judge)
/**
* 如果judge為真,就一直給行程加鎖,加鎖期間一直放開cpu給其他行程使用
*/
#define FL_LOCK_WHILE(fl, judge) FLOW_LOCK_WHILE(fl, judge)
/**
* 退出該行程
*/
#define FL_EXIT(fl) FLOW_EXIT(fl)
/**
* 無條件鎖住行程一次,下次進來再接著往下運行
*/
#define FL_LOCK_ONCE(fl) FLOW_LOCK_ONCE(fl)
/**
* 等待一個flow行程結束
*/
#define FL_WAIT_PROCESS_END(fl, process) FLOW_WAIT_PROCESS_END(fl, process)
/**
* 等待一個flow子行程結束
*/
#define FL_WAIT_CHILD(fl, cfl, process) FLOW_WAIT_CHILD_PROCESS_END(fl, cfl, process)
/**
* 給行程加鎖,時長為time,加鎖期間一直放開cpu給其他行程使用,time如果用FL_CLOCK_SEC來乘,那么time的單位就是s
* 此處time必須是常數
*/
#define FL_LOCK_DELAY(fl,time) FLOW_LOCK_DELAY(fl,time)
/**
* 給行程加鎖,時長為time,延時期間如果judge為真,就直接解鎖行程
* 此處time必須是常數
*/
#define FL_LOCK_DELAY_OR_WAIT(fl,judge,time) FLOW_LOCK_DELAY_OR_WAIT(fl,judge,time)
/**
* 初始化一個信號量
*/
#define FL_SEM_INIT(sem, count) FLOW_SEM_INIT(sem, count)
/**
* 給行程加鎖,直到有信號釋放
*/
#define FL_LOCK_WAIT_SEM(f, sem) FLOW_LOCK_WAIT_SEM(f, sem)
/**
* 給行程加鎖,直到有信號或者超時,此處time可以為變數,其他的介面處time必須是常數
*/
#define FL_LOCK_WAIT_SEM_OR_TIMEOUT(fl, sem, time) FLOW_LOCK_WAIT_SEM_OR_TIMEOUT(fl, sem, time)
/**
* 釋放一個信號量
*/
#define FL_SEM_RELEASE(sem) FLOW_SEM_RELEASE(sem)
/**
* 初始化一個軟體定時器
*/
void fl_timer_set(struct flow_timer *t, unsigned long interval);
/**
* 復位一個軟體定時器
*/
void fl_timer_reset(struct flow_timer *t);
/**
* 重啟一個軟體定時器
*/
void fl_timer_restart(struct flow_timer *t);
/**
* 檢測一個軟體定時器是否超時,0為不超時,1為超時
*/
char fl_timer_timeout(struct flow_timer *t);
/**
* 檢測一個軟體定時器還剩多少時間超時,單位為硬體tick,比如硬體tick 500ms中斷一次,那么
* 回傳的時間單位就是500ms
*/
unsigned long fl_hour_much_time(struct flow_timer *t);
#endif /* __FLOW_ */
簡單舉個例子,先從需求說起,假如說你現在需要一個函式,這個函式的功能是每隔1s讓你的led亮一次,正常設計的要么起個軟體定時器或者硬體定時器,甚至狀態機可以實作需求,但是都太low了,讓我們看一下如何用flow庫來實作這個函式。
該函式格式如下:
char led_flash(struct flow *fl)
{}
其中char、struct flow *fl是必備的。
再來看看函式里面的內容格式:
char led_flash(struct flow *fl)
{
FL_HEAD(fl);
FL_TAIL(fl);
}
函式里面的FL_HEAD和FL_TAIL是使用flow庫的所必須的宏,FL_HEAD(fl)放到函式的最前面,如果你的函式內部有變數定義的話放在變數定義的后面。而FL_TAIL(fl)是放在函式最后面一行的。
基本格式有了,再來看下如何實作延時一秒呢?其實只用一個陳述句就OK。
char led_flash(struct flow *fl)
{
FL_HEAD(fl);
FL_LOCK_DELAY(fl, FL_CLOCK_SEC * 1);
led_open();
FL_LOCK_DELAY(fl, FL_CLOCK_SEC * 1);
led_close();
FL_TAIL(fl);
}
是的,你沒看錯,僅僅只需要FL_LOCK_DELAY(fl, FL_CLOCK_SEC * 1)這一個陳述句就OK,當執行到這個陳述句的時候該函式就會讓出CPU權限,當延時時間到了之后,就會回來接著執行FL_LOCK_DELAY(fl, FL_CLOCK_SEC * 1)下面的陳述句。一直到FL_TAIL(fl),該函式就會結束任務,再也不會執行了,那么如果我們想讓它一直回圈執行呢?看下面:
char led_flash(struct flow *fl)
{
FL_HEAD(fl);
while(1)
{
FL_LOCK_DELAY(fl, FL_CLOCK_SEC * 1);
led_open();
FL_LOCK_DELAY(fl, FL_CLOCK_SEC * 1);
led_close();
}
FL_TAIL(fl);
}
看起來像不像個行程?其實也有點作業系統的樣子了。。。
光有這個函式也不行,還得進行一些額外的操作
比如:
static struct flow fl_led; /* 1,定義一個struct flow變數給這個函式使用 */
static char led_flash(struct flow *fl)
{
FL_HEAD(fl);
while(1)
{
FL_LOCK_DELAY(fl, FL_CLOCK_SEC * 1);
led_open();
FL_LOCK_DELAY(fl, FL_CLOCK_SEC * 1);
led_close();
}
FL_TAIL(fl);
}
int main(void)
{
FL_INIT(&fl_led); /* 2,初始化struct flow變數 */
while(1)
{
led_flash(&fl_led); /* 3,把led_flash行程放在main函式的while回圈里 */
...
}
return 0;
}
經過以上3步,就可以實作行程之間的切換啦。然后想根據某個條件來鎖住執行緒釋放CPU的話,可以把里面的
FL_LOCK_DELAY(fl, FL_CLOCK_SEC * 1);
換成
FL_LOCK_WAIT(fl, judge);
當里面的judge為假時執行緒就一直鎖住在這一行陳述句,當judge為真時就可以往下執行啦。同理可以完成很多其他的神奇功能,讓你的cpu再也不空轉啦,具體請看flow.h檔案。。。。
這個版本暫時先寫這么多,先看看example.c。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/247449.html
標籤:單片機/工控
下一篇:[求助]宏定義讀取埠狀態錯誤
